From 1096bbfa33a4af53ae2bfeee459c313fddb7c20d Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Sat, 22 May 2021 14:01:32 -0400 Subject: Update schema tests (#1693) * Update helper functions * Rename file * Update deleteProperty * Add some basic proxy tests --- ext/js/data/json-schema.js | 13 +- test/test-json-schema.js | 823 +++++++++++++++++++++++++++++++++++++++++++++ test/test-schema.js | 703 -------------------------------------- 3 files changed, 834 insertions(+), 705 deletions(-) create mode 100644 test/test-json-schema.js delete mode 100644 test/test-schema.js diff --git a/ext/js/data/json-schema.js b/ext/js/data/json-schema.js index 7b6b9c53..6a590911 100644 --- a/ext/js/data/json-schema.js +++ b/ext/js/data/json-schema.js @@ -103,8 +103,12 @@ class JsonSchemaProxyHandler { } deleteProperty(target, property) { - const required = this._schema.required; - if (Array.isArray(required) && required.includes(property)) { + const required = ( + (typeof target === 'object' && target !== null) ? + (Array.isArray(target) || this._jsonSchemaValidator.isObjectPropertyRequired(this._schema, property)) : + true + ); + if (required) { throw new Error(`${property} cannot be deleted`); } return Reflect.deleteProperty(target, property); @@ -159,6 +163,11 @@ class JsonSchemaValidator { this._regexCache.clear(); } + isObjectPropertyRequired(schema, property) { + const {required} = schema; + return Array.isArray(required) && required.includes(property); + } + // Private _getPropertySchema(schema, property, value, path) { diff --git a/test/test-json-schema.js b/test/test-json-schema.js new file mode 100644 index 00000000..d8e351be --- /dev/null +++ b/test/test-json-schema.js @@ -0,0 +1,823 @@ +/* + * Copyright (C) 2020-2021 Yomichan Authors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +const assert = require('assert'); +const {testMain} = require('../dev/util'); +const {VM} = require('../dev/vm'); + +const vm = new VM(); +vm.execute([ + 'js/core.js', + 'js/general/cache-map.js', + 'js/data/json-schema.js' +]); +const JsonSchemaValidator = vm.get('JsonSchemaValidator'); + + +function schemaValidate(schema, value) { + return new JsonSchemaValidator().isValid(value, schema); +} + +function getValidValueOrDefault(schema, value) { + return new JsonSchemaValidator().getValidValueOrDefault(schema, value); +} + +function createProxy(schema, value) { + return new JsonSchemaValidator().createProxy(value, schema); +} + + +function testValidate1() { + const schema = { + allOf: [ + { + type: 'number' + }, + { + anyOf: [ + {minimum: 10, maximum: 100}, + {minimum: -100, maximum: -10} + ] + }, + { + oneOf: [ + {multipleOf: 3}, + {multipleOf: 5} + ] + }, + { + not: [ + {multipleOf: 20} + ] + } + ] + }; + + const jsValidate = (value) => { + return ( + typeof value === 'number' && + ( + (value >= 10 && value <= 100) || + (value >= -100 && value <= -10) + ) && + ( + ( + (value % 3) === 0 || + (value % 5) === 0 + ) && + (value % 15) !== 0 + ) && + (value % 20) !== 0 + ); + }; + + for (let i = -111; i <= 111; i++) { + const actual = schemaValidate(schema, i); + const expected = jsValidate(i); + assert.strictEqual(actual, expected); + } +} + +function testValidate2() { + const data = [ + // String tests + { + schema: { + type: 'string' + }, + inputs: [ + {expected: false, value: null}, + {expected: false, value: void 0}, + {expected: false, value: 0}, + {expected: false, value: {}}, + {expected: false, value: []}, + {expected: true, value: ''} + ] + }, + { + schema: { + type: 'string', + minLength: 2 + }, + inputs: [ + {expected: false, value: ''}, + {expected: false, value: '1'}, + {expected: true, value: '12'}, + {expected: true, value: '123'} + ] + }, + { + schema: { + type: 'string', + maxLength: 2 + }, + inputs: [ + {expected: true, value: ''}, + {expected: true, value: '1'}, + {expected: true, value: '12'}, + {expected: false, value: '123'} + ] + }, + { + schema: { + type: 'string', + pattern: 'test' + }, + inputs: [ + {expected: false, value: ''}, + {expected: true, value: 'test'}, + {expected: false, value: 'TEST'}, + {expected: true, value: 'ABCtestDEF'}, + {expected: false, value: 'ABCTESTDEF'} + ] + }, + { + schema: { + type: 'string', + pattern: '^test$' + }, + inputs: [ + {expected: false, value: ''}, + {expected: true, value: 'test'}, + {expected: false, value: 'TEST'}, + {expected: false, value: 'ABCtestDEF'}, + {expected: false, value: 'ABCTESTDEF'} + ] + }, + { + schema: { + type: 'string', + pattern: '^test$', + patternFlags: 'i' + }, + inputs: [ + {expected: false, value: ''}, + {expected: true, value: 'test'}, + {expected: true, value: 'TEST'}, + {expected: false, value: 'ABCtestDEF'}, + {expected: false, value: 'ABCTESTDEF'} + ] + }, + { + schema: { + type: 'string', + pattern: '*' + }, + inputs: [ + {expected: false, value: ''} + ] + }, + { + schema: { + type: 'string', + pattern: '.', + patternFlags: '?' + }, + inputs: [ + {expected: false, value: ''} + ] + }, + + // Const tests + { + schema: { + const: 32 + }, + inputs: [ + {expected: true, value: 32}, + {expected: false, value: 0}, + {expected: false, value: '32'}, + {expected: false, value: null}, + {expected: false, value: {a: 'b'}}, + {expected: false, value: [1, 2, 3]} + ] + }, + { + schema: { + const: '32' + }, + inputs: [ + {expected: false, value: 32}, + {expected: false, value: 0}, + {expected: true, value: '32'}, + {expected: false, value: null}, + {expected: false, value: {a: 'b'}}, + {expected: false, value: [1, 2, 3]} + ] + }, + { + schema: { + const: null + }, + inputs: [ + {expected: false, value: 32}, + {expected: false, value: 0}, + {expected: false, value: '32'}, + {expected: true, value: null}, + {expected: false, value: {a: 'b'}}, + {expected: false, value: [1, 2, 3]} + ] + }, + { + schema: { + const: {a: 'b'} + }, + inputs: [ + {expected: false, value: 32}, + {expected: false, value: 0}, + {expected: false, value: '32'}, + {expected: false, value: null}, + {expected: false, value: {a: 'b'}}, + {expected: false, value: [1, 2, 3]} + ] + }, + { + schema: { + const: [1, 2, 3] + }, + inputs: [ + {expected: false, value: 32}, + {expected: false, value: 0}, + {expected: false, value: '32'}, + {expected: false, value: null}, + {expected: false, value: {a: 'b'}}, + {expected: false, value: [1, 2, 3]} + ] + }, + + // Array contains tests + { + schema: { + type: 'array', + contains: {const: 32} + }, + inputs: [ + {expected: false, value: []}, + {expected: true, value: [32]}, + {expected: true, value: [1, 32]}, + {expected: true, value: [1, 32, 1]}, + {expected: false, value: [33]}, + {expected: false, value: [1, 33]}, + {expected: false, value: [1, 33, 1]} + ] + }, + + // Number limits tests + { + schema: { + type: 'number', + minimum: 0 + }, + inputs: [ + {expected: false, value: -1}, + {expected: true, value: 0}, + {expected: true, value: 1} + ] + }, + { + schema: { + type: 'number', + exclusiveMinimum: 0 + }, + inputs: [ + {expected: false, value: -1}, + {expected: false, value: 0}, + {expected: true, value: 1} + ] + }, + { + schema: { + type: 'number', + maximum: 0 + }, + inputs: [ + {expected: true, value: -1}, + {expected: true, value: 0}, + {expected: false, value: 1} + ] + }, + { + schema: { + type: 'number', + exclusiveMaximum: 0 + }, + inputs: [ + {expected: true, value: -1}, + {expected: false, value: 0}, + {expected: false, value: 1} + ] + }, + + // Integer limits tests + { + schema: { + type: 'integer', + minimum: 0 + }, + inputs: [ + {expected: false, value: -1}, + {expected: true, value: 0}, + {expected: true, value: 1} + ] + }, + { + schema: { + type: 'integer', + exclusiveMinimum: 0 + }, + inputs: [ + {expected: false, value: -1}, + {expected: false, value: 0}, + {expected: true, value: 1} + ] + }, + { + schema: { + type: 'integer', + maximum: 0 + }, + inputs: [ + {expected: true, value: -1}, + {expected: true, value: 0}, + {expected: false, value: 1} + ] + }, + { + schema: { + type: 'integer', + exclusiveMaximum: 0 + }, + inputs: [ + {expected: true, value: -1}, + {expected: false, value: 0}, + {expected: false, value: 1} + ] + }, + { + schema: { + type: 'integer', + multipleOf: 2 + }, + inputs: [ + {expected: true, value: -2}, + {expected: false, value: -1}, + {expected: true, value: 0}, + {expected: false, value: 1}, + {expected: true, value: 2} + ] + }, + + // Numeric type tests + { + schema: { + type: 'number' + }, + inputs: [ + {expected: true, value: 0}, + {expected: true, value: 0.5}, + {expected: true, value: 1}, + {expected: false, value: '0'}, + {expected: false, value: null}, + {expected: false, value: []}, + {expected: false, value: {}} + ] + }, + { + schema: { + type: 'integer' + }, + inputs: [ + {expected: true, value: 0}, + {expected: false, value: 0.5}, + {expected: true, value: 1}, + {expected: false, value: '0'}, + {expected: false, value: null}, + {expected: false, value: []}, + {expected: false, value: {}} + ] + } + ]; + + for (const {schema, inputs} of data) { + for (const {expected, value} of inputs) { + const actual = schemaValidate(schema, value); + assert.strictEqual(actual, expected); + } + } +} + + +function testGetValidValueOrDefault1() { + const data = [ + // Test value defaulting on objects with additionalProperties=false + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'string', + default: 'default' + } + }, + additionalProperties: false + }, + inputs: [ + [ + void 0, + {test: 'default'} + ], + [ + null, + {test: 'default'} + ], + [ + 0, + {test: 'default'} + ], + [ + '', + {test: 'default'} + ], + [ + [], + {test: 'default'} + ], + [ + {}, + {test: 'default'} + ], + [ + {test: 'value'}, + {test: 'value'} + ], + [ + {test2: 'value2'}, + {test: 'default'} + ], + [ + {test: 'value', test2: 'value2'}, + {test: 'value'} + ] + ] + }, + + // Test value defaulting on objects with additionalProperties=true + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'string', + default: 'default' + } + }, + additionalProperties: true + }, + inputs: [ + [ + {}, + {test: 'default'} + ], + [ + {test: 'value'}, + {test: 'value'} + ], + [ + {test2: 'value2'}, + {test: 'default', test2: 'value2'} + ], + [ + {test: 'value', test2: 'value2'}, + {test: 'value', test2: 'value2'} + ] + ] + }, + + // Test value defaulting on objects with additionalProperties={schema} + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'string', + default: 'default' + } + }, + additionalProperties: { + type: 'number', + default: 10 + } + }, + inputs: [ + [ + {}, + {test: 'default'} + ], + [ + {test: 'value'}, + {test: 'value'} + ], + [ + {test2: 'value2'}, + {test: 'default', test2: 10} + ], + [ + {test: 'value', test2: 'value2'}, + {test: 'value', test2: 10} + ], + [ + {test2: 2}, + {test: 'default', test2: 2} + ], + [ + {test: 'value', test2: 2}, + {test: 'value', test2: 2} + ], + [ + {test: 'value', test2: 2, test3: null}, + {test: 'value', test2: 2, test3: 10} + ], + [ + {test: 'value', test2: 2, test3: void 0}, + {test: 'value', test2: 2, test3: 10} + ] + ] + }, + + // Test value defaulting where hasOwnProperty is false + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'string', + default: 'default' + } + } + }, + inputs: [ + [ + {}, + {test: 'default'} + ], + [ + {test: 'value'}, + {test: 'value'} + ], + [ + Object.create({test: 'value'}), + {test: 'default'} + ] + ] + }, + { + schema: { + type: 'object', + required: ['toString'], + properties: { + toString: { + type: 'string', + default: 'default' + } + } + }, + inputs: [ + [ + {}, + {toString: 'default'} + ], + [ + {toString: 'value'}, + {toString: 'value'} + ], + [ + Object.create({toString: 'value'}), + {toString: 'default'} + ] + ] + }, + + // Test enum + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'string', + default: 'value1', + enum: ['value1', 'value2', 'value3'] + } + } + }, + inputs: [ + [ + {test: 'value1'}, + {test: 'value1'} + ], + [ + {test: 'value2'}, + {test: 'value2'} + ], + [ + {test: 'value3'}, + {test: 'value3'} + ], + [ + {test: 'value4'}, + {test: 'value1'} + ] + ] + }, + + // Test valid vs invalid default + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'integer', + default: 2, + minimum: 1 + } + } + }, + inputs: [ + [ + {test: -1}, + {test: 2} + ] + ] + }, + { + schema: { + type: 'object', + required: ['test'], + properties: { + test: { + type: 'integer', + default: 1, + minimum: 2 + } + } + }, + inputs: [ + [ + {test: -1}, + {test: -1} + ] + ] + } + ]; + + for (const {schema, inputs} of data) { + for (const [value, expected] of inputs) { + const actual = getValidValueOrDefault(schema, value); + vm.assert.deepStrictEqual(actual, expected); + } + } +} + + +function testProxy1() { + const data = [ + // Object tests + { + schema: { + type: 'object', + required: ['test'], + additionalProperties: false, + properties: { + test: { + type: 'string', + default: 'default' + } + } + }, + tests: [ + {error: false, value: {test: 'default'}, action: (value) => { value.test = 'string'; }}, + {error: true, value: {test: 'default'}, action: (value) => { value.test = null; }}, + {error: true, value: {test: 'default'}, action: (value) => { delete value.test; }}, + {error: true, value: {test: 'default'}, action: (value) => { value.test2 = 'string'; }}, + {error: false, value: {test: 'default'}, action: (value) => { delete value.test2; }} + ] + }, + { + schema: { + type: 'object', + required: ['test'], + additionalProperties: true, + properties: { + test: { + type: 'string', + default: 'default' + } + } + }, + tests: [ + {error: false, value: {test: 'default'}, action: (value) => { value.test = 'string'; }}, + {error: true, value: {test: 'default'}, action: (value) => { value.test = null; }}, + {error: true, value: {test: 'default'}, action: (value) => { delete value.test; }}, + {error: false, value: {test: 'default'}, action: (value) => { value.test2 = 'string'; }}, + {error: false, value: {test: 'default'}, action: (value) => { delete value.test2; }} + ] + }, + { + schema: { + type: 'object', + required: ['test1'], + additionalProperties: false, + properties: { + test1: { + type: 'object', + required: ['test2'], + additionalProperties: false, + properties: { + test2: { + type: 'object', + required: ['test3'], + additionalProperties: false, + properties: { + test3: { + type: 'string', + default: 'default' + } + } + } + } + } + } + }, + tests: [ + {error: false, action: (value) => { value.test1.test2.test3 = 'string'; }}, + {error: true, action: (value) => { value.test1.test2.test3 = null; }}, + {error: true, action: (value) => { delete value.test1.test2.test3; }}, + {error: true, action: (value) => { value.test1.test2 = null; }}, + {error: true, action: (value) => { value.test1 = null; }}, + {error: true, action: (value) => { value.test4 = 'string'; }}, + {error: false, action: (value) => { delete value.test4; }} + ] + }, + + // Array tests + { + schema: { + type: 'array', + items: { + type: 'string', + default: 'default' + } + }, + tests: [ + {error: false, value: ['default'], action: (value) => { value[0] = 'string'; }}, + {error: true, value: ['default'], action: (value) => { value[0] = null; }}, + {error: true, value: ['default'], action: (value) => { delete value[0]; }}, + {error: false, value: ['default'], action: (value) => { value[1] = 'string'; }} + ] + } + ]; + + for (const {schema, tests} of data) { + for (let {error, value, action} of tests) { + if (typeof value === 'undefined') { value = getValidValueOrDefault(schema, void 0); } + assert.ok(schemaValidate(schema, value)); + console.log(error, value, schema); + const valueProxy = createProxy(schema, value); + if (error) { + assert.throws(() => action(valueProxy)); + } else { + assert.doesNotThrow(() => action(valueProxy)); + } + } + } +} + + +function main() { + testValidate1(); + testValidate2(); + testGetValidValueOrDefault1(); + testProxy1(); +} + + +if (require.main === module) { testMain(main); } diff --git a/test/test-schema.js b/test/test-schema.js deleted file mode 100644 index 7a1ea9bc..00000000 --- a/test/test-schema.js +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (C) 2020-2021 Yomichan Authors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -const assert = require('assert'); -const {testMain} = require('../dev/util'); -const {VM} = require('../dev/vm'); - -const vm = new VM(); -vm.execute([ - 'js/core.js', - 'js/general/cache-map.js', - 'js/data/json-schema.js' -]); -const JsonSchemaValidator = vm.get('JsonSchemaValidator'); - - -function testValidate1() { - const schema = { - allOf: [ - { - type: 'number' - }, - { - anyOf: [ - {minimum: 10, maximum: 100}, - {minimum: -100, maximum: -10} - ] - }, - { - oneOf: [ - {multipleOf: 3}, - {multipleOf: 5} - ] - }, - { - not: [ - {multipleOf: 20} - ] - } - ] - }; - - const schemaValidate = (value) => { - return new JsonSchemaValidator().isValid(value, schema); - }; - - const jsValidate = (value) => { - return ( - typeof value === 'number' && - ( - (value >= 10 && value <= 100) || - (value >= -100 && value <= -10) - ) && - ( - ( - (value % 3) === 0 || - (value % 5) === 0 - ) && - (value % 15) !== 0 - ) && - (value % 20) !== 0 - ); - }; - - for (let i = -111; i <= 111; i++) { - const actual = schemaValidate(i, schema); - const expected = jsValidate(i); - assert.strictEqual(actual, expected); - } -} - -function testValidate2() { - const data = [ - // String tests - { - schema: { - type: 'string' - }, - inputs: [ - {expected: false, value: null}, - {expected: false, value: void 0}, - {expected: false, value: 0}, - {expected: false, value: {}}, - {expected: false, value: []}, - {expected: true, value: ''} - ] - }, - { - schema: { - type: 'string', - minLength: 2 - }, - inputs: [ - {expected: false, value: ''}, - {expected: false, value: '1'}, - {expected: true, value: '12'}, - {expected: true, value: '123'} - ] - }, - { - schema: { - type: 'string', - maxLength: 2 - }, - inputs: [ - {expected: true, value: ''}, - {expected: true, value: '1'}, - {expected: true, value: '12'}, - {expected: false, value: '123'} - ] - }, - { - schema: { - type: 'string', - pattern: 'test' - }, - inputs: [ - {expected: false, value: ''}, - {expected: true, value: 'test'}, - {expected: false, value: 'TEST'}, - {expected: true, value: 'ABCtestDEF'}, - {expected: false, value: 'ABCTESTDEF'} - ] - }, - { - schema: { - type: 'string', - pattern: '^test$' - }, - inputs: [ - {expected: false, value: ''}, - {expected: true, value: 'test'}, - {expected: false, value: 'TEST'}, - {expected: false, value: 'ABCtestDEF'}, - {expected: false, value: 'ABCTESTDEF'} - ] - }, - { - schema: { - type: 'string', - pattern: '^test$', - patternFlags: 'i' - }, - inputs: [ - {expected: false, value: ''}, - {expected: true, value: 'test'}, - {expected: true, value: 'TEST'}, - {expected: false, value: 'ABCtestDEF'}, - {expected: false, value: 'ABCTESTDEF'} - ] - }, - { - schema: { - type: 'string', - pattern: '*' - }, - inputs: [ - {expected: false, value: ''} - ] - }, - { - schema: { - type: 'string', - pattern: '.', - patternFlags: '?' - }, - inputs: [ - {expected: false, value: ''} - ] - }, - - // Const tests - { - schema: { - const: 32 - }, - inputs: [ - {expected: true, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: '32' - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: true, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: null - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: true, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: {a: 'b'} - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - { - schema: { - const: [1, 2, 3] - }, - inputs: [ - {expected: false, value: 32}, - {expected: false, value: 0}, - {expected: false, value: '32'}, - {expected: false, value: null}, - {expected: false, value: {a: 'b'}}, - {expected: false, value: [1, 2, 3]} - ] - }, - - // Array contains tests - { - schema: { - type: 'array', - contains: {const: 32} - }, - inputs: [ - {expected: false, value: []}, - {expected: true, value: [32]}, - {expected: true, value: [1, 32]}, - {expected: true, value: [1, 32, 1]}, - {expected: false, value: [33]}, - {expected: false, value: [1, 33]}, - {expected: false, value: [1, 33, 1]} - ] - }, - - // Number limits tests - { - schema: { - type: 'number', - minimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: true, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'number', - exclusiveMinimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: false, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'number', - maximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: true, value: 0}, - {expected: false, value: 1} - ] - }, - { - schema: { - type: 'number', - exclusiveMaximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: false, value: 0}, - {expected: false, value: 1} - ] - }, - - // Integer limits tests - { - schema: { - type: 'integer', - minimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: true, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'integer', - exclusiveMinimum: 0 - }, - inputs: [ - {expected: false, value: -1}, - {expected: false, value: 0}, - {expected: true, value: 1} - ] - }, - { - schema: { - type: 'integer', - maximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: true, value: 0}, - {expected: false, value: 1} - ] - }, - { - schema: { - type: 'integer', - exclusiveMaximum: 0 - }, - inputs: [ - {expected: true, value: -1}, - {expected: false, value: 0}, - {expected: false, value: 1} - ] - }, - { - schema: { - type: 'integer', - multipleOf: 2 - }, - inputs: [ - {expected: true, value: -2}, - {expected: false, value: -1}, - {expected: true, value: 0}, - {expected: false, value: 1}, - {expected: true, value: 2} - ] - }, - - // Numeric type tests - { - schema: { - type: 'number' - }, - inputs: [ - {expected: true, value: 0}, - {expected: true, value: 0.5}, - {expected: true, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: false, value: {}} - ] - }, - { - schema: { - type: 'integer' - }, - inputs: [ - {expected: true, value: 0}, - {expected: false, value: 0.5}, - {expected: true, value: 1}, - {expected: false, value: '0'}, - {expected: false, value: null}, - {expected: false, value: []}, - {expected: false, value: {}} - ] - } - ]; - - const schemaValidate = (value, schema) => { - return new JsonSchemaValidator().isValid(value, schema); - }; - - for (const {schema, inputs} of data) { - for (const {expected, value} of inputs) { - const actual = schemaValidate(value, schema); - assert.strictEqual(actual, expected); - } - } -} - - -function testGetValidValueOrDefault1() { - const data = [ - // Test value defaulting on objects with additionalProperties=false - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - }, - additionalProperties: false - }, - inputs: [ - [ - void 0, - {test: 'default'} - ], - [ - null, - {test: 'default'} - ], - [ - 0, - {test: 'default'} - ], - [ - '', - {test: 'default'} - ], - [ - [], - {test: 'default'} - ], - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - {test2: 'value2'}, - {test: 'default'} - ], - [ - {test: 'value', test2: 'value2'}, - {test: 'value'} - ] - ] - }, - - // Test value defaulting on objects with additionalProperties=true - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - }, - additionalProperties: true - }, - inputs: [ - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - {test2: 'value2'}, - {test: 'default', test2: 'value2'} - ], - [ - {test: 'value', test2: 'value2'}, - {test: 'value', test2: 'value2'} - ] - ] - }, - - // Test value defaulting on objects with additionalProperties={schema} - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - }, - additionalProperties: { - type: 'number', - default: 10 - } - }, - inputs: [ - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - {test2: 'value2'}, - {test: 'default', test2: 10} - ], - [ - {test: 'value', test2: 'value2'}, - {test: 'value', test2: 10} - ], - [ - {test2: 2}, - {test: 'default', test2: 2} - ], - [ - {test: 'value', test2: 2}, - {test: 'value', test2: 2} - ], - [ - {test: 'value', test2: 2, test3: null}, - {test: 'value', test2: 2, test3: 10} - ], - [ - {test: 'value', test2: 2, test3: void 0}, - {test: 'value', test2: 2, test3: 10} - ] - ] - }, - - // Test value defaulting where hasOwnProperty is false - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'default' - } - } - }, - inputs: [ - [ - {}, - {test: 'default'} - ], - [ - {test: 'value'}, - {test: 'value'} - ], - [ - Object.create({test: 'value'}), - {test: 'default'} - ] - ] - }, - { - schema: { - type: 'object', - required: ['toString'], - properties: { - toString: { - type: 'string', - default: 'default' - } - } - }, - inputs: [ - [ - {}, - {toString: 'default'} - ], - [ - {toString: 'value'}, - {toString: 'value'} - ], - [ - Object.create({toString: 'value'}), - {toString: 'default'} - ] - ] - }, - - // Test enum - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'string', - default: 'value1', - enum: ['value1', 'value2', 'value3'] - } - } - }, - inputs: [ - [ - {test: 'value1'}, - {test: 'value1'} - ], - [ - {test: 'value2'}, - {test: 'value2'} - ], - [ - {test: 'value3'}, - {test: 'value3'} - ], - [ - {test: 'value4'}, - {test: 'value1'} - ] - ] - }, - - // Test valid vs invalid default - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'integer', - default: 2, - minimum: 1 - } - } - }, - inputs: [ - [ - {test: -1}, - {test: 2} - ] - ] - }, - { - schema: { - type: 'object', - required: ['test'], - properties: { - test: { - type: 'integer', - default: 1, - minimum: 2 - } - } - }, - inputs: [ - [ - {test: -1}, - {test: -1} - ] - ] - } - ]; - - for (const {schema, inputs} of data) { - for (const [value, expected] of inputs) { - const actual = new JsonSchemaValidator().getValidValueOrDefault(schema, value); - vm.assert.deepStrictEqual(actual, expected); - } - } -} - - -function main() { - testValidate1(); - testValidate2(); - testGetValidValueOrDefault1(); -} - - -if (require.main === module) { testMain(main); } -- cgit v1.2.3