Skip to content

Commit 2a1f52c

Browse files
feat: throw on invalid json-logic schemas (#178)
1 parent 49370b8 commit 2a1f52c

File tree

2 files changed

+28
-18
lines changed

2 files changed

+28
-18
lines changed

next/src/validation/json-logic.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function replaceUndefinedAndNullValuesWithNaN(values: ObjectValue = {}) {
3333
* @param {NonBooleanJsfSchema} schema - JSON Schema to validate.
3434
* @param {JsonLogicContext | undefined} jsonLogicContext - JSON Logic context.
3535
* @param {ValidationErrorPath} path - Current validation error path.
36+
* @throws {Error} If a validation has missing rule.
3637
*/
3738
export function validateJsonLogicRules(
3839
schema: NonBooleanJsfSchema,
@@ -46,12 +47,15 @@ export function validateJsonLogicRules(
4647
return []
4748
}
4849

49-
return validations.map((validation: string) => {
50-
const validationData = jsonLogicContext?.schema?.validations?.[validation]
50+
return validations.map((validationName: string) => {
51+
const validationData = jsonLogicContext?.schema?.validations?.[validationName]
5152
const formValue = jsonLogicContext?.value
5253

54+
// if the validation name does not reference any valid rule, we throw an error
5355
if (!validationData) {
54-
return []
56+
throw new Error(
57+
`[json-schema-form] json-logic error: "${schema.title}" required validation "${validationName}" doesn't exist.`,
58+
)
5559
}
5660

5761
const result: any = jsonLogic.apply(validationData.rule, replaceUndefinedAndNullValuesWithNaN(formValue as ObjectValue))
@@ -73,6 +77,7 @@ export function validateJsonLogicRules(
7377
* @param {ValidationOptions} options - Validation options.
7478
* @param {JsonLogicContext | undefined} jsonLogicContext - JSON Logic context.
7579
* @param {ValidationErrorPath} path - Current validation error path.
80+
* @throws {Error} If a computed attribute has missing rule.
7681
*/
7782
export function validateJsonLogicComputedAttributes(
7883
values: SchemaValue,
@@ -111,14 +116,15 @@ export function validateJsonLogicComputedAttributes(
111116

112117
const formValue = jsonLogicContext?.value
113118

114-
// if the computation name does not reference any valid rule, we ignore it
119+
// if the computation name does not reference any valid rule, we throw an error
115120
if (!computedAttributeRule) {
116-
return
121+
throw new Error(`[json-schema-form] json-logic error: Computed value "${validationName}" has missing rule.`)
117122
}
118123

119124
const result: any = jsonLogic.apply(computedAttributeRule, replaceUndefinedAndNullValuesWithNaN(formValue as ObjectValue))
120125

121-
if (typeof result === 'undefined') {
126+
// If running the apply function returns null, some variables are probably missing
127+
if (result === null) {
122128
return
123129
}
124130

@@ -147,8 +153,9 @@ function interpolate(message: string, jsonLogicContext: JsonLogicContext | undef
147153
const computedRule = jsonLogicContext.schema.computedValues?.[computationName]?.rule
148154

149155
if (!computedRule) {
150-
console.warn(`No computed rule found for ${computationName}`)
151-
return `{{${computationName}}}`
156+
throw new Error(
157+
`[json-schema-form] json-logic error: Computed value "${computationName}" doesn't exist`,
158+
)
152159
}
153160

154161
const result = jsonLogic.apply(

next/test/validation/json-logic.test.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ describe('validateJsonLogicRules', () => {
4343
it('returns empty array when validation data is not found', () => {
4444
const schema: NonBooleanJsfSchema = {
4545
'type': 'object',
46+
'title': 'foo',
4647
'properties': {},
4748
'x-jsf-logic-validations': ['someValidation'],
4849
}
@@ -54,8 +55,9 @@ describe('validateJsonLogicRules', () => {
5455
value: {},
5556
}
5657

57-
const result = validateJsonLogicRules(schema, jsonLogicContext)
58-
expect(result).toEqual([])
58+
expect(() => validateJsonLogicRules(schema, jsonLogicContext)).toThrow(
59+
`[json-schema-form] json-logic error: "foo" required validation "someValidation" doesn't exist.`,
60+
)
5961
})
6062

6163
it('returns validation error when rule evaluates to false', () => {
@@ -316,8 +318,9 @@ describe('validateJsonLogicRules', () => {
316318
},
317319
}
318320

319-
const errors = validateSchema({ num_guests: 4, amount_of_snacks_to_bring: 3 }, schema)
320-
expect(errors).toHaveLength(0)
321+
expect(() => validateSchema({ num_guests: 4, amount_of_snacks_to_bring: 3 }, schema)).toThrow(
322+
`[json-schema-form] json-logic error: "Number of snacks to bring" required validation "invalid-rule" doesn't exist.`,
323+
)
321324
expect(jsonLogic.apply).not.toHaveBeenCalled()
322325
})
323326

@@ -378,9 +381,10 @@ describe('validateJsonLogicComputedAttributes', () => {
378381
}
379382

380383
const jsonLogicContext: JsonLogicContext = { schema: { computedValues: {} }, value: { age: 16 } }
381-
const result = validateJsonLogicComputedAttributes({ age: 16 }, schema, {}, jsonLogicContext, [])
384+
expect(() => validateJsonLogicComputedAttributes({ age: 16 }, schema, {}, jsonLogicContext, [])).toThrow(
385+
`[json-schema-form] json-logic error: Computed value "nonexistentRule" has missing rule.`,
386+
)
382387

383-
expect(result).toEqual([])
384388
expect(jsonLogic.apply).not.toHaveBeenCalled()
385389
})
386390

@@ -570,10 +574,9 @@ describe('validateJsonLogicComputedAttributes', () => {
570574

571575
(jsonLogic.apply as jest.Mock).mockReturnValue(15)
572576

573-
const result = validateSchema({ someProperty: 10 }, schema)
574-
expect(result).toHaveLength(1)
575-
expect(result[0].validation).toBe('minimum')
576-
expect(result[0].schema['x-jsf-errorMessage']?.minimum).toBe('Must be at least {{invalidVar}} units')
577+
expect(() => validateSchema({ someProperty: 10 }, schema)).toThrow(
578+
`[json-schema-form] json-logic error: Computed value "invalidVar" doesn't exist`,
579+
)
577580
})
578581
})
579582
})

0 commit comments

Comments
 (0)