2020-02-23 18:05:48 +00:00
|
|
|
/*
|
2022-02-03 01:43:10 +00:00
|
|
|
* Copyright (C) 2020-2022 Yomichan Authors
|
2020-02-23 18:05:48 +00:00
|
|
|
*
|
|
|
|
* 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 <https://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2020-02-17 19:20:22 +00:00
|
|
|
const assert = require('assert');
|
2020-11-07 16:34:14 +00:00
|
|
|
const {testMain} = require('../dev/util');
|
2020-09-19 23:04:28 +00:00
|
|
|
const {VM} = require('../dev/vm');
|
2020-02-17 19:20:22 +00:00
|
|
|
|
2020-03-03 03:20:47 +00:00
|
|
|
const vm = new VM();
|
2020-06-28 16:38:34 +00:00
|
|
|
vm.execute([
|
2021-02-14 03:52:28 +00:00
|
|
|
'js/core.js',
|
|
|
|
'js/general/cache-map.js',
|
2021-02-14 16:19:54 +00:00
|
|
|
'js/data/json-schema.js'
|
2020-06-28 16:38:34 +00:00
|
|
|
]);
|
2021-05-22 19:45:20 +00:00
|
|
|
const JsonSchema = vm.get('JsonSchema');
|
2020-02-17 19:20:22 +00:00
|
|
|
|
|
|
|
|
2021-05-22 18:01:32 +00:00
|
|
|
function schemaValidate(schema, value) {
|
2021-05-22 19:45:20 +00:00
|
|
|
return new JsonSchema(schema).isValid(value);
|
2021-05-22 18:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getValidValueOrDefault(schema, value) {
|
2021-05-22 19:45:20 +00:00
|
|
|
return new JsonSchema(schema).getValidValueOrDefault(value);
|
2021-05-22 18:01:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function createProxy(schema, value) {
|
2021-05-22 19:45:20 +00:00
|
|
|
return new JsonSchema(schema).createProxy(value);
|
2021-05-22 18:01:32 +00:00
|
|
|
}
|
|
|
|
|
2021-05-22 19:19:52 +00:00
|
|
|
function clone(value) {
|
|
|
|
return JSON.parse(JSON.stringify(value));
|
|
|
|
}
|
|
|
|
|
2021-05-22 18:01:32 +00:00
|
|
|
|
2020-02-17 19:20:22 +00:00
|
|
|
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)
|
|
|
|
) &&
|
|
|
|
(
|
|
|
|
(
|
2020-02-17 20:36:58 +00:00
|
|
|
(value % 3) === 0 ||
|
2020-02-17 19:20:22 +00:00
|
|
|
(value % 5) === 0
|
|
|
|
) &&
|
|
|
|
(value % 15) !== 0
|
|
|
|
) &&
|
|
|
|
(value % 20) !== 0
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
for (let i = -111; i <= 111; i++) {
|
2021-05-22 18:01:32 +00:00
|
|
|
const actual = schemaValidate(schema, i);
|
2020-02-17 19:20:22 +00:00
|
|
|
const expected = jsValidate(i);
|
|
|
|
assert.strictEqual(actual, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-09 18:18:59 +00:00
|
|
|
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: ''}
|
|
|
|
]
|
2020-08-11 23:21:26 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// 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}
|
|
|
|
]
|
|
|
|
},
|
2020-11-30 23:56:28 +00:00
|
|
|
{
|
|
|
|
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}
|
|
|
|
]
|
|
|
|
},
|
2020-08-11 23:21:26 +00:00
|
|
|
|
|
|
|
// 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: {}}
|
|
|
|
]
|
2021-05-23 19:49:25 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Reference tests
|
|
|
|
{
|
|
|
|
schema: {
|
|
|
|
definitions: {
|
|
|
|
example: {
|
|
|
|
type: 'number'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
},
|
|
|
|
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: {
|
|
|
|
definitions: {
|
|
|
|
example: {
|
|
|
|
type: 'integer'
|
|
|
|
}
|
|
|
|
},
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
},
|
|
|
|
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: {}}
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
schema: {
|
|
|
|
definitions: {
|
|
|
|
example: {
|
|
|
|
type: 'object',
|
|
|
|
additionalProperties: false,
|
|
|
|
properties: {
|
|
|
|
test: {
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
},
|
|
|
|
inputs: [
|
|
|
|
{expected: false, value: 0},
|
|
|
|
{expected: false, value: 0.5},
|
|
|
|
{expected: false, value: 1},
|
|
|
|
{expected: false, value: '0'},
|
|
|
|
{expected: false, value: null},
|
|
|
|
{expected: false, value: []},
|
|
|
|
{expected: true, value: {}},
|
|
|
|
{expected: false, value: {test: 0}},
|
|
|
|
{expected: false, value: {test: 0.5}},
|
|
|
|
{expected: false, value: {test: 1}},
|
|
|
|
{expected: false, value: {test: '0'}},
|
|
|
|
{expected: false, value: {test: null}},
|
|
|
|
{expected: false, value: {test: []}},
|
|
|
|
{expected: true, value: {test: {}}},
|
|
|
|
{expected: true, value: {test: {test: {}}}},
|
|
|
|
{expected: true, value: {test: {test: {test: {}}}}}
|
|
|
|
]
|
2020-08-09 18:18:59 +00:00
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const {schema, inputs} of data) {
|
|
|
|
for (const {expected, value} of inputs) {
|
2021-05-22 18:01:32 +00:00
|
|
|
const actual = schemaValidate(schema, value);
|
2020-08-09 18:18:59 +00:00
|
|
|
assert.strictEqual(actual, expected);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-17 19:20:22 +00:00
|
|
|
|
|
|
|
function testGetValidValueOrDefault1() {
|
2020-08-11 23:21:26 +00:00
|
|
|
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'}
|
|
|
|
]
|
|
|
|
]
|
2020-02-17 19:20:22 +00:00
|
|
|
},
|
|
|
|
|
2020-08-11 23:21:26 +00:00
|
|
|
// 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'}
|
|
|
|
]
|
|
|
|
]
|
2020-02-17 19:20:22 +00:00
|
|
|
},
|
|
|
|
|
2020-08-11 23:21:26 +00:00
|
|
|
// 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}
|
|
|
|
]
|
|
|
|
]
|
2020-10-27 23:40:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// 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'}
|
|
|
|
]
|
|
|
|
]
|
2020-11-30 23:56:28 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// 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}
|
|
|
|
]
|
|
|
|
]
|
2021-05-23 19:49:25 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Test references
|
|
|
|
{
|
|
|
|
schema: {
|
|
|
|
definitions: {
|
|
|
|
example: {
|
|
|
|
type: 'number',
|
|
|
|
default: 0
|
|
|
|
}
|
|
|
|
},
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
},
|
|
|
|
inputs: [
|
|
|
|
[
|
|
|
|
1,
|
|
|
|
1
|
|
|
|
],
|
|
|
|
[
|
|
|
|
null,
|
|
|
|
0
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'test',
|
|
|
|
0
|
|
|
|
],
|
|
|
|
[
|
|
|
|
{test: 'value'},
|
|
|
|
0
|
|
|
|
]
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
schema: {
|
|
|
|
definitions: {
|
|
|
|
example: {
|
|
|
|
type: 'object',
|
|
|
|
additionalProperties: false,
|
|
|
|
properties: {
|
|
|
|
test: {
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
},
|
|
|
|
inputs: [
|
|
|
|
[
|
|
|
|
1,
|
|
|
|
{}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
null,
|
|
|
|
{}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
'test',
|
|
|
|
{}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
{},
|
|
|
|
{}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
{test: {}},
|
|
|
|
{test: {}}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
{test: 'value'},
|
|
|
|
{test: {}}
|
|
|
|
],
|
|
|
|
[
|
|
|
|
{test: {test: {}}},
|
|
|
|
{test: {test: {}}}
|
|
|
|
]
|
|
|
|
]
|
2020-02-17 19:20:22 +00:00
|
|
|
}
|
|
|
|
];
|
|
|
|
|
2020-08-11 23:21:26 +00:00
|
|
|
for (const {schema, inputs} of data) {
|
|
|
|
for (const [value, expected] of inputs) {
|
2021-05-22 18:01:32 +00:00
|
|
|
const actual = getValidValueOrDefault(schema, value);
|
2020-08-11 23:21:26 +00:00
|
|
|
vm.assert.deepStrictEqual(actual, expected);
|
|
|
|
}
|
2020-02-17 19:20:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-05-22 18:01:32 +00:00
|
|
|
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; }},
|
2021-05-27 01:08:24 +00:00
|
|
|
{error: false, value: ['default'], action: (value) => { delete value[0]; }},
|
2021-05-24 22:53:42 +00:00
|
|
|
{error: false, value: ['default'], action: (value) => { value[1] = 'string'; }},
|
|
|
|
{error: false, value: ['default'], action: (value) => {
|
|
|
|
value[1] = 'string';
|
|
|
|
if (value.length !== 2) { throw new Error(`Invalid length; expected=2; actual=${value.length}`); }
|
|
|
|
if (typeof value.push !== 'function') { throw new Error(`Invalid push; expected=function; actual=${typeof value.push}`); }
|
|
|
|
}}
|
2021-05-22 18:01:32 +00:00
|
|
|
]
|
2021-05-23 19:49:25 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
// Reference tests
|
|
|
|
{
|
|
|
|
schema: {
|
|
|
|
definitions: {
|
|
|
|
example: {
|
|
|
|
type: 'object',
|
|
|
|
additionalProperties: false,
|
|
|
|
properties: {
|
|
|
|
test: {
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
$ref: '#/definitions/example'
|
|
|
|
},
|
|
|
|
tests: [
|
|
|
|
{error: false, value: {}, action: (value) => { value.test = {}; }},
|
|
|
|
{error: false, value: {}, action: (value) => { value.test = {}; value.test.test = {}; }},
|
|
|
|
{error: false, value: {}, action: (value) => { value.test = {test: {}}; }},
|
|
|
|
{error: true, value: {}, action: (value) => { value.test = null; }},
|
|
|
|
{error: true, value: {}, action: (value) => { value.test = 'string'; }},
|
|
|
|
{error: true, value: {}, action: (value) => { value.test = {}; value.test.test = 'string'; }},
|
|
|
|
{error: true, value: {}, action: (value) => { value.test = {test: 'string'}; }}
|
|
|
|
]
|
2021-05-22 18:01:32 +00:00
|
|
|
}
|
|
|
|
];
|
|
|
|
|
|
|
|
for (const {schema, tests} of data) {
|
|
|
|
for (let {error, value, action} of tests) {
|
|
|
|
if (typeof value === 'undefined') { value = getValidValueOrDefault(schema, void 0); }
|
2021-05-22 19:19:52 +00:00
|
|
|
value = clone(value);
|
2021-05-22 18:01:32 +00:00
|
|
|
assert.ok(schemaValidate(schema, value));
|
|
|
|
const valueProxy = createProxy(schema, value);
|
|
|
|
if (error) {
|
|
|
|
assert.throws(() => action(valueProxy));
|
|
|
|
} else {
|
|
|
|
assert.doesNotThrow(() => action(valueProxy));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-02-17 19:20:22 +00:00
|
|
|
function main() {
|
|
|
|
testValidate1();
|
2020-08-09 18:18:59 +00:00
|
|
|
testValidate2();
|
2020-02-17 19:20:22 +00:00
|
|
|
testGetValidValueOrDefault1();
|
2021-05-22 18:01:32 +00:00
|
|
|
testProxy1();
|
2020-02-17 19:20:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-11-07 16:34:14 +00:00
|
|
|
if (require.main === module) { testMain(main); }
|