Skip to content

Commit

Permalink
refactor: code for multiple options
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander-akait committed Jun 14, 2023
1 parent 3731a59 commit f049ae8
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 25 deletions.
46 changes: 21 additions & 25 deletions src/validate.js
Expand Up @@ -90,6 +90,22 @@ const getAjv = memoize(() => {
* @property {PostFormatter=} postFormatter
*/

/**
* @param {SchemaUtilErrorObject} error
* @param {number} idx
* @returns {SchemaUtilErrorObject}
*/
function applyPrefix(error, idx) {
// eslint-disable-next-line no-param-reassign
error.instancePath = `[${idx}]${error.instancePath}`;

if (error.children) {
error.children.forEach((err) => applyPrefix(err, idx));
}

return error;
}

/**
* @param {Schema} schema
* @param {Array<object> | object} options
Expand All @@ -100,31 +116,11 @@ function validate(schema, options, configuration) {
let errors = [];

if (Array.isArray(options)) {
errors = Array.from(options, (nestedOptions) =>
validateObject(schema, nestedOptions)
);

errors.forEach((list, idx) => {
const applyPrefix =
/**
* @param {SchemaUtilErrorObject} error
*/
(error) => {
// eslint-disable-next-line no-param-reassign
error.instancePath = `[${idx}]${error.instancePath}`;

if (error.children) {
error.children.forEach(applyPrefix);
}
};

list.forEach(applyPrefix);
});

errors = errors.reduce((arr, items) => {
arr.push(...items);
return arr;
}, []);
for (let i = 0; i <= options.length - 1; i++) {
errors.push(
...validateObject(schema, options[i]).map((err) => applyPrefix(err, i))
);
}
} else {
errors = validateObject(schema, options);
}
Expand Down
27 changes: 27 additions & 0 deletions test/__snapshots__/api.test.js.snap
Expand Up @@ -29,3 +29,30 @@ exports[`api should use default values when "title" is broken 1`] = `
- configuration has an unknown property 'foo'. These properties are valid:
object { name? }"
`;
exports[`api should work with anyOf 1`] = `
"Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration should be one of these:
object { bar, … } | object { baz, … }
Details:
* configuration misses the property 'bar' | should be any non-object. Should be:
number
* configuration misses the property 'baz' | should be any non-object. Should be:
number"
`;
exports[`api should work with minProperties properties 1`] = `
"Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration should be a non-empty object."
`;
exports[`api should work with required properties #2 1`] = `
"Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration misses the property 'e'."
`;
exports[`api should work with required properties 1`] = `
"Invalid configuration object. Object has been initialized using a configuration object that does not match the API schema.
- configuration.c misses the property 'e'. Should be:
string"
`;
99 changes: 99 additions & 0 deletions test/api.test.js
Expand Up @@ -97,4 +97,103 @@ describe("api", () => {
expect(error.message).toMatchSnapshot();
}
});

it("should work with required properties", () => {
try {
validate(
{
type: "object",
properties: {
c: {
type: "object",
properties: {
d: {
type: "string",
},
e: {
type: "string",
},
},
additionalProperties: true,
required: ["d", "e"],
},
},
},
{ c: { d: "e" } }
);
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}
});

it("should work with required properties #2", () => {
try {
validate(
{
type: "object",
properties: {},
required: ["d", "e"],
},
{}
);
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}
});

it("should work with minProperties properties", () => {
try {
validate(
{
type: "object",
properties: {},
minProperties: 1,
},
{}
);
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}
});

it("should work with anyOf", () => {
try {
validate(
{
type: "object",
properties: { foo: { type: "number" } },
unevaluatedProperties: false,
anyOf: [
{
required: ["bar"],
properties: { bar: { type: "number" } },
},
{
required: ["baz"],
properties: { baz: { type: "number" } },
},
],
},
{}
);
} catch (error) {
if (error.name !== "ValidationError") {
throw error;
}

expect(error.message).toMatchSnapshot();
}
});
});

0 comments on commit f049ae8

Please sign in to comment.