-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for if, else, then rules #2506
Changes from all commits
f72a62c
75c4d84
a08c563
5ccf7ec
17816d3
fa0269a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -572,7 +572,7 @@ export function optionsList(schema) { | |
}); | ||
} else { | ||
const altSchemas = schema.oneOf || schema.anyOf; | ||
return altSchemas.map((schema, i) => { | ||
return altSchemas.map(schema => { | ||
const value = toConstant(schema); | ||
const label = schema.title || String(value); | ||
return { | ||
|
@@ -665,12 +665,40 @@ export function stubExistingAdditionalProperties( | |
return schema; | ||
} | ||
|
||
const resolveCondition = (schema, rootSchema, formdata) => { | ||
let { | ||
if: expression, | ||
then, | ||
else: otherwise, | ||
...resolvedSchemaLessConditional | ||
} = schema; | ||
|
||
const conditionalSchema = isValid(expression, formdata, rootSchema) | ||
? then | ||
: otherwise; | ||
|
||
if (conditionalSchema) { | ||
return retrieveSchema( | ||
mergeSchemas( | ||
resolvedSchemaLessConditional, | ||
retrieveSchema(conditionalSchema, rootSchema, formdata) | ||
Comment on lines
+683
to
+684
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Noticed that this was swapped (presumably to fix a bug?). Is there a test case we could add that would catch a regression? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Expected behavior: inner property ( |
||
), | ||
rootSchema, | ||
formdata | ||
); | ||
} else { | ||
return retrieveSchema(resolvedSchemaLessConditional, rootSchema, formdata); | ||
} | ||
}; | ||
|
||
export function resolveSchema(schema, rootSchema = {}, formData = {}) { | ||
if (schema.hasOwnProperty("$ref")) { | ||
return resolveReference(schema, rootSchema, formData); | ||
} else if (schema.hasOwnProperty("dependencies")) { | ||
const resolvedSchema = resolveDependencies(schema, rootSchema, formData); | ||
return retrieveSchema(resolvedSchema, rootSchema, formData); | ||
} else if (schema.hasOwnProperty("if")) { | ||
return resolveCondition(schema, rootSchema, formData); | ||
} else if (schema.hasOwnProperty("allOf")) { | ||
return { | ||
...schema, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2403,6 +2403,210 @@ describe("utils", () => { | |
}); | ||
}); | ||
}); | ||
|
||
describe("ifThenElse", () => { | ||
it("should resolve if, then", () => { | ||
const schema = { | ||
type: "object", | ||
properties: { | ||
country: { | ||
default: "United States of America", | ||
enum: ["United States of America", "Canada"], | ||
}, | ||
}, | ||
if: { | ||
properties: { country: { const: "United States of America" } }, | ||
}, | ||
then: { | ||
properties: { postal_code: { pattern: "[0-9]{5}(-[0-9]{4})?" } }, | ||
}, | ||
else: { | ||
properties: { | ||
postal_code: { pattern: "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" }, | ||
}, | ||
}, | ||
}; | ||
const definitions = {}; | ||
const formData = { | ||
country: "United States of America", | ||
postal_code: "20500", | ||
}; | ||
expect(retrieveSchema(schema, { definitions }, formData)).eql({ | ||
type: "object", | ||
properties: { | ||
country: { | ||
default: "United States of America", | ||
enum: ["United States of America", "Canada"], | ||
}, | ||
postal_code: { pattern: "[0-9]{5}(-[0-9]{4})?" }, | ||
}, | ||
}); | ||
}); | ||
it("should resolve if, else", () => { | ||
const schema = { | ||
type: "object", | ||
properties: { | ||
country: { | ||
default: "United States of America", | ||
enum: ["United States of America", "Canada"], | ||
}, | ||
}, | ||
if: { | ||
properties: { country: { const: "United States of America" } }, | ||
}, | ||
then: { | ||
properties: { postal_code: { pattern: "[0-9]{5}(-[0-9]{4})?" } }, | ||
}, | ||
else: { | ||
properties: { | ||
postal_code: { pattern: "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" }, | ||
}, | ||
}, | ||
}; | ||
const definitions = {}; | ||
const formData = { | ||
country: "Canada", | ||
postal_code: "K1M 1M4", | ||
}; | ||
expect(retrieveSchema(schema, { definitions }, formData)).eql({ | ||
type: "object", | ||
properties: { | ||
country: { | ||
default: "United States of America", | ||
enum: ["United States of America", "Canada"], | ||
}, | ||
postal_code: { pattern: "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" }, | ||
}, | ||
}); | ||
}); | ||
it("should resolve multiple conditions", () => { | ||
const schema = { | ||
type: "object", | ||
properties: { | ||
animal: { | ||
enum: ["Cat", "Fish"], | ||
}, | ||
}, | ||
allOf: [ | ||
{ | ||
if: { | ||
properties: { animal: { const: "Cat" } }, | ||
}, | ||
then: { | ||
properties: { | ||
food: { type: "string", enum: ["meat", "grass", "fish"] }, | ||
}, | ||
}, | ||
required: ["food"], | ||
}, | ||
{ | ||
if: { | ||
properties: { animal: { const: "Fish" } }, | ||
}, | ||
then: { | ||
properties: { | ||
food: { | ||
type: "string", | ||
enum: ["insect", "worms"], | ||
}, | ||
water: { | ||
type: "string", | ||
enum: ["lake", "sea"], | ||
}, | ||
}, | ||
required: ["food", "water"], | ||
}, | ||
}, | ||
{ | ||
required: ["animal"], | ||
}, | ||
], | ||
}; | ||
const definitions = {}; | ||
const formData = { | ||
animal: "Cat", | ||
}; | ||
|
||
expect(retrieveSchema(schema, { definitions }, formData)).eql({ | ||
type: "object", | ||
properties: { | ||
animal: { | ||
enum: ["Cat", "Fish"], | ||
}, | ||
food: { type: "string", enum: ["meat", "grass", "fish"] }, | ||
}, | ||
required: ["animal", "food"], | ||
}); | ||
}); | ||
it.only("should resolve $ref", () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove .only |
||
const schema = { | ||
type: "object", | ||
properties: { | ||
animal: { | ||
enum: ["Cat", "Fish"], | ||
}, | ||
}, | ||
allOf: [ | ||
{ | ||
if: { | ||
properties: { animal: { const: "Cat" } }, | ||
}, | ||
then: { | ||
$ref: "#/definitions/cat", | ||
}, | ||
required: ["food"], | ||
}, | ||
{ | ||
if: { | ||
properties: { animal: { const: "Fish" } }, | ||
}, | ||
then: { | ||
$ref: "#/definitions/fish", | ||
}, | ||
}, | ||
{ | ||
required: ["animal"], | ||
}, | ||
], | ||
}; | ||
|
||
const definitions = { | ||
cat: { | ||
properties: { | ||
food: { type: "string", enum: ["meat", "grass", "fish"] }, | ||
}, | ||
}, | ||
fish: { | ||
properties: { | ||
food: { | ||
type: "string", | ||
enum: ["insect", "worms"], | ||
}, | ||
water: { | ||
type: "string", | ||
enum: ["lake", "sea"], | ||
}, | ||
}, | ||
required: ["food", "water"], | ||
}, | ||
}; | ||
|
||
const formData = { | ||
animal: "Cat", | ||
}; | ||
|
||
expect(retrieveSchema(schema, { definitions }, formData)).eql({ | ||
type: "object", | ||
properties: { | ||
animal: { | ||
enum: ["Cat", "Fish"], | ||
}, | ||
food: { type: "string", enum: ["meat", "grass", "fish"] }, | ||
}, | ||
required: ["animal", "food"], | ||
}); | ||
}); | ||
}); | ||
}); | ||
|
||
describe("shouldRender", () => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
module.exports = { | ||
schema: { | ||
type: "object", | ||
properties: { | ||
animal: { | ||
enum: ["Cat", "Fish"], | ||
}, | ||
}, | ||
allOf: [ | ||
{ | ||
if: { | ||
properties: { animal: { const: "Cat" } }, | ||
}, | ||
then: { | ||
properties: { | ||
food: { type: "string", enum: ["meat", "grass", "fish"] }, | ||
}, | ||
required: ["food"], | ||
}, | ||
}, | ||
{ | ||
if: { | ||
properties: { animal: { const: "Fish" } }, | ||
}, | ||
then: { | ||
properties: { | ||
food: { | ||
type: "string", | ||
enum: ["insect", "worms"], | ||
}, | ||
water: { | ||
type: "string", | ||
enum: ["lake", "sea"], | ||
}, | ||
}, | ||
required: ["food", "water"], | ||
}, | ||
}, | ||
{ | ||
required: ["animal"], | ||
}, | ||
], | ||
}, | ||
formData: {}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename formdata to
formData
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment describing what this function does