@fogpipe/forma-react 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -61
- package/dist/index.js +36 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/ErrorBoundary.tsx +14 -7
- package/src/FieldRenderer.tsx +3 -1
- package/src/FormRenderer.tsx +3 -1
- package/src/__tests__/FieldRenderer.test.tsx +128 -1
- package/src/__tests__/FormRenderer.test.tsx +54 -0
- package/src/__tests__/canProceed.test.ts +141 -100
- package/src/__tests__/diabetes-trial-flow.test.ts +235 -66
- package/src/__tests__/null-handling.test.ts +27 -8
- package/src/__tests__/optionVisibility.test.tsx +199 -58
- package/src/__tests__/test-utils.tsx +26 -7
- package/src/__tests__/useForma.test.ts +244 -73
- package/src/context.ts +3 -1
- package/src/index.ts +6 -1
- package/src/types.ts +58 -14
- package/src/useForma.ts +31 -3
|
@@ -79,31 +79,90 @@ function createDiabetesTrialSpec(): Forma {
|
|
|
79
79
|
},
|
|
80
80
|
fields: {
|
|
81
81
|
studyName: { type: "text", label: "Study Name", enabledWhen: "false" },
|
|
82
|
-
protocolNumber: {
|
|
82
|
+
protocolNumber: {
|
|
83
|
+
type: "text",
|
|
84
|
+
label: "Protocol Number",
|
|
85
|
+
enabledWhen: "false",
|
|
86
|
+
},
|
|
83
87
|
screeningId: { type: "text", label: "Screening ID" },
|
|
84
88
|
participantInitials: { type: "text", label: "Participant Initials" },
|
|
85
89
|
dateOfBirth: { type: "date", label: "Date of Birth" },
|
|
86
90
|
inclusionAge: { type: "boolean", label: "Age between 18-65 years" },
|
|
87
|
-
inclusionDiagnosis: {
|
|
88
|
-
|
|
91
|
+
inclusionDiagnosis: {
|
|
92
|
+
type: "boolean",
|
|
93
|
+
label: "Confirmed Type 2 diabetes diagnosis",
|
|
94
|
+
},
|
|
95
|
+
inclusionVisits: {
|
|
96
|
+
type: "boolean",
|
|
97
|
+
label: "Willing to attend all study visits",
|
|
98
|
+
},
|
|
89
99
|
inclusionConsent: { type: "boolean", label: "Can give informed consent" },
|
|
90
|
-
exclusionPregnant: {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
exclusionPregnant: {
|
|
101
|
+
type: "boolean",
|
|
102
|
+
label: "Pregnant or planning to become pregnant",
|
|
103
|
+
},
|
|
104
|
+
exclusionAllergy: {
|
|
105
|
+
type: "boolean",
|
|
106
|
+
label: "Allergy to metformin or similar drugs",
|
|
107
|
+
},
|
|
108
|
+
exclusionRecentStudy: {
|
|
109
|
+
type: "boolean",
|
|
110
|
+
label: "Participated in another drug study in last 30 days",
|
|
111
|
+
},
|
|
112
|
+
exclusionKidney: {
|
|
113
|
+
type: "boolean",
|
|
114
|
+
label: "History of severe kidney disease",
|
|
115
|
+
},
|
|
116
|
+
exclusionSglt2: {
|
|
117
|
+
type: "boolean",
|
|
118
|
+
label: "Currently taking SGLT2 inhibitors",
|
|
119
|
+
},
|
|
120
|
+
ineligibilityReason: {
|
|
121
|
+
type: "textarea",
|
|
122
|
+
label: "Ineligibility Reason",
|
|
123
|
+
enabledWhen: "false",
|
|
124
|
+
},
|
|
96
125
|
ineligibilityNotes: { type: "textarea", label: "Additional Notes" },
|
|
97
|
-
consentPurpose: {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
126
|
+
consentPurpose: {
|
|
127
|
+
type: "boolean",
|
|
128
|
+
label: "I have read and understand the study purpose",
|
|
129
|
+
},
|
|
130
|
+
consentProcedures: {
|
|
131
|
+
type: "boolean",
|
|
132
|
+
label: "I understand the procedures I will undergo",
|
|
133
|
+
},
|
|
134
|
+
consentRisks: {
|
|
135
|
+
type: "boolean",
|
|
136
|
+
label: "I understand the risks involved",
|
|
137
|
+
},
|
|
138
|
+
consentBenefits: {
|
|
139
|
+
type: "boolean",
|
|
140
|
+
label: "I understand the potential benefits",
|
|
141
|
+
},
|
|
142
|
+
consentVoluntary: {
|
|
143
|
+
type: "boolean",
|
|
144
|
+
label: "I understand participation is voluntary",
|
|
145
|
+
},
|
|
146
|
+
consentDataHandling: {
|
|
147
|
+
type: "boolean",
|
|
148
|
+
label: "I understand how my data will be handled",
|
|
149
|
+
},
|
|
150
|
+
optionalSamples: {
|
|
151
|
+
type: "boolean",
|
|
152
|
+
label: "I consent to storing blood samples",
|
|
153
|
+
},
|
|
154
|
+
optionalContact: {
|
|
155
|
+
type: "boolean",
|
|
156
|
+
label: "I consent to being contacted about other studies",
|
|
157
|
+
},
|
|
158
|
+
optionalGenetic: {
|
|
159
|
+
type: "boolean",
|
|
160
|
+
label: "I consent to genetic analysis",
|
|
161
|
+
},
|
|
162
|
+
signingOnBehalf: {
|
|
163
|
+
type: "boolean",
|
|
164
|
+
label: "Is someone signing on behalf of the participant?",
|
|
165
|
+
},
|
|
107
166
|
participantSignatureName: {
|
|
108
167
|
type: "text",
|
|
109
168
|
label: "Participant Signature Name",
|
|
@@ -135,9 +194,18 @@ function createDiabetesTrialSpec(): Forma {
|
|
|
135
194
|
requiredWhen: "signingOnBehalf = true",
|
|
136
195
|
},
|
|
137
196
|
researcherName: { type: "text", label: "Researcher Name" },
|
|
138
|
-
researcherConfirm: {
|
|
139
|
-
|
|
140
|
-
|
|
197
|
+
researcherConfirm: {
|
|
198
|
+
type: "boolean",
|
|
199
|
+
label: "I confirm I have properly explained the study",
|
|
200
|
+
},
|
|
201
|
+
researcherSignatureDateTime: {
|
|
202
|
+
type: "datetime",
|
|
203
|
+
label: "Researcher Signature Date and Time",
|
|
204
|
+
},
|
|
205
|
+
witnessRequired: {
|
|
206
|
+
type: "boolean",
|
|
207
|
+
label: "Is a witness signature required?",
|
|
208
|
+
},
|
|
141
209
|
witnessName: {
|
|
142
210
|
type: "text",
|
|
143
211
|
label: "Witness Name",
|
|
@@ -163,70 +231,113 @@ function createDiabetesTrialSpec(): Forma {
|
|
|
163
231
|
},
|
|
164
232
|
},
|
|
165
233
|
fieldOrder: [
|
|
166
|
-
"studyName",
|
|
167
|
-
"
|
|
168
|
-
"
|
|
169
|
-
"
|
|
170
|
-
"
|
|
171
|
-
"
|
|
172
|
-
"
|
|
173
|
-
"
|
|
174
|
-
"
|
|
175
|
-
"
|
|
176
|
-
"
|
|
177
|
-
"
|
|
234
|
+
"studyName",
|
|
235
|
+
"protocolNumber",
|
|
236
|
+
"screeningId",
|
|
237
|
+
"participantInitials",
|
|
238
|
+
"dateOfBirth",
|
|
239
|
+
"inclusionAge",
|
|
240
|
+
"inclusionDiagnosis",
|
|
241
|
+
"inclusionVisits",
|
|
242
|
+
"inclusionConsent",
|
|
243
|
+
"exclusionPregnant",
|
|
244
|
+
"exclusionAllergy",
|
|
245
|
+
"exclusionRecentStudy",
|
|
246
|
+
"exclusionKidney",
|
|
247
|
+
"exclusionSglt2",
|
|
248
|
+
"ineligibilityReason",
|
|
249
|
+
"ineligibilityNotes",
|
|
250
|
+
"consentPurpose",
|
|
251
|
+
"consentProcedures",
|
|
252
|
+
"consentRisks",
|
|
253
|
+
"consentBenefits",
|
|
254
|
+
"consentVoluntary",
|
|
255
|
+
"consentDataHandling",
|
|
256
|
+
"optionalSamples",
|
|
257
|
+
"optionalContact",
|
|
258
|
+
"optionalGenetic",
|
|
259
|
+
"signingOnBehalf",
|
|
260
|
+
"participantSignatureName",
|
|
261
|
+
"participantSignatureDateTime",
|
|
262
|
+
"larName",
|
|
263
|
+
"larRelationship",
|
|
264
|
+
"larSignatureDateTime",
|
|
265
|
+
"researcherName",
|
|
266
|
+
"researcherConfirm",
|
|
267
|
+
"researcherSignatureDateTime",
|
|
268
|
+
"witnessRequired",
|
|
269
|
+
"witnessName",
|
|
270
|
+
"witnessSignatureDateTime",
|
|
271
|
+
"enrollmentDate",
|
|
272
|
+
"randomizationNumber",
|
|
273
|
+
"treatmentGroup",
|
|
178
274
|
],
|
|
179
275
|
computed: {
|
|
180
276
|
// Inclusion checks
|
|
181
277
|
allInclusionAnswered: {
|
|
182
|
-
expression:
|
|
278
|
+
expression:
|
|
279
|
+
"(inclusionAge = true or inclusionAge = false) and (inclusionDiagnosis = true or inclusionDiagnosis = false) and (inclusionVisits = true or inclusionVisits = false) and (inclusionConsent = true or inclusionConsent = false)",
|
|
183
280
|
},
|
|
184
281
|
allInclusionMet: {
|
|
185
|
-
expression:
|
|
282
|
+
expression:
|
|
283
|
+
"inclusionAge = true and inclusionDiagnosis = true and inclusionVisits = true and inclusionConsent = true",
|
|
186
284
|
},
|
|
187
285
|
// Exclusion checks
|
|
188
286
|
allExclusionAnswered: {
|
|
189
|
-
expression:
|
|
287
|
+
expression:
|
|
288
|
+
"(exclusionPregnant = true or exclusionPregnant = false) and (exclusionAllergy = true or exclusionAllergy = false) and (exclusionRecentStudy = true or exclusionRecentStudy = false) and (exclusionKidney = true or exclusionKidney = false) and (exclusionSglt2 = true or exclusionSglt2 = false)",
|
|
190
289
|
},
|
|
191
290
|
anyExclusionMet: {
|
|
192
|
-
expression:
|
|
291
|
+
expression:
|
|
292
|
+
"exclusionPregnant = true or exclusionAllergy = true or exclusionRecentStudy = true or exclusionKidney = true or exclusionSglt2 = true",
|
|
193
293
|
},
|
|
194
294
|
// Eligibility determination
|
|
195
295
|
eligibilityDetermined: {
|
|
196
|
-
expression:
|
|
296
|
+
expression:
|
|
297
|
+
"computed.allInclusionAnswered = true and computed.allExclusionAnswered = true",
|
|
197
298
|
},
|
|
198
299
|
eligible: {
|
|
199
|
-
expression:
|
|
300
|
+
expression:
|
|
301
|
+
"computed.eligibilityDetermined = true and computed.allInclusionMet = true and computed.anyExclusionMet = false",
|
|
200
302
|
},
|
|
201
303
|
ineligible: {
|
|
202
|
-
expression:
|
|
304
|
+
expression:
|
|
305
|
+
"computed.eligibilityDetermined = true and (computed.allInclusionMet = false or computed.anyExclusionMet = true)",
|
|
203
306
|
},
|
|
204
307
|
// Consent checks
|
|
205
308
|
allMainConsentsSigned: {
|
|
206
|
-
expression:
|
|
309
|
+
expression:
|
|
310
|
+
"consentPurpose = true and consentProcedures = true and consentRisks = true and consentBenefits = true and consentVoluntary = true and consentDataHandling = true",
|
|
207
311
|
},
|
|
208
312
|
// Signature checks - using null-safe patterns
|
|
209
313
|
hasParticipantSignature: {
|
|
210
|
-
expression:
|
|
314
|
+
expression:
|
|
315
|
+
"signingOnBehalf != true and participantSignatureName != null and participantSignatureDateTime != null",
|
|
211
316
|
},
|
|
212
317
|
hasLarSignature: {
|
|
213
|
-
expression:
|
|
318
|
+
expression:
|
|
319
|
+
"signingOnBehalf = true and larName != null and larRelationship != null and larSignatureDateTime != null",
|
|
214
320
|
},
|
|
215
321
|
hasValidSignature: {
|
|
216
|
-
expression:
|
|
322
|
+
expression:
|
|
323
|
+
"computed.hasParticipantSignature = true or computed.hasLarSignature = true",
|
|
217
324
|
},
|
|
218
325
|
hasResearcherSignature: {
|
|
219
|
-
expression:
|
|
326
|
+
expression:
|
|
327
|
+
"researcherName != null and researcherConfirm = true and researcherSignatureDateTime != null",
|
|
220
328
|
},
|
|
221
329
|
hasWitnessSignature: {
|
|
222
|
-
expression:
|
|
330
|
+
expression:
|
|
331
|
+
"witnessRequired != true or (witnessName != null and witnessSignatureDateTime != null)",
|
|
223
332
|
},
|
|
224
333
|
allSignaturesComplete: {
|
|
225
|
-
expression:
|
|
334
|
+
expression:
|
|
335
|
+
"computed.hasValidSignature = true and computed.hasResearcherSignature = true and computed.hasWitnessSignature = true",
|
|
226
336
|
},
|
|
227
337
|
// Final enrollment gate
|
|
228
338
|
canEnroll: {
|
|
229
|
-
expression:
|
|
339
|
+
expression:
|
|
340
|
+
"computed.eligible = true and computed.allMainConsentsSigned = true and computed.allSignaturesComplete = true",
|
|
230
341
|
},
|
|
231
342
|
},
|
|
232
343
|
pages: [
|
|
@@ -243,12 +354,23 @@ function createDiabetesTrialSpec(): Forma {
|
|
|
243
354
|
{
|
|
244
355
|
id: "inclusion-criteria",
|
|
245
356
|
title: "Eligibility Screening - Inclusion Criteria",
|
|
246
|
-
fields: [
|
|
357
|
+
fields: [
|
|
358
|
+
"inclusionAge",
|
|
359
|
+
"inclusionDiagnosis",
|
|
360
|
+
"inclusionVisits",
|
|
361
|
+
"inclusionConsent",
|
|
362
|
+
],
|
|
247
363
|
},
|
|
248
364
|
{
|
|
249
365
|
id: "exclusion-criteria",
|
|
250
366
|
title: "Eligibility Screening - Exclusion Criteria",
|
|
251
|
-
fields: [
|
|
367
|
+
fields: [
|
|
368
|
+
"exclusionPregnant",
|
|
369
|
+
"exclusionAllergy",
|
|
370
|
+
"exclusionRecentStudy",
|
|
371
|
+
"exclusionKidney",
|
|
372
|
+
"exclusionSglt2",
|
|
373
|
+
],
|
|
252
374
|
},
|
|
253
375
|
{
|
|
254
376
|
id: "ineligibility-documentation",
|
|
@@ -259,7 +381,14 @@ function createDiabetesTrialSpec(): Forma {
|
|
|
259
381
|
{
|
|
260
382
|
id: "main-consents",
|
|
261
383
|
title: "Informed Consent - Main Consents",
|
|
262
|
-
fields: [
|
|
384
|
+
fields: [
|
|
385
|
+
"consentPurpose",
|
|
386
|
+
"consentProcedures",
|
|
387
|
+
"consentRisks",
|
|
388
|
+
"consentBenefits",
|
|
389
|
+
"consentVoluntary",
|
|
390
|
+
"consentDataHandling",
|
|
391
|
+
],
|
|
263
392
|
visibleWhen: "computed.eligible = true",
|
|
264
393
|
},
|
|
265
394
|
{
|
|
@@ -271,14 +400,30 @@ function createDiabetesTrialSpec(): Forma {
|
|
|
271
400
|
{
|
|
272
401
|
id: "participant-signature",
|
|
273
402
|
title: "Participant Signature",
|
|
274
|
-
fields: [
|
|
275
|
-
|
|
403
|
+
fields: [
|
|
404
|
+
"signingOnBehalf",
|
|
405
|
+
"participantSignatureName",
|
|
406
|
+
"participantSignatureDateTime",
|
|
407
|
+
"larName",
|
|
408
|
+
"larRelationship",
|
|
409
|
+
"larSignatureDateTime",
|
|
410
|
+
],
|
|
411
|
+
visibleWhen:
|
|
412
|
+
"computed.eligible = true and computed.allMainConsentsSigned = true",
|
|
276
413
|
},
|
|
277
414
|
{
|
|
278
415
|
id: "researcher-witness-signatures",
|
|
279
416
|
title: "Researcher and Witness Signatures",
|
|
280
|
-
fields: [
|
|
281
|
-
|
|
417
|
+
fields: [
|
|
418
|
+
"researcherName",
|
|
419
|
+
"researcherConfirm",
|
|
420
|
+
"researcherSignatureDateTime",
|
|
421
|
+
"witnessRequired",
|
|
422
|
+
"witnessName",
|
|
423
|
+
"witnessSignatureDateTime",
|
|
424
|
+
],
|
|
425
|
+
visibleWhen:
|
|
426
|
+
"computed.eligible = true and computed.allMainConsentsSigned = true and computed.hasValidSignature = true",
|
|
282
427
|
},
|
|
283
428
|
{
|
|
284
429
|
id: "enrollment-details",
|
|
@@ -447,7 +592,9 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
447
592
|
});
|
|
448
593
|
|
|
449
594
|
describe("eligible flow - page visibility", () => {
|
|
450
|
-
function setupEligibleParticipant(
|
|
595
|
+
function setupEligibleParticipant(
|
|
596
|
+
setFieldValue: (field: string, value: unknown) => void,
|
|
597
|
+
) {
|
|
451
598
|
// All inclusion = true
|
|
452
599
|
setFieldValue("inclusionAge", true);
|
|
453
600
|
setFieldValue("inclusionDiagnosis", true);
|
|
@@ -524,7 +671,10 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
524
671
|
act(() => {
|
|
525
672
|
result.current.setFieldValue("signingOnBehalf", false);
|
|
526
673
|
result.current.setFieldValue("participantSignatureName", "John Doe");
|
|
527
|
-
result.current.setFieldValue(
|
|
674
|
+
result.current.setFieldValue(
|
|
675
|
+
"participantSignatureDateTime",
|
|
676
|
+
"2024-01-15T10:00:00",
|
|
677
|
+
);
|
|
528
678
|
});
|
|
529
679
|
|
|
530
680
|
expect(result.current.computed?.hasValidSignature).toBe(true);
|
|
@@ -547,7 +697,10 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
547
697
|
// Participant signature
|
|
548
698
|
result.current.setFieldValue("signingOnBehalf", false);
|
|
549
699
|
result.current.setFieldValue("participantSignatureName", "John Doe");
|
|
550
|
-
result.current.setFieldValue(
|
|
700
|
+
result.current.setFieldValue(
|
|
701
|
+
"participantSignatureDateTime",
|
|
702
|
+
"2024-01-15T10:00:00",
|
|
703
|
+
);
|
|
551
704
|
});
|
|
552
705
|
|
|
553
706
|
// Enrollment page not yet visible
|
|
@@ -557,7 +710,10 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
557
710
|
act(() => {
|
|
558
711
|
result.current.setFieldValue("researcherName", "Dr. Smith");
|
|
559
712
|
result.current.setFieldValue("researcherConfirm", true);
|
|
560
|
-
result.current.setFieldValue(
|
|
713
|
+
result.current.setFieldValue(
|
|
714
|
+
"researcherSignatureDateTime",
|
|
715
|
+
"2024-01-15T10:30:00",
|
|
716
|
+
);
|
|
561
717
|
result.current.setFieldValue("witnessRequired", false);
|
|
562
718
|
});
|
|
563
719
|
|
|
@@ -629,7 +785,9 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
629
785
|
});
|
|
630
786
|
|
|
631
787
|
describe("signature flow variations", () => {
|
|
632
|
-
function setupReadyForSignature(
|
|
788
|
+
function setupReadyForSignature(
|
|
789
|
+
setFieldValue: (field: string, value: unknown) => void,
|
|
790
|
+
) {
|
|
633
791
|
// Eligible
|
|
634
792
|
setFieldValue("inclusionAge", true);
|
|
635
793
|
setFieldValue("inclusionDiagnosis", true);
|
|
@@ -684,7 +842,9 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
684
842
|
|
|
685
843
|
// Participant fields hidden
|
|
686
844
|
expect(result.current.visibility.participantSignatureName).toBe(false);
|
|
687
|
-
expect(result.current.visibility.participantSignatureDateTime).toBe(
|
|
845
|
+
expect(result.current.visibility.participantSignatureDateTime).toBe(
|
|
846
|
+
false,
|
|
847
|
+
);
|
|
688
848
|
});
|
|
689
849
|
|
|
690
850
|
it("should show witness fields when witness required", () => {
|
|
@@ -722,7 +882,10 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
722
882
|
result.current.setFieldValue("signingOnBehalf", true);
|
|
723
883
|
result.current.setFieldValue("larName", "Jane Doe");
|
|
724
884
|
result.current.setFieldValue("larRelationship", "Spouse");
|
|
725
|
-
result.current.setFieldValue(
|
|
885
|
+
result.current.setFieldValue(
|
|
886
|
+
"larSignatureDateTime",
|
|
887
|
+
"2024-01-15T10:00:00",
|
|
888
|
+
);
|
|
726
889
|
});
|
|
727
890
|
|
|
728
891
|
expect(result.current.computed?.hasLarSignature).toBe(true);
|
|
@@ -744,7 +907,9 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
744
907
|
result.current.wizard?.nextPage();
|
|
745
908
|
});
|
|
746
909
|
expect(result.current.wizard?.currentPageIndex).toBe(1);
|
|
747
|
-
expect(result.current.wizard?.currentPage?.id).toBe(
|
|
910
|
+
expect(result.current.wizard?.currentPage?.id).toBe(
|
|
911
|
+
"participant-information",
|
|
912
|
+
);
|
|
748
913
|
|
|
749
914
|
// Continue to inclusion
|
|
750
915
|
act(() => {
|
|
@@ -776,7 +941,9 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
776
941
|
// With auto-initialized booleans, visible pages are:
|
|
777
942
|
// study-info (0), participant-info (1), inclusion (2), exclusion (3), ineligibility-documentation (4)
|
|
778
943
|
// Pages 5-9 are for eligible flow and still hidden
|
|
779
|
-
const visiblePages = result.current.wizard?.pages.filter(
|
|
944
|
+
const visiblePages = result.current.wizard?.pages.filter(
|
|
945
|
+
(p) => p.visible,
|
|
946
|
+
);
|
|
780
947
|
expect(visiblePages?.length).toBe(5);
|
|
781
948
|
|
|
782
949
|
// Not on last visible page anymore (ineligibility page is visible)
|
|
@@ -786,7 +953,9 @@ describe("diabetes trial enrollment wizard", () => {
|
|
|
786
953
|
act(() => {
|
|
787
954
|
result.current.wizard?.goToPage(4);
|
|
788
955
|
});
|
|
789
|
-
expect(result.current.wizard?.currentPage?.id).toBe(
|
|
956
|
+
expect(result.current.wizard?.currentPage?.id).toBe(
|
|
957
|
+
"ineligibility-documentation",
|
|
958
|
+
);
|
|
790
959
|
expect(result.current.wizard?.isLastPage).toBe(true);
|
|
791
960
|
});
|
|
792
961
|
});
|
|
@@ -93,7 +93,11 @@ describe("FEEL null handling in visibility expressions", () => {
|
|
|
93
93
|
// Since the field has a value (false), it's not null
|
|
94
94
|
// Note: FEEL may still return null/false for != null comparisons
|
|
95
95
|
const hasAnsweredValue = result.current.computed?.hasAnswered;
|
|
96
|
-
expect(
|
|
96
|
+
expect(
|
|
97
|
+
hasAnsweredValue === true ||
|
|
98
|
+
hasAnsweredValue === null ||
|
|
99
|
+
hasAnsweredValue === false,
|
|
100
|
+
).toBe(true);
|
|
97
101
|
});
|
|
98
102
|
});
|
|
99
103
|
|
|
@@ -120,8 +124,12 @@ describe("FEEL null handling in visibility expressions", () => {
|
|
|
120
124
|
// The chain: age is undefined → hasAge evaluates to null → canProceed evaluates to null
|
|
121
125
|
// Both computed values should be null or false due to the dependency chain
|
|
122
126
|
const computed = result.current.computed;
|
|
123
|
-
expect(computed?.hasAge === null || computed?.hasAge === false).toBe(
|
|
124
|
-
|
|
127
|
+
expect(computed?.hasAge === null || computed?.hasAge === false).toBe(
|
|
128
|
+
true,
|
|
129
|
+
);
|
|
130
|
+
expect(
|
|
131
|
+
computed?.canProceed === null || computed?.canProceed === false,
|
|
132
|
+
).toBe(true);
|
|
125
133
|
|
|
126
134
|
// When we provide a value, the chain resolves
|
|
127
135
|
act(() => {
|
|
@@ -339,8 +347,16 @@ describe("page navigation with conditional visibility", () => {
|
|
|
339
347
|
},
|
|
340
348
|
},
|
|
341
349
|
pages: [
|
|
342
|
-
{
|
|
343
|
-
|
|
350
|
+
{
|
|
351
|
+
id: "inclusion",
|
|
352
|
+
title: "Inclusion Criteria",
|
|
353
|
+
fields: ["ageOk", "diagnosisOk"],
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
id: "exclusion",
|
|
357
|
+
title: "Exclusion Criteria",
|
|
358
|
+
fields: ["pregnant", "allergy"],
|
|
359
|
+
},
|
|
344
360
|
{
|
|
345
361
|
id: "consent",
|
|
346
362
|
title: "Consent",
|
|
@@ -396,13 +412,16 @@ describe("page navigation with conditional visibility", () => {
|
|
|
396
412
|
},
|
|
397
413
|
computed: {
|
|
398
414
|
eligibilityDetermined: {
|
|
399
|
-
expression:
|
|
415
|
+
expression:
|
|
416
|
+
"(ageOk = true or ageOk = false) and (pregnant = true or pregnant = false)",
|
|
400
417
|
},
|
|
401
418
|
eligible: {
|
|
402
|
-
expression:
|
|
419
|
+
expression:
|
|
420
|
+
"computed.eligibilityDetermined = true and ageOk = true and pregnant = false",
|
|
403
421
|
},
|
|
404
422
|
ineligible: {
|
|
405
|
-
expression:
|
|
423
|
+
expression:
|
|
424
|
+
"computed.eligibilityDetermined = true and (ageOk = false or pregnant = true)",
|
|
406
425
|
},
|
|
407
426
|
},
|
|
408
427
|
pages: [
|