@fogpipe/forma-core 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 +12 -12
- package/dist/{chunk-U2OXXFEH.js → chunk-BDICNCE2.js} +1 -1
- package/dist/chunk-BDICNCE2.js.map +1 -0
- package/dist/{chunk-ZSW7NIMY.js → chunk-NKA3L2LJ.js} +64 -15
- package/dist/chunk-NKA3L2LJ.js.map +1 -0
- package/dist/engine/calculate.d.ts.map +1 -1
- package/dist/engine/enabled.d.ts.map +1 -1
- package/dist/engine/index.cjs +62 -13
- package/dist/engine/index.cjs.map +1 -1
- package/dist/engine/index.d.ts +8 -8
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +2 -2
- package/dist/engine/readonly.d.ts.map +1 -1
- package/dist/engine/required.d.ts.map +1 -1
- package/dist/engine/validate.d.ts.map +1 -1
- package/dist/engine/visibility.d.ts.map +1 -1
- package/dist/feel/index.cjs.map +1 -1
- package/dist/feel/index.js +1 -1
- package/dist/index.cjs +62 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/types.d.ts +16 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/feel.test.ts +67 -76
- package/src/__tests__/format.test.ts +19 -6
- package/src/__tests__/validate.test.ts +62 -20
- package/src/__tests__/visibility.test.ts +217 -85
- package/src/engine/calculate.ts +13 -10
- package/src/engine/enabled.ts +16 -6
- package/src/engine/index.ts +8 -28
- package/src/engine/readonly.ts +16 -6
- package/src/engine/required.ts +7 -5
- package/src/engine/validate.ts +43 -22
- package/src/engine/visibility.ts +40 -16
- package/src/feel/index.ts +12 -12
- package/src/format/index.ts +1 -1
- package/src/types.ts +46 -7
- package/dist/chunk-U2OXXFEH.js.map +0 -1
- package/dist/chunk-ZSW7NIMY.js.map +0 -1
package/dist/types.d.ts
CHANGED
|
@@ -53,6 +53,7 @@ export interface JSONSchemaString extends JSONSchemaBase {
|
|
|
53
53
|
pattern?: string;
|
|
54
54
|
format?: "date" | "date-time" | "email" | "uri" | "uuid";
|
|
55
55
|
enum?: string[];
|
|
56
|
+
default?: string;
|
|
56
57
|
}
|
|
57
58
|
export interface JSONSchemaNumber extends JSONSchemaBase {
|
|
58
59
|
type: "number";
|
|
@@ -61,15 +62,18 @@ export interface JSONSchemaNumber extends JSONSchemaBase {
|
|
|
61
62
|
exclusiveMinimum?: number;
|
|
62
63
|
exclusiveMaximum?: number;
|
|
63
64
|
multipleOf?: number;
|
|
65
|
+
default?: number;
|
|
64
66
|
}
|
|
65
67
|
export interface JSONSchemaInteger extends JSONSchemaBase {
|
|
66
68
|
type: "integer";
|
|
67
69
|
minimum?: number;
|
|
68
70
|
maximum?: number;
|
|
69
71
|
multipleOf?: number;
|
|
72
|
+
default?: number;
|
|
70
73
|
}
|
|
71
74
|
export interface JSONSchemaBoolean extends JSONSchemaBase {
|
|
72
75
|
type: "boolean";
|
|
76
|
+
default?: boolean;
|
|
73
77
|
}
|
|
74
78
|
export interface JSONSchemaArray extends JSONSchemaBase {
|
|
75
79
|
type: "array";
|
|
@@ -85,6 +89,7 @@ export interface JSONSchemaObject extends JSONSchemaBase {
|
|
|
85
89
|
export interface JSONSchemaEnum extends JSONSchemaBase {
|
|
86
90
|
type: "string";
|
|
87
91
|
enum: string[];
|
|
92
|
+
default?: string;
|
|
88
93
|
}
|
|
89
94
|
/**
|
|
90
95
|
* Field type enumeration - maps to UI component types
|
|
@@ -142,6 +147,17 @@ export interface FieldDefinitionBase {
|
|
|
142
147
|
variant?: string;
|
|
143
148
|
/** Variant-specific configuration */
|
|
144
149
|
variantConfig?: Record<string, unknown>;
|
|
150
|
+
/**
|
|
151
|
+
* Default value for this field when the form initializes.
|
|
152
|
+
* Applied by the renderer during state initialization.
|
|
153
|
+
* Ignored on display fields (enforced by Zod validation layer).
|
|
154
|
+
*
|
|
155
|
+
* Resolution order (highest to lowest priority):
|
|
156
|
+
* 1. initialData prop (runtime)
|
|
157
|
+
* 2. defaultValue (from spec)
|
|
158
|
+
* 3. Implicit type defaults (boolean → false, etc.)
|
|
159
|
+
*/
|
|
160
|
+
defaultValue?: unknown;
|
|
145
161
|
}
|
|
146
162
|
/**
|
|
147
163
|
* Text-like and numeric input fields that support prefix/suffix adorners.
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAMpC;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;CAC5C;AAED,MAAM,MAAM,kBAAkB,GAC1B,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,iBAAiB,GACjB,eAAe,GACf,gBAAgB,GAChB,cAAc,CAAC;AAEnB,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,IAAI,EAAE,QAAQ,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IACzD,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -26,7 +26,7 @@ import type { EvaluationContext } from "../types.js";
|
|
|
26
26
|
* Create a minimal evaluation context for testing
|
|
27
27
|
*/
|
|
28
28
|
function createContext(
|
|
29
|
-
overrides: Partial<EvaluationContext> = {}
|
|
29
|
+
overrides: Partial<EvaluationContext> = {},
|
|
30
30
|
): EvaluationContext {
|
|
31
31
|
return {
|
|
32
32
|
data: {},
|
|
@@ -51,7 +51,7 @@ describe("evaluate", () => {
|
|
|
51
51
|
it("evaluates field references from data", () => {
|
|
52
52
|
const result = evaluate(
|
|
53
53
|
"age >= 18",
|
|
54
|
-
createContext({ data: { age: 21 } })
|
|
54
|
+
createContext({ data: { age: 21 } }),
|
|
55
55
|
);
|
|
56
56
|
expect(result.success).toBe(true);
|
|
57
57
|
if (result.success) {
|
|
@@ -62,7 +62,7 @@ describe("evaluate", () => {
|
|
|
62
62
|
it("evaluates computed field references", () => {
|
|
63
63
|
const result = evaluate(
|
|
64
64
|
"computed.total > 100",
|
|
65
|
-
createContext({ data: {}, computed: { total: 150 } })
|
|
65
|
+
createContext({ data: {}, computed: { total: 150 } }),
|
|
66
66
|
);
|
|
67
67
|
expect(result.success).toBe(true);
|
|
68
68
|
if (result.success) {
|
|
@@ -73,7 +73,7 @@ describe("evaluate", () => {
|
|
|
73
73
|
it("evaluates item field references in array context", () => {
|
|
74
74
|
const result = evaluate(
|
|
75
75
|
"item.quantity > 5",
|
|
76
|
-
createContext({ data: {}, item: { quantity: 10 } })
|
|
76
|
+
createContext({ data: {}, item: { quantity: 10 } }),
|
|
77
77
|
);
|
|
78
78
|
expect(result.success).toBe(true);
|
|
79
79
|
if (result.success) {
|
|
@@ -82,7 +82,10 @@ describe("evaluate", () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
it("evaluates value reference for validation", () => {
|
|
85
|
-
const result = evaluate(
|
|
85
|
+
const result = evaluate(
|
|
86
|
+
"value >= 0",
|
|
87
|
+
createContext({ data: {}, value: 5 }),
|
|
88
|
+
);
|
|
86
89
|
expect(result.success).toBe(true);
|
|
87
90
|
if (result.success) {
|
|
88
91
|
expect(result.value).toBe(true);
|
|
@@ -106,7 +109,7 @@ describe("evaluate", () => {
|
|
|
106
109
|
// This differs from strict FEEL three-valued logic
|
|
107
110
|
const result = evaluate(
|
|
108
111
|
"undefinedField = true",
|
|
109
|
-
createContext({ data: {} })
|
|
112
|
+
createContext({ data: {} }),
|
|
110
113
|
);
|
|
111
114
|
expect(result.success).toBe(true);
|
|
112
115
|
if (result.success) {
|
|
@@ -118,7 +121,7 @@ describe("evaluate", () => {
|
|
|
118
121
|
// In feelin, undefined != null returns false
|
|
119
122
|
const result = evaluate(
|
|
120
123
|
"undefinedField != null",
|
|
121
|
-
createContext({ data: {} })
|
|
124
|
+
createContext({ data: {} }),
|
|
122
125
|
);
|
|
123
126
|
expect(result.success).toBe(true);
|
|
124
127
|
if (result.success) {
|
|
@@ -130,7 +133,7 @@ describe("evaluate", () => {
|
|
|
130
133
|
// Numeric comparisons DO return null when field is undefined
|
|
131
134
|
const result = evaluate(
|
|
132
135
|
"undefinedField > 5",
|
|
133
|
-
createContext({ data: {} })
|
|
136
|
+
createContext({ data: {} }),
|
|
134
137
|
);
|
|
135
138
|
expect(result.success).toBe(true);
|
|
136
139
|
if (result.success) {
|
|
@@ -141,7 +144,7 @@ describe("evaluate", () => {
|
|
|
141
144
|
it("returns null for string length of undefined field", () => {
|
|
142
145
|
const result = evaluate(
|
|
143
146
|
"string length(undefinedField)",
|
|
144
|
-
createContext({ data: {} })
|
|
147
|
+
createContext({ data: {} }),
|
|
145
148
|
);
|
|
146
149
|
expect(result.success).toBe(true);
|
|
147
150
|
if (result.success) {
|
|
@@ -152,7 +155,7 @@ describe("evaluate", () => {
|
|
|
152
155
|
it("returns null for string length comparison with undefined field", () => {
|
|
153
156
|
const result = evaluate(
|
|
154
157
|
"string length(undefinedField) > 0",
|
|
155
|
-
createContext({ data: {} })
|
|
158
|
+
createContext({ data: {} }),
|
|
156
159
|
);
|
|
157
160
|
expect(result.success).toBe(true);
|
|
158
161
|
if (result.success) {
|
|
@@ -163,7 +166,7 @@ describe("evaluate", () => {
|
|
|
163
166
|
it("returns null for count of undefined field", () => {
|
|
164
167
|
const result = evaluate(
|
|
165
168
|
"count(undefinedField) > 0",
|
|
166
|
-
createContext({ data: {} })
|
|
169
|
+
createContext({ data: {} }),
|
|
167
170
|
);
|
|
168
171
|
expect(result.success).toBe(true);
|
|
169
172
|
if (result.success) {
|
|
@@ -173,10 +176,7 @@ describe("evaluate", () => {
|
|
|
173
176
|
|
|
174
177
|
it("propagates null through logical AND with null operand", () => {
|
|
175
178
|
// null and true = null
|
|
176
|
-
const result = evaluate(
|
|
177
|
-
"null and true",
|
|
178
|
-
createContext({ data: {} })
|
|
179
|
-
);
|
|
179
|
+
const result = evaluate("null and true", createContext({ data: {} }));
|
|
180
180
|
expect(result.success).toBe(true);
|
|
181
181
|
if (result.success) {
|
|
182
182
|
expect(result.value).toBeNull();
|
|
@@ -188,7 +188,7 @@ describe("evaluate", () => {
|
|
|
188
188
|
// null propagates through AND
|
|
189
189
|
const result = evaluate(
|
|
190
190
|
"computed.eligible and x = true",
|
|
191
|
-
createContext({ data: { x: true }, computed: { eligible: null } })
|
|
191
|
+
createContext({ data: { x: true }, computed: { eligible: null } }),
|
|
192
192
|
);
|
|
193
193
|
expect(result.success).toBe(true);
|
|
194
194
|
if (result.success) {
|
|
@@ -201,7 +201,7 @@ describe("evaluate", () => {
|
|
|
201
201
|
// false and null = false (short-circuit)
|
|
202
202
|
const result = evaluate(
|
|
203
203
|
"computed.eligible and x = true",
|
|
204
|
-
createContext({ data: {}, computed: { eligible: null } })
|
|
204
|
+
createContext({ data: {}, computed: { eligible: null } }),
|
|
205
205
|
);
|
|
206
206
|
expect(result.success).toBe(true);
|
|
207
207
|
if (result.success) {
|
|
@@ -240,7 +240,7 @@ describe("evaluateBoolean", () => {
|
|
|
240
240
|
it("returns true for true expression", () => {
|
|
241
241
|
const result = evaluateBoolean(
|
|
242
242
|
"age >= 18",
|
|
243
|
-
createContext({ data: { age: 21 } })
|
|
243
|
+
createContext({ data: { age: 21 } }),
|
|
244
244
|
);
|
|
245
245
|
expect(result).toBe(true);
|
|
246
246
|
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
|
@@ -249,7 +249,7 @@ describe("evaluateBoolean", () => {
|
|
|
249
249
|
it("returns false for false expression", () => {
|
|
250
250
|
const result = evaluateBoolean(
|
|
251
251
|
"age >= 18",
|
|
252
|
-
createContext({ data: { age: 15 } })
|
|
252
|
+
createContext({ data: { age: 15 } }),
|
|
253
253
|
);
|
|
254
254
|
expect(result).toBe(false);
|
|
255
255
|
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
|
@@ -258,7 +258,7 @@ describe("evaluateBoolean", () => {
|
|
|
258
258
|
it("returns true for explicitly true boolean field", () => {
|
|
259
259
|
const result = evaluateBoolean(
|
|
260
260
|
"hasConsent = true",
|
|
261
|
-
createContext({ data: { hasConsent: true } })
|
|
261
|
+
createContext({ data: { hasConsent: true } }),
|
|
262
262
|
);
|
|
263
263
|
expect(result).toBe(true);
|
|
264
264
|
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
|
@@ -267,7 +267,7 @@ describe("evaluateBoolean", () => {
|
|
|
267
267
|
it("returns false for explicitly false boolean field", () => {
|
|
268
268
|
const result = evaluateBoolean(
|
|
269
269
|
"hasConsent = true",
|
|
270
|
-
createContext({ data: { hasConsent: false } })
|
|
270
|
+
createContext({ data: { hasConsent: false } }),
|
|
271
271
|
);
|
|
272
272
|
expect(result).toBe(false);
|
|
273
273
|
expect(consoleWarnSpy).not.toHaveBeenCalled();
|
|
@@ -289,7 +289,7 @@ describe("evaluateBoolean", () => {
|
|
|
289
289
|
// feelin returns false for undefined = true, so no warning
|
|
290
290
|
const result = evaluateBoolean(
|
|
291
291
|
"undefinedField = true",
|
|
292
|
-
createContext({ data: {} })
|
|
292
|
+
createContext({ data: {} }),
|
|
293
293
|
);
|
|
294
294
|
|
|
295
295
|
expect(result).toBe(false);
|
|
@@ -300,39 +300,39 @@ describe("evaluateBoolean", () => {
|
|
|
300
300
|
// undefinedField > 5 returns null, triggering warning
|
|
301
301
|
const result = evaluateBoolean(
|
|
302
302
|
"undefinedField > 5",
|
|
303
|
-
createContext({ data: {} })
|
|
303
|
+
createContext({ data: {} }),
|
|
304
304
|
);
|
|
305
305
|
|
|
306
306
|
expect(result).toBe(false);
|
|
307
307
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
308
308
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
309
|
-
expect.stringContaining("returned null")
|
|
309
|
+
expect.stringContaining("returned null"),
|
|
310
310
|
);
|
|
311
311
|
});
|
|
312
312
|
|
|
313
313
|
it("logs warning for string length comparison on undefined field", () => {
|
|
314
314
|
const result = evaluateBoolean(
|
|
315
315
|
"string length(undefinedField) > 0",
|
|
316
|
-
createContext({ data: {} })
|
|
316
|
+
createContext({ data: {} }),
|
|
317
317
|
);
|
|
318
318
|
|
|
319
319
|
expect(result).toBe(false);
|
|
320
320
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
321
321
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
322
|
-
expect.stringContaining("returned null")
|
|
322
|
+
expect.stringContaining("returned null"),
|
|
323
323
|
);
|
|
324
324
|
});
|
|
325
325
|
|
|
326
326
|
it("logs warning for count comparison on undefined field", () => {
|
|
327
327
|
const result = evaluateBoolean(
|
|
328
328
|
"count(undefinedField) > 0",
|
|
329
|
-
createContext({ data: {} })
|
|
329
|
+
createContext({ data: {} }),
|
|
330
330
|
);
|
|
331
331
|
|
|
332
332
|
expect(result).toBe(false);
|
|
333
333
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
334
334
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
335
|
-
expect.stringContaining("returned null")
|
|
335
|
+
expect.stringContaining("returned null"),
|
|
336
336
|
);
|
|
337
337
|
});
|
|
338
338
|
|
|
@@ -340,13 +340,13 @@ describe("evaluateBoolean", () => {
|
|
|
340
340
|
// computed.eligible is null, AND propagates null when other operand is defined
|
|
341
341
|
const result = evaluateBoolean(
|
|
342
342
|
"computed.eligible and x = true",
|
|
343
|
-
createContext({ data: { x: true }, computed: { eligible: null } })
|
|
343
|
+
createContext({ data: { x: true }, computed: { eligible: null } }),
|
|
344
344
|
);
|
|
345
345
|
|
|
346
346
|
expect(result).toBe(false);
|
|
347
347
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
348
348
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
349
|
-
expect.stringContaining("returned null")
|
|
349
|
+
expect.stringContaining("returned null"),
|
|
350
350
|
);
|
|
351
351
|
});
|
|
352
352
|
|
|
@@ -355,7 +355,7 @@ describe("evaluateBoolean", () => {
|
|
|
355
355
|
// feelin may short-circuit: false and null = false (no null in result)
|
|
356
356
|
const result = evaluateBoolean(
|
|
357
357
|
"computed.eligible and x = true",
|
|
358
|
-
createContext({ data: {}, computed: { eligible: null } })
|
|
358
|
+
createContext({ data: {}, computed: { eligible: null } }),
|
|
359
359
|
);
|
|
360
360
|
|
|
361
361
|
expect(result).toBe(false);
|
|
@@ -365,7 +365,7 @@ describe("evaluateBoolean", () => {
|
|
|
365
365
|
it("logs warning for explicit null and true expression", () => {
|
|
366
366
|
const result = evaluateBoolean(
|
|
367
367
|
"null and true",
|
|
368
|
-
createContext({ data: {} })
|
|
368
|
+
createContext({ data: {} }),
|
|
369
369
|
);
|
|
370
370
|
|
|
371
371
|
expect(result).toBe(false);
|
|
@@ -373,52 +373,40 @@ describe("evaluateBoolean", () => {
|
|
|
373
373
|
});
|
|
374
374
|
|
|
375
375
|
it("warning message includes expression that caused it", () => {
|
|
376
|
-
evaluateBoolean(
|
|
377
|
-
"undefinedField > 5",
|
|
378
|
-
createContext({ data: {} })
|
|
379
|
-
);
|
|
376
|
+
evaluateBoolean("undefinedField > 5", createContext({ data: {} }));
|
|
380
377
|
|
|
381
378
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
382
|
-
expect.stringContaining("undefinedField > 5")
|
|
379
|
+
expect.stringContaining("undefinedField > 5"),
|
|
383
380
|
);
|
|
384
381
|
});
|
|
385
382
|
|
|
386
383
|
it("warning message includes null-safe pattern guidance", () => {
|
|
387
|
-
evaluateBoolean(
|
|
388
|
-
"undefinedField > 5",
|
|
389
|
-
createContext({ data: {} })
|
|
390
|
-
);
|
|
384
|
+
evaluateBoolean("undefinedField > 5", createContext({ data: {} }));
|
|
391
385
|
|
|
392
386
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
393
|
-
expect.stringContaining("null-safe patterns")
|
|
387
|
+
expect.stringContaining("null-safe patterns"),
|
|
394
388
|
);
|
|
395
389
|
});
|
|
396
390
|
});
|
|
397
391
|
|
|
398
392
|
describe("non-boolean result handling", () => {
|
|
399
393
|
it("logs warning and returns false for numeric result", () => {
|
|
400
|
-
const result = evaluateBoolean(
|
|
401
|
-
"2 + 3",
|
|
402
|
-
createContext({ data: {} })
|
|
403
|
-
);
|
|
394
|
+
const result = evaluateBoolean("2 + 3", createContext({ data: {} }));
|
|
404
395
|
|
|
405
396
|
expect(result).toBe(false);
|
|
406
397
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
407
398
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
408
|
-
expect.stringContaining("did not return boolean")
|
|
399
|
+
expect.stringContaining("did not return boolean"),
|
|
409
400
|
);
|
|
410
401
|
});
|
|
411
402
|
|
|
412
403
|
it("logs warning and returns false for string result", () => {
|
|
413
|
-
const result = evaluateBoolean(
|
|
414
|
-
'"hello"',
|
|
415
|
-
createContext({ data: {} })
|
|
416
|
-
);
|
|
404
|
+
const result = evaluateBoolean('"hello"', createContext({ data: {} }));
|
|
417
405
|
|
|
418
406
|
expect(result).toBe(false);
|
|
419
407
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
420
408
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
421
|
-
expect.stringContaining("did not return boolean")
|
|
409
|
+
expect.stringContaining("did not return boolean"),
|
|
422
410
|
);
|
|
423
411
|
});
|
|
424
412
|
});
|
|
@@ -428,7 +416,7 @@ describe("evaluateBoolean", () => {
|
|
|
428
416
|
// Force an error by using invalid function
|
|
429
417
|
const result = evaluateBoolean(
|
|
430
418
|
"nonExistentFunction(x)",
|
|
431
|
-
createContext({ data: {} })
|
|
419
|
+
createContext({ data: {} }),
|
|
432
420
|
);
|
|
433
421
|
|
|
434
422
|
expect(result).toBe(false);
|
|
@@ -454,9 +442,12 @@ describe("evaluateNumber", () => {
|
|
|
454
442
|
});
|
|
455
443
|
|
|
456
444
|
it("returns number for valid arithmetic", () => {
|
|
457
|
-
const result = evaluateNumber(
|
|
458
|
-
|
|
459
|
-
|
|
445
|
+
const result = evaluateNumber(
|
|
446
|
+
"quantity * price",
|
|
447
|
+
createContext({
|
|
448
|
+
data: { quantity: 5, price: 10 },
|
|
449
|
+
}),
|
|
450
|
+
);
|
|
460
451
|
expect(result).toBe(50);
|
|
461
452
|
});
|
|
462
453
|
|
|
@@ -464,7 +455,7 @@ describe("evaluateNumber", () => {
|
|
|
464
455
|
const result = evaluateNumber('"hello"', createContext());
|
|
465
456
|
expect(result).toBeNull();
|
|
466
457
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
467
|
-
expect.stringContaining("did not return number")
|
|
458
|
+
expect.stringContaining("did not return number"),
|
|
468
459
|
);
|
|
469
460
|
});
|
|
470
461
|
|
|
@@ -493,7 +484,7 @@ describe("evaluateString", () => {
|
|
|
493
484
|
it("returns string for valid string expression", () => {
|
|
494
485
|
const result = evaluateString(
|
|
495
486
|
'if age >= 18 then "adult" else "minor"',
|
|
496
|
-
createContext({ data: { age: 21 } })
|
|
487
|
+
createContext({ data: { age: 21 } }),
|
|
497
488
|
);
|
|
498
489
|
expect(result).toBe("adult");
|
|
499
490
|
});
|
|
@@ -502,7 +493,7 @@ describe("evaluateString", () => {
|
|
|
502
493
|
const result = evaluateString("2 + 3", createContext());
|
|
503
494
|
expect(result).toBeNull();
|
|
504
495
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
505
|
-
expect.stringContaining("did not return string")
|
|
496
|
+
expect.stringContaining("did not return string"),
|
|
506
497
|
);
|
|
507
498
|
});
|
|
508
499
|
});
|
|
@@ -529,7 +520,7 @@ describe("evaluateBooleanBatch", () => {
|
|
|
529
520
|
canDrive: "age >= 16",
|
|
530
521
|
canDrink: "age >= 21",
|
|
531
522
|
},
|
|
532
|
-
createContext({ data: { age: 20 } })
|
|
523
|
+
createContext({ data: { age: 20 } }),
|
|
533
524
|
);
|
|
534
525
|
|
|
535
526
|
expect(results.canVote).toBe(true);
|
|
@@ -544,7 +535,7 @@ describe("evaluateBooleanBatch", () => {
|
|
|
544
535
|
visible: "undefinedField = true",
|
|
545
536
|
enabled: "anotherUndefined = false",
|
|
546
537
|
},
|
|
547
|
-
createContext({ data: {} })
|
|
538
|
+
createContext({ data: {} }),
|
|
548
539
|
);
|
|
549
540
|
|
|
550
541
|
expect(results.visible).toBe(false);
|
|
@@ -559,7 +550,7 @@ describe("evaluateBooleanBatch", () => {
|
|
|
559
550
|
hasEnoughItems: "count(items) > 5",
|
|
560
551
|
hasLongName: "string length(name) > 10",
|
|
561
552
|
},
|
|
562
|
-
createContext({ data: {} })
|
|
553
|
+
createContext({ data: {} }),
|
|
563
554
|
);
|
|
564
555
|
|
|
565
556
|
expect(results.hasEnoughItems).toBe(false);
|
|
@@ -643,7 +634,7 @@ describe("real-world scenarios", () => {
|
|
|
643
634
|
inclusionDiagnosis: true,
|
|
644
635
|
inclusionHbA1c: true,
|
|
645
636
|
},
|
|
646
|
-
})
|
|
637
|
+
}),
|
|
647
638
|
);
|
|
648
639
|
|
|
649
640
|
expect(result).toBe(true);
|
|
@@ -659,7 +650,7 @@ describe("real-world scenarios", () => {
|
|
|
659
650
|
inclusionDiagnosis: false,
|
|
660
651
|
inclusionHbA1c: true,
|
|
661
652
|
},
|
|
662
|
-
})
|
|
653
|
+
}),
|
|
663
654
|
);
|
|
664
655
|
|
|
665
656
|
expect(result).toBe(false);
|
|
@@ -677,7 +668,7 @@ describe("real-world scenarios", () => {
|
|
|
677
668
|
// inclusionDiagnosis not yet answered
|
|
678
669
|
inclusionHbA1c: true,
|
|
679
670
|
},
|
|
680
|
-
})
|
|
671
|
+
}),
|
|
681
672
|
);
|
|
682
673
|
|
|
683
674
|
expect(result).toBe(false);
|
|
@@ -695,7 +686,7 @@ describe("real-world scenarios", () => {
|
|
|
695
686
|
inclusionAge: true,
|
|
696
687
|
// inclusionDiagnosis not yet answered
|
|
697
688
|
},
|
|
698
|
-
})
|
|
689
|
+
}),
|
|
699
690
|
);
|
|
700
691
|
|
|
701
692
|
expect(allAnswered).toBe(false);
|
|
@@ -712,7 +703,7 @@ describe("real-world scenarios", () => {
|
|
|
712
703
|
data: {
|
|
713
704
|
// signingOnBehalf not yet answered
|
|
714
705
|
},
|
|
715
|
-
})
|
|
706
|
+
}),
|
|
716
707
|
);
|
|
717
708
|
|
|
718
709
|
// feelin returns true for undefined != true
|
|
@@ -728,7 +719,7 @@ describe("real-world scenarios", () => {
|
|
|
728
719
|
createContext({
|
|
729
720
|
data: {},
|
|
730
721
|
computed: { eligible: true },
|
|
731
|
-
})
|
|
722
|
+
}),
|
|
732
723
|
);
|
|
733
724
|
|
|
734
725
|
expect(result).toBe(true);
|
|
@@ -741,7 +732,7 @@ describe("real-world scenarios", () => {
|
|
|
741
732
|
createContext({
|
|
742
733
|
data: {},
|
|
743
734
|
computed: { eligible: false },
|
|
744
|
-
})
|
|
735
|
+
}),
|
|
745
736
|
);
|
|
746
737
|
|
|
747
738
|
expect(result).toBe(false);
|
|
@@ -755,7 +746,7 @@ describe("real-world scenarios", () => {
|
|
|
755
746
|
createContext({
|
|
756
747
|
data: {},
|
|
757
748
|
computed: { eligible: null },
|
|
758
|
-
})
|
|
749
|
+
}),
|
|
759
750
|
);
|
|
760
751
|
|
|
761
752
|
expect(result).toBe(false);
|
|
@@ -771,13 +762,13 @@ describe("real-world scenarios", () => {
|
|
|
771
762
|
createContext({
|
|
772
763
|
data: { otherCondition: true },
|
|
773
764
|
computed: { eligible: null },
|
|
774
|
-
})
|
|
765
|
+
}),
|
|
775
766
|
);
|
|
776
767
|
|
|
777
768
|
expect(result).toBe(false);
|
|
778
769
|
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
|
|
779
770
|
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
780
|
-
expect.stringContaining("returned null")
|
|
771
|
+
expect.stringContaining("returned null"),
|
|
781
772
|
);
|
|
782
773
|
});
|
|
783
774
|
|
|
@@ -788,7 +779,7 @@ describe("real-world scenarios", () => {
|
|
|
788
779
|
createContext({
|
|
789
780
|
data: {},
|
|
790
781
|
computed: { eligible: null },
|
|
791
|
-
})
|
|
782
|
+
}),
|
|
792
783
|
);
|
|
793
784
|
|
|
794
785
|
expect(result).toBe(false);
|
|
@@ -801,7 +792,7 @@ describe("real-world scenarios", () => {
|
|
|
801
792
|
// This is a common pattern that triggers warnings
|
|
802
793
|
const result = evaluateBoolean(
|
|
803
794
|
"string length(signature) > 0",
|
|
804
|
-
createContext({ data: {} })
|
|
795
|
+
createContext({ data: {} }),
|
|
805
796
|
);
|
|
806
797
|
|
|
807
798
|
expect(result).toBe(false);
|
|
@@ -811,7 +802,7 @@ describe("real-world scenarios", () => {
|
|
|
811
802
|
it("no warning when field has value", () => {
|
|
812
803
|
const result = evaluateBoolean(
|
|
813
804
|
"string length(signature) > 0",
|
|
814
|
-
createContext({ data: { signature: "John Doe" } })
|
|
805
|
+
createContext({ data: { signature: "John Doe" } }),
|
|
815
806
|
);
|
|
816
807
|
|
|
817
808
|
expect(result).toBe(true);
|
|
@@ -822,7 +813,7 @@ describe("real-world scenarios", () => {
|
|
|
822
813
|
// Proper null-safe pattern: check != null first
|
|
823
814
|
const result = evaluateBoolean(
|
|
824
815
|
"signature != null and string length(signature) > 0",
|
|
825
|
-
createContext({ data: {} })
|
|
816
|
+
createContext({ data: {} }),
|
|
826
817
|
);
|
|
827
818
|
|
|
828
819
|
expect(result).toBe(false);
|
|
@@ -157,7 +157,9 @@ describe("format module", () => {
|
|
|
157
157
|
|
|
158
158
|
it("formats date strings", () => {
|
|
159
159
|
const result = formatValue("2024-03-15", "date");
|
|
160
|
-
expect(result).toMatch(
|
|
160
|
+
expect(result).toMatch(
|
|
161
|
+
/3\/15\/2024|15\/3\/2024|3\/14\/2024|14\/3\/2024/,
|
|
162
|
+
);
|
|
161
163
|
});
|
|
162
164
|
|
|
163
165
|
it("falls back to string for invalid dates", () => {
|
|
@@ -189,23 +191,34 @@ describe("format module", () => {
|
|
|
189
191
|
describe("nullDisplay option", () => {
|
|
190
192
|
it("uses nullDisplay for null values", () => {
|
|
191
193
|
expect(formatValue(null, undefined, { nullDisplay: "—" })).toBe("—");
|
|
192
|
-
expect(formatValue(null, "decimal(2)", { nullDisplay: "N/A" })).toBe(
|
|
194
|
+
expect(formatValue(null, "decimal(2)", { nullDisplay: "N/A" })).toBe(
|
|
195
|
+
"N/A",
|
|
196
|
+
);
|
|
193
197
|
});
|
|
194
198
|
|
|
195
199
|
it("uses nullDisplay for undefined values", () => {
|
|
196
|
-
expect(formatValue(undefined, undefined, { nullDisplay: "—" })).toBe(
|
|
197
|
-
|
|
200
|
+
expect(formatValue(undefined, undefined, { nullDisplay: "—" })).toBe(
|
|
201
|
+
"—",
|
|
202
|
+
);
|
|
203
|
+
expect(formatValue(undefined, "currency", { nullDisplay: "-" })).toBe(
|
|
204
|
+
"-",
|
|
205
|
+
);
|
|
198
206
|
});
|
|
199
207
|
|
|
200
208
|
it("does not affect non-null values", () => {
|
|
201
|
-
expect(formatValue(123, "decimal(2)", { nullDisplay: "—" })).toBe(
|
|
209
|
+
expect(formatValue(123, "decimal(2)", { nullDisplay: "—" })).toBe(
|
|
210
|
+
"123.00",
|
|
211
|
+
);
|
|
202
212
|
expect(formatValue(0, "decimal(2)", { nullDisplay: "—" })).toBe("0.00");
|
|
203
213
|
});
|
|
204
214
|
});
|
|
205
215
|
|
|
206
216
|
describe("locale option", () => {
|
|
207
217
|
it("respects locale for currency formatting", () => {
|
|
208
|
-
const result = formatValue(1234.56, "currency", {
|
|
218
|
+
const result = formatValue(1234.56, "currency", {
|
|
219
|
+
locale: "de-DE",
|
|
220
|
+
currency: "EUR",
|
|
221
|
+
});
|
|
209
222
|
// German locale uses comma for decimals
|
|
210
223
|
expect(result).toContain("1.234,56");
|
|
211
224
|
});
|