Skip to content

Commit 6e5ac35

Browse files
authored
fix(GAT-9356): Form hydration causing error on save as draft (#1595)
1 parent 2901768 commit 6e5ac35

3 files changed

Lines changed: 87 additions & 13 deletions

File tree

src/consts/createDataset.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ const INITIAL_FORM_SECTION = "Welcome and form builder";
22
const SUBMISSON_FORM_SECTION = "Make active";
33
const STRUCTURAL_METADATA_FORM_SECTION = "structuralMetadata";
44
const DATASET_TYPE = "Dataset type";
5+
const DATASET_TYPE_ARRAY = "Dataset Type Array";
6+
const DATASET_SUBTYPES = "Dataset subtypes";
7+
const PROVENANCE_ORIGIN_DATASET_TYPE_PATH = "provenance.origin.datasetType";
58
const DATA_CUSTODIAN_ID = "identifier";
69
const DATA_CUSTODIAN_NAME = "Name of Data Custodian";
710
const PATIENT_PATHWAY_DESCRIPTION = "Patient pathway description";
@@ -18,6 +21,9 @@ export {
1821
SUBMISSON_FORM_SECTION,
1922
STRUCTURAL_METADATA_FORM_SECTION,
2023
DATASET_TYPE,
24+
DATASET_TYPE_ARRAY,
25+
DATASET_SUBTYPES,
26+
PROVENANCE_ORIGIN_DATASET_TYPE_PATH,
2127
DATA_CUSTODIAN_ID,
2228
DATA_CUSTODIAN_NAME,
2329
DATA_CUSTODIAN_FIELDS,

src/utils/formHydration.test.tsx

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
import { buildYup } from "schema-to-yup";
2-
import { FormHydrationValidation } from "@/interfaces/FormHydration";
2+
import { Metadata } from "@/interfaces/Dataset";
3+
import {
4+
FormHydration,
5+
FormHydrationValidation,
6+
} from "@/interfaces/FormHydration";
37
import {
48
formGenerateLegendItems,
59
formGetFieldsCompletedCount,
610
generateValidationRules,
11+
mapFormFieldsForSubmission,
712
} from "./formHydration";
813

914
const buildYupSchema = (validationFields: FormHydrationValidation[]) =>
@@ -118,9 +123,9 @@ describe("generateValidationRules", () => {
118123
it("rejects a non-URL value in an optional url-format array field", () => {
119124
const schema = buildYupSchema(toolsValidation);
120125

121-
expect(() =>
122-
schema.validateSync({ Tools: ["das"] })
123-
).toThrow(/must be a valid URL/);
126+
expect(() => schema.validateSync({ Tools: ["das"] })).toThrow(
127+
/must be a valid URL/
128+
);
124129
});
125130

126131
it("accepts a valid URL in an optional url-format array field", () => {
@@ -154,9 +159,66 @@ describe("generateValidationRules", () => {
154159
const schema = buildYupSchema(requiredEnumValidation);
155160

156161
expect(() => schema.validateSync({ Category: [] })).toThrow();
157-
expect(() =>
158-
schema.validateSync({ Category: ["A"] })
159-
).not.toThrow();
162+
expect(() => schema.validateSync({ Category: ["A"] })).not.toThrow();
163+
});
164+
});
165+
166+
describe("mapFormFieldsForSubmission", () => {
167+
// A minimal schema for a single field that lives outside the provenance
168+
// section, so a "partial draft" produces formattedFormData with no
169+
// provenance branch at all - the exact condition that used to throw.
170+
const schema = [
171+
{
172+
title: "Title",
173+
is_array_form: false,
174+
location: "summary.title",
175+
field: {
176+
component: "TextField",
177+
name: "Title",
178+
required: true,
179+
hidden: false,
180+
},
181+
},
182+
] as unknown as FormHydration[];
183+
184+
const submit = (formData: Record<string, unknown>) =>
185+
mapFormFieldsForSubmission(formData as unknown as Metadata, schema) as {
186+
provenance?: { origin?: { datasetType?: unknown } };
187+
};
188+
189+
it("does not throw when the provenance section is empty (partial draft)", () => {
190+
expect(() => submit({ Title: "A partial draft" })).not.toThrow();
191+
});
192+
193+
it("defaults datasetType to an empty array when Dataset Type Array is absent", () => {
194+
const result = submit({ Title: "A partial draft" });
195+
196+
expect(result.provenance?.origin?.datasetType).toEqual([]);
197+
});
198+
199+
it("maps Dataset Type Array into provenance.origin.datasetType when provenance is otherwise empty", () => {
200+
const result = submit({
201+
"Dataset Type Array": [
202+
{
203+
"Dataset type": "Health and disease",
204+
"Dataset subtypes": ["Cancer"],
205+
},
206+
],
207+
});
208+
209+
expect(result.provenance?.origin?.datasetType).toEqual([
210+
{ name: "Health and disease", subTypes: ["Cancer"] },
211+
]);
212+
});
213+
214+
it("defaults subTypes to an empty array when Dataset subtypes is missing", () => {
215+
const result = submit({
216+
"Dataset Type Array": [{ "Dataset type": "Health and disease" }],
217+
});
218+
219+
expect(result.provenance?.origin?.datasetType).toEqual([
220+
{ name: "Health and disease", subTypes: [] },
221+
]);
160222
});
161223
});
162224

src/utils/formHydration.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ import { LegendItem, LegendStatus } from "@/interfaces/FormLegend";
1919
import InputWrapper from "@/components/InputWrapper";
2020
import { inputComponents } from "@/config/forms";
2121
import {
22+
DATASET_SUBTYPES,
23+
DATASET_TYPE,
24+
DATASET_TYPE_ARRAY,
2225
INITIAL_FORM_SECTION,
26+
PROVENANCE_ORIGIN_DATASET_TYPE_PATH,
2327
SUBMISSON_FORM_SECTION,
2428
} from "@/consts/createDataset";
2529
import { getLastSplitPart } from "./string";
@@ -462,12 +466,14 @@ const mapFormFieldsForSubmission = (
462466
set(formattedFormData, key, value);
463467
});
464468

465-
formattedFormData.provenance.origin.datasetType = formData[
466-
"Dataset Type Array"
467-
].map(item => ({
468-
name: item["Dataset type"],
469-
subTypes: item["Dataset subtypes"] ?? [],
470-
}));
469+
set(
470+
formattedFormData,
471+
PROVENANCE_ORIGIN_DATASET_TYPE_PATH,
472+
(formData[DATASET_TYPE_ARRAY] ?? []).map(item => ({
473+
name: item[DATASET_TYPE],
474+
subTypes: item[DATASET_SUBTYPES] ?? [],
475+
}))
476+
);
471477
const cleanUndefinedObjects = (
472478
obj: Record<string, unknown>
473479
): Record<string, unknown> | undefined => {

0 commit comments

Comments
 (0)