diff --git a/app/routes/shared/formular.server.ts b/app/routes/shared/formular.server.ts index fa5e5dea9..c976f88d8 100644 --- a/app/routes/shared/formular.server.ts +++ b/app/routes/shared/formular.server.ts @@ -40,6 +40,7 @@ import { updateMainSession } from "~/services/session.server/updateSessionInHead import { validateFormData } from "~/services/validation/validateFormData.server"; import { getButtonNavigationProps } from "~/util/buttonProps"; import { interpolateDeep } from "~/util/fillTemplate"; +import { filterFormData } from "~/util/filterFormData"; const structureCmsContent = ( formPageContent: z.infer, @@ -214,11 +215,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { const cookieHeader = request.headers.get("Cookie"); const flowSession = await getSession(cookieHeader); const formData = await request.formData(); - - // Note: This also reduces same-named fields to the last entry - const relevantFormData = Object.fromEntries( - Array.from(formData.entries()).filter(([key]) => !key.startsWith("_")), - ); + const relevantFormData = filterFormData(formData); if (formData.get("_action") === "delete") { try { diff --git a/app/routes/shared/vorabcheck.server.ts b/app/routes/shared/vorabcheck.server.ts index e2ad682a9..302b5e8d9 100644 --- a/app/routes/shared/vorabcheck.server.ts +++ b/app/routes/shared/vorabcheck.server.ts @@ -27,6 +27,7 @@ import { updateMainSession } from "~/services/session.server/updateSessionInHead import { validateFormData } from "~/services/validation/validateFormData.server"; import { getButtonNavigationProps } from "~/util/buttonProps"; import { interpolateDeep } from "~/util/fillTemplate"; +import { filterFormData } from "~/util/filterFormData"; export const loader = async ({ params, @@ -135,11 +136,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { const flowSession = await sessionManager.getSession(cookieHeader); const formData = await request.formData(); - // Note: This also reduces same-named fields to the last entry - const relevantFormData = Object.fromEntries( - Array.from(formData.entries()).filter(([key]) => !key.startsWith("_")), - ); - + const relevantFormData = filterFormData(formData); const validationResult = await validateFormData(flowId, relevantFormData); if (validationResult.error) return validationError( diff --git a/app/util/__test__/filterFormData.test.ts b/app/util/__test__/filterFormData.test.ts new file mode 100644 index 000000000..691874352 --- /dev/null +++ b/app/util/__test__/filterFormData.test.ts @@ -0,0 +1,24 @@ +import { filterFormData } from "../filterFormData"; + +describe("filterFormData", () => { + it("creates a object with data", () => { + const formData = new FormData(); + formData.append("a", "1"); + formData.append("b", "2"); + expect(filterFormData(formData)).toEqual({ a: "1", b: "2" }); + }); + + it("filters out entries starting with underscore", () => { + const formData = new FormData(); + formData.append("a", "1"); + formData.append("_b", "2"); + expect(filterFormData(formData)).toEqual({ a: "1" }); + }); + + it("filters out repeated entries", () => { + const formData = new FormData(); + formData.append("a", "1"); + formData.append("a", "2"); + expect(filterFormData(formData)).toEqual({ a: "2" }); + }); +}); diff --git a/app/util/filterFormData.ts b/app/util/filterFormData.ts new file mode 100644 index 000000000..be6b7a9cf --- /dev/null +++ b/app/util/filterFormData.ts @@ -0,0 +1,5 @@ +export const filterFormData = (formData: FormData) => + // Note: fromEntries() reduces same-named form fields to the last one + Object.fromEntries( + Array.from(formData.entries()).filter(([key]) => !key.startsWith("_")), + );