Skip to content

Commit

Permalink
Merge pull request #2 from Marcisbee/all-of
Browse files Browse the repository at this point in the history
Adds `allOf` schema rule
  • Loading branch information
Marcisbee authored Oct 5, 2021
2 parents c7699e7 + 3fe279d commit 8a4cee1
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/validate/all-of.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* @this {import('src').Context}
* @param {*} value
* @param {*[]} currentSchema
* @param {(string | number)[]} position
*/
function validateAllOf(value, currentSchema, position) {
let errorDepth = position.length + 1;
let possibleError;

const passSize = currentSchema.length;
let passedValues = 0;

for (const key in currentSchema) {
try {
// Run shallow validation
this.validateSchema.call(
{...this, shallow: true},
value,
position,
currentSchema[key],
);

passedValues += 1;
} catch (e) {
if (e.position && e.position.length > errorDepth) {
possibleError = key;
errorDepth = e.position.length;
}
}
}

if (passedValues >= passSize) {
return;
}

// Guessing the error based on error depth
if (possibleError) {
return possibleError;
}

this.error("Value doesn't match all of criteria", "allOf", position);
}

module.exports = validateAllOf;
12 changes: 12 additions & 0 deletions src/validate/schema.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const GenericError = require("../diagnostics/generic-error");

const validateEnum = require("./enum");
const validateAllOf = require("./all-of");
const validateAnyOf = require("./any-of");
const validateString = require("./type/string");
const validateObject = require("./type/object");
Expand Down Expand Up @@ -67,6 +68,17 @@ function validateSchema(json, position, currentSchema = this.schema) {
return;
}

if (!this.shallow && currentSchema.allOf) {
const key = validateAllOf.call(this, json, currentSchema.allOf, position);

if (typeof key === "undefined") {
return;
}

validateSchema.call(this, json, position, currentSchema.allOf[key]);
return;
}

if (!this.shallow && currentSchema.anyOf) {
const key = validateAnyOf.call(this, json, currentSchema.anyOf, position);

Expand Down
67 changes: 67 additions & 0 deletions tests/all-of.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const {test} = require("uvu");
const assert = require("uvu/assert");

const ValidationError = require("../src/diagnostics/validation-error");
const output = require("../src/output");

const userConfig = {};

test("allOf with one empty schema", () => {
const schema = {
"allOf": [{}],
};
const errors = output("1", schema, userConfig);

assert.equal(errors, []);
});

test("allOf with two empty schemas", () => {
const schema = {
"allOf": [{}, {}],
};
const errors = output("1", schema, userConfig);

assert.equal(errors, []);
});

test("allOf with two schemas, the first is empty - number is valid", () => {
const schema = {
"allOf": [{}, { "type": "number" }],
};
const errors = output("1", schema, userConfig);

assert.equal(errors, []);
});

test("allOf with two schemas, the first is empty - string is invalid", () => {
const schema = {
"allOf": [{}, { "type": "number" }],
};
const errors = output("\"foo\"", schema, userConfig);

assert.equal(errors, [
new ValidationError("Value doesn't match all of criteria", "allOf", [])
]);
});

test("allOf with two schemas, the second is empty - number is valid", () => {
const schema = {
"allOf": [{ "type": "number" }, {}],
};
const errors = output("1", schema, userConfig);

assert.equal(errors, []);
});

test("allOf with two schemas, the second is empty - string is invalid", () => {
const schema = {
"allOf": [{ "type": "number" }, {}],
};
const errors = output("\"foo\"", schema, userConfig);

assert.equal(errors, [
new ValidationError("Value doesn't match all of criteria", "allOf", [])
]);
});

test.run();

0 comments on commit 8a4cee1

Please sign in to comment.