@fogpipe/forma-react 0.12.0 → 0.14.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.
@@ -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(hasAnsweredValue === true || hasAnsweredValue === null || hasAnsweredValue === false).toBe(true);
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(true);
124
- expect(computed?.canProceed === null || computed?.canProceed === false).toBe(true);
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
- { id: "inclusion", title: "Inclusion Criteria", fields: ["ageOk", "diagnosisOk"] },
343
- { id: "exclusion", title: "Exclusion Criteria", fields: ["pregnant", "allergy"] },
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: "(ageOk = true or ageOk = false) and (pregnant = true or pregnant = false)",
415
+ expression:
416
+ "(ageOk = true or ageOk = false) and (pregnant = true or pregnant = false)",
400
417
  },
401
418
  eligible: {
402
- expression: "computed.eligibilityDetermined = true and ageOk = true and pregnant = false",
419
+ expression:
420
+ "computed.eligibilityDetermined = true and ageOk = true and pregnant = false",
403
421
  },
404
422
  ineligible: {
405
- expression: "computed.eligibilityDetermined = true and (ageOk = false or pregnant = true)",
423
+ expression:
424
+ "computed.eligibilityDetermined = true and (ageOk = false or pregnant = true)",
406
425
  },
407
426
  },
408
427
  pages: [
@@ -34,7 +34,7 @@ describe("Option Visibility", () => {
34
34
  const props = result.current.getSelectFieldProps("department");
35
35
 
36
36
  expect(props.options).toHaveLength(3);
37
- expect(props.options.map(o => o.value)).toEqual(["eng", "hr", "sales"]);
37
+ expect(props.options.map((o) => o.value)).toEqual(["eng", "hr", "sales"]);
38
38
  });
39
39
 
40
40
  it("should filter options based on visibleWhen expressions", () => {
@@ -45,21 +45,33 @@ describe("Option Visibility", () => {
45
45
  type: "select",
46
46
  options: [
47
47
  { value: "intern", label: "Intern" },
48
- { value: "junior", label: "Junior Developer", visibleWhen: "experienceYears >= 1" },
49
- { value: "senior", label: "Senior Developer", visibleWhen: "experienceYears >= 5" },
50
- { value: "lead", label: "Tech Lead", visibleWhen: "experienceYears >= 8" },
48
+ {
49
+ value: "junior",
50
+ label: "Junior Developer",
51
+ visibleWhen: "experienceYears >= 1",
52
+ },
53
+ {
54
+ value: "senior",
55
+ label: "Senior Developer",
56
+ visibleWhen: "experienceYears >= 5",
57
+ },
58
+ {
59
+ value: "lead",
60
+ label: "Tech Lead",
61
+ visibleWhen: "experienceYears >= 8",
62
+ },
51
63
  ],
52
64
  },
53
65
  },
54
66
  });
55
67
 
56
68
  const { result } = renderHook(() =>
57
- useForma({ spec, initialData: { experienceYears: 3 } })
69
+ useForma({ spec, initialData: { experienceYears: 3 } }),
58
70
  );
59
71
 
60
72
  // With 3 years: intern, junior should be visible
61
73
  let props = result.current.getSelectFieldProps("position");
62
- expect(props.options.map(o => o.value)).toEqual(["intern", "junior"]);
74
+ expect(props.options.map((o) => o.value)).toEqual(["intern", "junior"]);
63
75
 
64
76
  // Change to 6 years: intern, junior, senior should be visible
65
77
  act(() => {
@@ -67,7 +79,11 @@ describe("Option Visibility", () => {
67
79
  });
68
80
 
69
81
  props = result.current.getSelectFieldProps("position");
70
- expect(props.options.map(o => o.value)).toEqual(["intern", "junior", "senior"]);
82
+ expect(props.options.map((o) => o.value)).toEqual([
83
+ "intern",
84
+ "junior",
85
+ "senior",
86
+ ]);
71
87
 
72
88
  // Change to 10 years: all should be visible
73
89
  act(() => {
@@ -75,7 +91,12 @@ describe("Option Visibility", () => {
75
91
  });
76
92
 
77
93
  props = result.current.getSelectFieldProps("position");
78
- expect(props.options.map(o => o.value)).toEqual(["intern", "junior", "senior", "lead"]);
94
+ expect(props.options.map((o) => o.value)).toEqual([
95
+ "intern",
96
+ "junior",
97
+ "senior",
98
+ "lead",
99
+ ]);
79
100
  });
80
101
 
81
102
  it("should filter options based on another select field value", () => {
@@ -91,22 +112,41 @@ describe("Option Visibility", () => {
91
112
  position: {
92
113
  type: "select",
93
114
  options: [
94
- { value: "dev_frontend", label: "Frontend Developer", visibleWhen: 'department = "eng"' },
95
- { value: "dev_backend", label: "Backend Developer", visibleWhen: 'department = "eng"' },
96
- { value: "recruiter", label: "Recruiter", visibleWhen: 'department = "hr"' },
97
- { value: "hr_manager", label: "HR Manager", visibleWhen: 'department = "hr"' },
115
+ {
116
+ value: "dev_frontend",
117
+ label: "Frontend Developer",
118
+ visibleWhen: 'department = "eng"',
119
+ },
120
+ {
121
+ value: "dev_backend",
122
+ label: "Backend Developer",
123
+ visibleWhen: 'department = "eng"',
124
+ },
125
+ {
126
+ value: "recruiter",
127
+ label: "Recruiter",
128
+ visibleWhen: 'department = "hr"',
129
+ },
130
+ {
131
+ value: "hr_manager",
132
+ label: "HR Manager",
133
+ visibleWhen: 'department = "hr"',
134
+ },
98
135
  ],
99
136
  },
100
137
  },
101
138
  });
102
139
 
103
140
  const { result } = renderHook(() =>
104
- useForma({ spec, initialData: { department: "eng" } })
141
+ useForma({ spec, initialData: { department: "eng" } }),
105
142
  );
106
143
 
107
144
  // With Engineering selected
108
145
  let props = result.current.getSelectFieldProps("position");
109
- expect(props.options.map(o => o.value)).toEqual(["dev_frontend", "dev_backend"]);
146
+ expect(props.options.map((o) => o.value)).toEqual([
147
+ "dev_frontend",
148
+ "dev_backend",
149
+ ]);
110
150
 
111
151
  // Switch to HR
112
152
  act(() => {
@@ -114,7 +154,10 @@ describe("Option Visibility", () => {
114
154
  });
115
155
 
116
156
  props = result.current.getSelectFieldProps("position");
117
- expect(props.options.map(o => o.value)).toEqual(["recruiter", "hr_manager"]);
157
+ expect(props.options.map((o) => o.value)).toEqual([
158
+ "recruiter",
159
+ "hr_manager",
160
+ ]);
118
161
  });
119
162
 
120
163
  it("should return empty options when all are hidden", () => {
@@ -124,15 +167,23 @@ describe("Option Visibility", () => {
124
167
  premiumFeature: {
125
168
  type: "select",
126
169
  options: [
127
- { value: "feature_a", label: "Feature A", visibleWhen: "isPremium = true" },
128
- { value: "feature_b", label: "Feature B", visibleWhen: "isPremium = true" },
170
+ {
171
+ value: "feature_a",
172
+ label: "Feature A",
173
+ visibleWhen: "isPremium = true",
174
+ },
175
+ {
176
+ value: "feature_b",
177
+ label: "Feature B",
178
+ visibleWhen: "isPremium = true",
179
+ },
129
180
  ],
130
181
  },
131
182
  },
132
183
  });
133
184
 
134
185
  const { result } = renderHook(() =>
135
- useForma({ spec, initialData: { isPremium: false } })
186
+ useForma({ spec, initialData: { isPremium: false } }),
136
187
  );
137
188
 
138
189
  const props = result.current.getSelectFieldProps("premiumFeature");
@@ -148,8 +199,16 @@ describe("Option Visibility", () => {
148
199
  type: "select",
149
200
  options: [
150
201
  { value: "standard", label: "Standard Shipping" },
151
- { value: "express", label: "Express Shipping", visibleWhen: "computed.orderTotal >= 50" },
152
- { value: "overnight", label: "Overnight Shipping", visibleWhen: "computed.orderTotal >= 100" },
202
+ {
203
+ value: "express",
204
+ label: "Express Shipping",
205
+ visibleWhen: "computed.orderTotal >= 50",
206
+ },
207
+ {
208
+ value: "overnight",
209
+ label: "Overnight Shipping",
210
+ visibleWhen: "computed.orderTotal >= 100",
211
+ },
153
212
  ],
154
213
  },
155
214
  },
@@ -159,12 +218,12 @@ describe("Option Visibility", () => {
159
218
  });
160
219
 
161
220
  const { result } = renderHook(() =>
162
- useForma({ spec, initialData: { quantity: 2, unitPrice: 20 } })
221
+ useForma({ spec, initialData: { quantity: 2, unitPrice: 20 } }),
163
222
  );
164
223
 
165
224
  // Total = 40: only standard
166
225
  let props = result.current.getSelectFieldProps("shippingMethod");
167
- expect(props.options.map(o => o.value)).toEqual(["standard"]);
226
+ expect(props.options.map((o) => o.value)).toEqual(["standard"]);
168
227
 
169
228
  // Total = 60: standard and express
170
229
  act(() => {
@@ -172,7 +231,10 @@ describe("Option Visibility", () => {
172
231
  });
173
232
 
174
233
  props = result.current.getSelectFieldProps("shippingMethod");
175
- expect(props.options.map(o => o.value)).toEqual(["standard", "express"]);
234
+ expect(props.options.map((o) => o.value)).toEqual([
235
+ "standard",
236
+ "express",
237
+ ]);
176
238
 
177
239
  // Total = 120: all options
178
240
  act(() => {
@@ -180,7 +242,11 @@ describe("Option Visibility", () => {
180
242
  });
181
243
 
182
244
  props = result.current.getSelectFieldProps("shippingMethod");
183
- expect(props.options.map(o => o.value)).toEqual(["standard", "express", "overnight"]);
245
+ expect(props.options.map((o) => o.value)).toEqual([
246
+ "standard",
247
+ "express",
248
+ "overnight",
249
+ ]);
184
250
  });
185
251
  });
186
252
 
@@ -203,20 +269,28 @@ describe("Option Visibility", () => {
203
269
  type: "multiselect",
204
270
  options: [
205
271
  { value: "basic", label: "Basic Features" },
206
- { value: "advanced", label: "Advanced Features", visibleWhen: 'accountType = "paid"' },
207
- { value: "enterprise", label: "Enterprise Features", visibleWhen: 'accountType = "paid"' },
272
+ {
273
+ value: "advanced",
274
+ label: "Advanced Features",
275
+ visibleWhen: 'accountType = "paid"',
276
+ },
277
+ {
278
+ value: "enterprise",
279
+ label: "Enterprise Features",
280
+ visibleWhen: 'accountType = "paid"',
281
+ },
208
282
  ],
209
283
  },
210
284
  },
211
285
  });
212
286
 
213
287
  const { result } = renderHook(() =>
214
- useForma({ spec, initialData: { accountType: "free" } })
288
+ useForma({ spec, initialData: { accountType: "free" } }),
215
289
  );
216
290
 
217
291
  // Free account: only basic
218
292
  let props = result.current.getSelectFieldProps("features");
219
- expect(props.options.map(o => o.value)).toEqual(["basic"]);
293
+ expect(props.options.map((o) => o.value)).toEqual(["basic"]);
220
294
 
221
295
  // Paid account: all features
222
296
  act(() => {
@@ -224,7 +298,11 @@ describe("Option Visibility", () => {
224
298
  });
225
299
 
226
300
  props = result.current.getSelectFieldProps("features");
227
- expect(props.options.map(o => o.value)).toEqual(["basic", "advanced", "enterprise"]);
301
+ expect(props.options.map((o) => o.value)).toEqual([
302
+ "basic",
303
+ "advanced",
304
+ "enterprise",
305
+ ]);
228
306
  });
229
307
  });
230
308
 
@@ -249,9 +327,17 @@ describe("Option Visibility", () => {
249
327
  addon: {
250
328
  type: "select",
251
329
  options: [
252
- { value: "warranty", label: "Extended Warranty", visibleWhen: 'item.category = "electronics"' },
330
+ {
331
+ value: "warranty",
332
+ label: "Extended Warranty",
333
+ visibleWhen: 'item.category = "electronics"',
334
+ },
253
335
  { value: "insurance", label: "Shipping Insurance" },
254
- { value: "giftWrap", label: "Gift Wrap", visibleWhen: 'item.category = "clothing"' },
336
+ {
337
+ value: "giftWrap",
338
+ label: "Gift Wrap",
339
+ visibleWhen: 'item.category = "clothing"',
340
+ },
255
341
  ],
256
342
  },
257
343
  },
@@ -268,18 +354,24 @@ describe("Option Visibility", () => {
268
354
  { category: "clothing", addon: null },
269
355
  ],
270
356
  },
271
- })
357
+ }),
272
358
  );
273
359
 
274
360
  const helpers = result.current.getArrayHelpers("orderItems");
275
361
 
276
362
  // First item (electronics): warranty and insurance
277
363
  const item0Props = helpers.getItemFieldProps(0, "addon");
278
- expect(item0Props.options?.map(o => o.value)).toEqual(["warranty", "insurance"]);
364
+ expect(item0Props.options?.map((o) => o.value)).toEqual([
365
+ "warranty",
366
+ "insurance",
367
+ ]);
279
368
 
280
369
  // Second item (clothing): insurance and giftWrap
281
370
  const item1Props = helpers.getItemFieldProps(1, "addon");
282
- expect(item1Props.options?.map(o => o.value)).toEqual(["insurance", "giftWrap"]);
371
+ expect(item1Props.options?.map((o) => o.value)).toEqual([
372
+ "insurance",
373
+ "giftWrap",
374
+ ]);
283
375
  });
284
376
 
285
377
  it("should update array item options when item data changes", () => {
@@ -300,7 +392,11 @@ describe("Option Visibility", () => {
300
392
  options: [
301
393
  { value: "email", label: "Email" },
302
394
  { value: "phone", label: "Phone" },
303
- { value: "fax", label: "Fax", visibleWhen: 'item.type = "business"' },
395
+ {
396
+ value: "fax",
397
+ label: "Fax",
398
+ visibleWhen: 'item.type = "business"',
399
+ },
304
400
  ],
305
401
  },
306
402
  },
@@ -314,13 +410,16 @@ describe("Option Visibility", () => {
314
410
  initialData: {
315
411
  contacts: [{ type: "personal", method: null }],
316
412
  },
317
- })
413
+ }),
318
414
  );
319
415
 
320
416
  // Initially personal: email and phone only
321
417
  let helpers = result.current.getArrayHelpers("contacts");
322
418
  let methodProps = helpers.getItemFieldProps(0, "method");
323
- expect(methodProps.options?.map(o => o.value)).toEqual(["email", "phone"]);
419
+ expect(methodProps.options?.map((o) => o.value)).toEqual([
420
+ "email",
421
+ "phone",
422
+ ]);
324
423
 
325
424
  // Change to business: fax becomes available
326
425
  act(() => {
@@ -329,7 +428,11 @@ describe("Option Visibility", () => {
329
428
 
330
429
  helpers = result.current.getArrayHelpers("contacts");
331
430
  methodProps = helpers.getItemFieldProps(0, "method");
332
- expect(methodProps.options?.map(o => o.value)).toEqual(["email", "phone", "fax"]);
431
+ expect(methodProps.options?.map((o) => o.value)).toEqual([
432
+ "email",
433
+ "phone",
434
+ "fax",
435
+ ]);
333
436
  });
334
437
 
335
438
  it("should use itemIndex in option visibleWhen expressions", () => {
@@ -342,7 +445,11 @@ describe("Option Visibility", () => {
342
445
  type: "select",
343
446
  options: [
344
447
  { value: "member", label: "Team Member" },
345
- { value: "lead", label: "Team Lead", visibleWhen: "itemIndex = 0" },
448
+ {
449
+ value: "lead",
450
+ label: "Team Lead",
451
+ visibleWhen: "itemIndex = 0",
452
+ },
346
453
  ],
347
454
  },
348
455
  },
@@ -356,22 +463,25 @@ describe("Option Visibility", () => {
356
463
  initialData: {
357
464
  teamMembers: [{ role: null }, { role: null }, { role: null }],
358
465
  },
359
- })
466
+ }),
360
467
  );
361
468
 
362
469
  const helpers = result.current.getArrayHelpers("teamMembers");
363
470
 
364
471
  // First item: can be member or lead
365
472
  const item0Props = helpers.getItemFieldProps(0, "role");
366
- expect(item0Props.options?.map(o => o.value)).toEqual(["member", "lead"]);
473
+ expect(item0Props.options?.map((o) => o.value)).toEqual([
474
+ "member",
475
+ "lead",
476
+ ]);
367
477
 
368
478
  // Second item: can only be member
369
479
  const item1Props = helpers.getItemFieldProps(1, "role");
370
- expect(item1Props.options?.map(o => o.value)).toEqual(["member"]);
480
+ expect(item1Props.options?.map((o) => o.value)).toEqual(["member"]);
371
481
 
372
482
  // Third item: can only be member
373
483
  const item2Props = helpers.getItemFieldProps(2, "role");
374
- expect(item2Props.options?.map(o => o.value)).toEqual(["member"]);
484
+ expect(item2Props.options?.map((o) => o.value)).toEqual(["member"]);
375
485
  });
376
486
 
377
487
  it("should combine form data, computed values, and item context", () => {
@@ -392,8 +502,17 @@ describe("Option Visibility", () => {
392
502
  type: "select",
393
503
  options: [
394
504
  { value: "standard", label: "Standard" },
395
- { value: "express", label: "Express", visibleWhen: "isPremiumOrder = true" },
396
- { value: "priority", label: "Priority", visibleWhen: 'isPremiumOrder = true and item.productType = "premium"' },
505
+ {
506
+ value: "express",
507
+ label: "Express",
508
+ visibleWhen: "isPremiumOrder = true",
509
+ },
510
+ {
511
+ value: "priority",
512
+ label: "Priority",
513
+ visibleWhen:
514
+ 'isPremiumOrder = true and item.productType = "premium"',
515
+ },
397
516
  ],
398
517
  },
399
518
  },
@@ -411,14 +530,18 @@ describe("Option Visibility", () => {
411
530
  { productType: "premium", shipping: null },
412
531
  ],
413
532
  },
414
- })
533
+ }),
415
534
  );
416
535
 
417
536
  let helpers = result.current.getArrayHelpers("lineItems");
418
537
 
419
538
  // Not premium order: only standard shipping for both
420
- expect(helpers.getItemFieldProps(0, "shipping").options?.map(o => o.value)).toEqual(["standard"]);
421
- expect(helpers.getItemFieldProps(1, "shipping").options?.map(o => o.value)).toEqual(["standard"]);
539
+ expect(
540
+ helpers.getItemFieldProps(0, "shipping").options?.map((o) => o.value),
541
+ ).toEqual(["standard"]);
542
+ expect(
543
+ helpers.getItemFieldProps(1, "shipping").options?.map((o) => o.value),
544
+ ).toEqual(["standard"]);
422
545
 
423
546
  // Upgrade to premium order
424
547
  act(() => {
@@ -428,10 +551,14 @@ describe("Option Visibility", () => {
428
551
  helpers = result.current.getArrayHelpers("lineItems");
429
552
 
430
553
  // Standard product: standard and express
431
- expect(helpers.getItemFieldProps(0, "shipping").options?.map(o => o.value)).toEqual(["standard", "express"]);
554
+ expect(
555
+ helpers.getItemFieldProps(0, "shipping").options?.map((o) => o.value),
556
+ ).toEqual(["standard", "express"]);
432
557
 
433
558
  // Premium product: standard, express, and priority
434
- expect(helpers.getItemFieldProps(1, "shipping").options?.map(o => o.value)).toEqual(["standard", "express", "priority"]);
559
+ expect(
560
+ helpers.getItemFieldProps(1, "shipping").options?.map((o) => o.value),
561
+ ).toEqual(["standard", "express", "priority"]);
435
562
  });
436
563
  });
437
564
 
@@ -460,7 +587,11 @@ describe("Option Visibility", () => {
460
587
  type: "select",
461
588
  options: [
462
589
  { value: "valid", label: "Valid Option" },
463
- { value: "invalid", label: "Invalid", visibleWhen: "this is not valid FEEL syntax !!!" },
590
+ {
591
+ value: "invalid",
592
+ label: "Invalid",
593
+ visibleWhen: "this is not valid FEEL syntax !!!",
594
+ },
464
595
  ],
465
596
  },
466
597
  },
@@ -470,7 +601,7 @@ describe("Option Visibility", () => {
470
601
  const props = result.current.getSelectFieldProps("status");
471
602
 
472
603
  // Invalid expression should hide the option (treated as false)
473
- expect(props.options.map(o => o.value)).toEqual(["valid"]);
604
+ expect(props.options.map((o) => o.value)).toEqual(["valid"]);
474
605
  });
475
606
 
476
607
  it("should preserve selected value when option becomes hidden", () => {
@@ -481,20 +612,27 @@ describe("Option Visibility", () => {
481
612
  type: "select",
482
613
  options: [
483
614
  { value: "basic", label: "Basic" },
484
- { value: "advanced", label: "Advanced", visibleWhen: "level >= 5" },
615
+ {
616
+ value: "advanced",
617
+ label: "Advanced",
618
+ visibleWhen: "level >= 5",
619
+ },
485
620
  ],
486
621
  },
487
622
  },
488
623
  });
489
624
 
490
625
  const { result } = renderHook(() =>
491
- useForma({ spec, initialData: { level: 5, feature: "advanced" } })
626
+ useForma({ spec, initialData: { level: 5, feature: "advanced" } }),
492
627
  );
493
628
 
494
629
  // Initially advanced is selected and visible
495
630
  expect(result.current.data.feature).toBe("advanced");
496
- expect(result.current.getSelectFieldProps("feature").options.map(o => o.value))
497
- .toEqual(["basic", "advanced"]);
631
+ expect(
632
+ result.current
633
+ .getSelectFieldProps("feature")
634
+ .options.map((o) => o.value),
635
+ ).toEqual(["basic", "advanced"]);
498
636
 
499
637
  // Reduce level - advanced option becomes hidden but value is preserved
500
638
  act(() => {
@@ -504,8 +642,11 @@ describe("Option Visibility", () => {
504
642
  // Value is preserved (validation would catch this if needed)
505
643
  expect(result.current.data.feature).toBe("advanced");
506
644
  // But option is no longer visible
507
- expect(result.current.getSelectFieldProps("feature").options.map(o => o.value))
508
- .toEqual(["basic"]);
645
+ expect(
646
+ result.current
647
+ .getSelectFieldProps("feature")
648
+ .options.map((o) => o.value),
649
+ ).toEqual(["basic"]);
509
650
  });
510
651
  });
511
652
  });
@@ -3,7 +3,11 @@
3
3
  */
4
4
 
5
5
  import { render, type RenderOptions } from "@testing-library/react";
6
- import type { Forma, FieldDefinition, PageDefinition } from "@fogpipe/forma-core";
6
+ import type {
7
+ Forma,
8
+ FieldDefinition,
9
+ PageDefinition,
10
+ } from "@fogpipe/forma-core";
7
11
  import type {
8
12
  ComponentMap,
9
13
  TextComponentProps,
@@ -24,7 +28,7 @@ export function createTestSpec(
24
28
  computed?: Record<string, { expression: string }>;
25
29
  pages?: PageDefinition[];
26
30
  referenceData?: Record<string, unknown>;
27
- } = {}
31
+ } = {},
28
32
  ): Forma {
29
33
  const { fields = {}, fieldOrder, computed, pages, referenceData } = options;
30
34
 
@@ -33,10 +37,22 @@ export function createTestSpec(
33
37
  const schemaRequired: string[] = [];
34
38
 
35
39
  for (const [name, field] of Object.entries(fields)) {
36
- const { type, required, options: fieldOptions, items, ...rest } = field as Record<string, unknown>;
40
+ const {
41
+ type,
42
+ required,
43
+ options: fieldOptions,
44
+ items,
45
+ ...rest
46
+ } = field as Record<string, unknown>;
37
47
 
38
48
  let schemaType = type;
39
- if (type === "text" || type === "email" || type === "url" || type === "textarea" || type === "password") {
49
+ if (
50
+ type === "text" ||
51
+ type === "email" ||
52
+ type === "url" ||
53
+ type === "textarea" ||
54
+ type === "password"
55
+ ) {
40
56
  schemaType = "string";
41
57
  }
42
58
  if (type === "select") {
@@ -86,7 +102,8 @@ export function createTestSpec(
86
102
  void __; // Mark as intentionally unused
87
103
  fieldDefs[name] = {
88
104
  type: type as FieldDefinition["type"],
89
- label: (rest.label as string) || name.charAt(0).toUpperCase() + name.slice(1),
105
+ label:
106
+ (rest.label as string) || name.charAt(0).toUpperCase() + name.slice(1),
90
107
  ...rest,
91
108
  } as FieldDefinition;
92
109
  }
@@ -205,7 +222,9 @@ export function createTestComponentMap(): ComponentMap {
205
222
  };
206
223
 
207
224
  // Multiselect fields
208
- const MultiSelectComponent = ({ field: props }: MultiSelectComponentProps) => {
225
+ const MultiSelectComponent = ({
226
+ field: props,
227
+ }: MultiSelectComponentProps) => {
209
228
  const { name, field, value, options, onChange, onBlur, disabled } = props;
210
229
  const displayValue = (value || []).join(",");
211
230
  return (
@@ -288,7 +307,7 @@ export function createTestComponentMap(): ComponentMap {
288
307
  */
289
308
  export function renderWithProviders(
290
309
  ui: React.ReactElement,
291
- options?: Omit<RenderOptions, "wrapper">
310
+ options?: Omit<RenderOptions, "wrapper">,
292
311
  ) {
293
312
  return render(ui, { ...options });
294
313
  }