yomichan/test/test-profile-conditions.js
toasted-nutbread 6a271e067f
Move mixed/js (#1383)
* Move mixed/js/core.js to js/core.js

* Move mixed/js/yomichan.js to js/yomichan.js

* Move mixed/js/timer.js to js/debug/timer.js

* Move mixed/js/hotkey-handler.js to js/input/hotkey-handler.js

* Move mixed/js/hotkey-help-controller.js to js/input/hotkey-help-controller.js

* Move mixed/js/hotkey-util.js to js/input/hotkey-util.js

* Move mixed/js/audio-system.js to js/input/audio-system.js

* Move mixed/js/media-loader.js to js/input/media-loader.js

* Move mixed/js/text-to-speech-audio.js to js/input/text-to-speech-audio.js

* Move mixed/js/comm.js to js/comm/cross-frame-api.js

* Move mixed/js/api.js to js/comm/api.js

* Move mixed/js/frame-client.js to js/comm/frame-client.js

* Move mixed/js/frame-endpoint.js to js/comm/frame-endpoint.js

* Move mixed/js/display.js to js/display/display.js

* Move mixed/js/display-audio.js to js/display/display-audio.js

* Move mixed/js/display-generator.js to js/display/display-generator.js

* Move mixed/js/display-history.js to js/display/display-history.js

* Move mixed/js/display-notification.js to js/display/display-notification.js

* Move mixed/js/display-profile-selection.js to js/display/display-profile-selection.js

* Move mixed/js/japanese.js to js/language/japanese-util.js

* Move mixed/js/dictionary-data-util.js to js/language/dictionary-data-util.js

* Move mixed/js/document-focus-controller.js to js/dom/document-focus-controller.js

* Move mixed/js/document-util.js to js/dom/document-util.js

* Move mixed/js/dom-data-binder.js to js/dom/dom-data-binder.js

* Move mixed/js/html-template-collection.js to js/dom/html-template-collection.js

* Move mixed/js/panel-element.js to js/dom/panel-element.js

* Move mixed/js/popup-menu.js to js/dom/popup-menu.js

* Move mixed/js/selector-observer.js to js/dom/selector-observer.js

* Move mixed/js/scroll.js to js/dom/window-scroll.js

* Move mixed/js/text-scanner.js to js/language/text-scanner.js

* Move mixed/js/cache-map.js to js/general/cache-map.js

* Move mixed/js/object-property-accessor.js to js/general/object-property-accessor.js

* Move mixed/js/task-accumulator.js to js/general/task-accumulator.js

* Move mixed/js/environment.js to js/background/environment.js

* Move mixed/js/dynamic-loader.js to js/scripting/dynamic-loader.js

* Move mixed/js/dynamic-loader-sentinel.js to js/scripting/dynamic-loader-sentinel.js
2021-02-13 22:52:28 -05:00

844 lines
30 KiB
JavaScript

/*
* 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 <https://www.gnu.org/licenses/>.
*/
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',
'bg/js/json-schema.js',
'bg/js/profile-conditions.js'
]);
const [JsonSchemaValidator, ProfileConditions] = vm.get(['JsonSchemaValidator', 'ProfileConditions']);
function schemaValidate(value, schema) {
return new JsonSchemaValidator().isValid(value, schema);
}
function testNormalizeContext() {
const data = [
// Empty
{
context: {},
expected: {}
},
// Domain normalization
{
context: {url: ''},
expected: {url: ''}
},
{
context: {url: 'http://example.com/'},
expected: {url: 'http://example.com/', domain: 'example.com'}
},
{
context: {url: 'http://example.com:1234/'},
expected: {url: 'http://example.com:1234/', domain: 'example.com'}
},
{
context: {url: 'http://user@example.com:1234/'},
expected: {url: 'http://user@example.com:1234/', domain: 'example.com'}
}
];
for (const {context, expected} of data) {
const profileConditions = new ProfileConditions();
const actual = profileConditions.normalizeContext(context);
vm.assert.deepStrictEqual(actual, expected);
}
}
function testSchemas() {
const data = [
// Empty
{
conditionGroups: [],
expectedSchema: {},
inputs: [
{expected: true, context: {url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{conditions: []}
],
expectedSchema: {},
inputs: [
{expected: true, context: {url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{conditions: []},
{conditions: []}
],
expectedSchema: {},
inputs: [
{expected: true, context: {url: 'http://example.com/'}}
]
},
// popupLevel tests
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'equal',
value: '0'
}
]
}
],
expectedSchema: {
properties: {
depth: {const: 0}
},
required: ['depth']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: false, context: {depth: 1, url: 'http://example.com/'}},
{expected: false, context: {depth: -1, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'notEqual',
value: '0'
}
]
}
],
expectedSchema: {
not: [
{
properties: {
depth: {const: 0}
},
required: ['depth']
}
]
},
inputs: [
{expected: false, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 1, url: 'http://example.com/'}},
{expected: true, context: {depth: -1, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'lessThan',
value: '0'
}
]
}
],
expectedSchema: {
properties: {
depth: {
type: 'number',
exclusiveMaximum: 0
}
},
required: ['depth']
},
inputs: [
{expected: false, context: {depth: 0, url: 'http://example.com/'}},
{expected: false, context: {depth: 1, url: 'http://example.com/'}},
{expected: true, context: {depth: -1, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'greaterThan',
value: '0'
}
]
}
],
expectedSchema: {
properties: {
depth: {
type: 'number',
exclusiveMinimum: 0
}
},
required: ['depth']
},
inputs: [
{expected: false, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 1, url: 'http://example.com/'}},
{expected: false, context: {depth: -1, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'lessThanOrEqual',
value: '0'
}
]
}
],
expectedSchema: {
properties: {
depth: {
type: 'number',
maximum: 0
}
},
required: ['depth']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: false, context: {depth: 1, url: 'http://example.com/'}},
{expected: true, context: {depth: -1, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'greaterThanOrEqual',
value: '0'
}
]
}
],
expectedSchema: {
properties: {
depth: {
type: 'number',
minimum: 0
}
},
required: ['depth']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 1, url: 'http://example.com/'}},
{expected: false, context: {depth: -1, url: 'http://example.com/'}}
]
},
// url tests
{
conditionGroups: [
{
conditions: [
{
type: 'url',
operator: 'matchDomain',
value: 'example.com'
}
]
}
],
expectedSchema: {
properties: {
domain: {
oneOf: [
{const: 'example.com'}
]
}
},
required: ['domain']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: false, context: {depth: 0, url: 'http://example1.com/'}},
{expected: false, context: {depth: 0, url: 'http://example2.com/'}},
{expected: true, context: {depth: 0, url: 'http://example.com:1234/'}},
{expected: true, context: {depth: 0, url: 'http://user@example.com:1234/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'url',
operator: 'matchDomain',
value: 'example.com, example1.com, example2.com'
}
]
}
],
expectedSchema: {
properties: {
domain: {
oneOf: [
{const: 'example.com'},
{const: 'example1.com'},
{const: 'example2.com'}
]
}
},
required: ['domain']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 0, url: 'http://example1.com/'}},
{expected: true, context: {depth: 0, url: 'http://example2.com/'}},
{expected: false, context: {depth: 0, url: 'http://example3.com/'}},
{expected: true, context: {depth: 0, url: 'http://example.com:1234/'}},
{expected: true, context: {depth: 0, url: 'http://user@example.com:1234/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'url',
operator: 'matchRegExp',
value: '^http://example\\d?\\.com/[\\w\\W]*$'
}
]
}
],
expectedSchema: {
properties: {
url: {
type: 'string',
pattern: '^http://example\\d?\\.com/[\\w\\W]*$',
patternFlags: 'i'
}
},
required: ['url']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 0, url: 'http://example1.com/'}},
{expected: true, context: {depth: 0, url: 'http://example2.com/'}},
{expected: true, context: {depth: 0, url: 'http://example3.com/'}},
{expected: true, context: {depth: 0, url: 'http://example.com/example'}},
{expected: false, context: {depth: 0, url: 'http://example.com:1234/'}},
{expected: false, context: {depth: 0, url: 'http://user@example.com:1234/'}},
{expected: false, context: {depth: 0, url: 'http://example-1.com/'}}
]
},
// modifierKeys tests
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'are',
value: ''
}
]
}
],
expectedSchema: {
properties: {
modifierKeys: {
type: 'array',
maxItems: 0,
minItems: 0
}
},
required: ['modifierKeys']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'are',
value: 'Alt, Shift'
}
]
}
],
expectedSchema: {
properties: {
modifierKeys: {
type: 'array',
maxItems: 2,
minItems: 2,
allOf: [
{contains: {const: 'Alt'}},
{contains: {const: 'Shift'}}
]
}
},
required: ['modifierKeys']
},
inputs: [
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'areNot',
value: ''
}
]
}
],
expectedSchema: {
not: [
{
properties: {
modifierKeys: {
type: 'array',
maxItems: 0,
minItems: 0
}
},
required: ['modifierKeys']
}
]
},
inputs: [
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'areNot',
value: 'Alt, Shift'
}
]
}
],
expectedSchema: {
not: [
{
properties: {
modifierKeys: {
type: 'array',
maxItems: 2,
minItems: 2,
allOf: [
{contains: {const: 'Alt'}},
{contains: {const: 'Shift'}}
]
}
},
required: ['modifierKeys']
}
]
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'include',
value: ''
}
]
}
],
expectedSchema: {
properties: {
modifierKeys: {
type: 'array',
minItems: 0
}
},
required: ['modifierKeys']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'include',
value: 'Alt, Shift'
}
]
}
],
expectedSchema: {
properties: {
modifierKeys: {
type: 'array',
minItems: 2,
allOf: [
{contains: {const: 'Alt'}},
{contains: {const: 'Shift'}}
]
}
},
required: ['modifierKeys']
},
inputs: [
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'notInclude',
value: ''
}
]
}
],
expectedSchema: {
properties: {
modifierKeys: {
type: 'array'
}
},
required: ['modifierKeys']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'modifierKeys',
operator: 'notInclude',
value: 'Alt, Shift'
}
]
}
],
expectedSchema: {
properties: {
modifierKeys: {
type: 'array',
not: [
{contains: {const: 'Alt'}},
{contains: {const: 'Shift'}}
]
}
},
required: ['modifierKeys']
},
inputs: [
{expected: true, context: {depth: 0, url: 'http://example.com/', modifierKeys: []}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt']}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift']}},
{expected: false, context: {depth: 0, url: 'http://example.com/', modifierKeys: ['Alt', 'Shift', 'Ctrl']}}
]
},
// Multiple conditions tests
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'greaterThan',
value: '0'
},
{
type: 'popupLevel',
operator: 'lessThan',
value: '3'
}
]
}
],
expectedSchema: {
allOf: [
{
properties: {
depth: {
type: 'number',
exclusiveMinimum: 0
}
},
required: ['depth']
},
{
properties: {
depth: {
type: 'number',
exclusiveMaximum: 3
}
},
required: ['depth']
}
]
},
inputs: [
{expected: false, context: {depth: -2, url: 'http://example.com/'}},
{expected: false, context: {depth: -1, url: 'http://example.com/'}},
{expected: false, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 1, url: 'http://example.com/'}},
{expected: true, context: {depth: 2, url: 'http://example.com/'}},
{expected: false, context: {depth: 3, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'greaterThan',
value: '0'
},
{
type: 'popupLevel',
operator: 'lessThan',
value: '3'
}
]
},
{
conditions: [
{
type: 'popupLevel',
operator: 'equal',
value: '0'
}
]
}
],
expectedSchema: {
anyOf: [
{
allOf: [
{
properties: {
depth: {
type: 'number',
exclusiveMinimum: 0
}
},
required: ['depth']
},
{
properties: {
depth: {
type: 'number',
exclusiveMaximum: 3
}
},
required: ['depth']
}
]
},
{
properties: {
depth: {const: 0}
},
required: ['depth']
}
]
},
inputs: [
{expected: false, context: {depth: -2, url: 'http://example.com/'}},
{expected: false, context: {depth: -1, url: 'http://example.com/'}},
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 1, url: 'http://example.com/'}},
{expected: true, context: {depth: 2, url: 'http://example.com/'}},
{expected: false, context: {depth: 3, url: 'http://example.com/'}}
]
},
{
conditionGroups: [
{
conditions: [
{
type: 'popupLevel',
operator: 'greaterThan',
value: '0'
},
{
type: 'popupLevel',
operator: 'lessThan',
value: '3'
}
]
},
{
conditions: [
{
type: 'popupLevel',
operator: 'lessThanOrEqual',
value: '0'
},
{
type: 'popupLevel',
operator: 'greaterThanOrEqual',
value: '-1'
}
]
}
],
expectedSchema: {
anyOf: [
{
allOf: [
{
properties: {
depth: {
type: 'number',
exclusiveMinimum: 0
}
},
required: ['depth']
},
{
properties: {
depth: {
type: 'number',
exclusiveMaximum: 3
}
},
required: ['depth']
}
]
},
{
allOf: [
{
properties: {
depth: {
type: 'number',
maximum: 0
}
},
required: ['depth']
},
{
properties: {
depth: {
type: 'number',
minimum: -1
}
},
required: ['depth']
}
]
}
]
},
inputs: [
{expected: false, context: {depth: -2, url: 'http://example.com/'}},
{expected: true, context: {depth: -1, url: 'http://example.com/'}},
{expected: true, context: {depth: 0, url: 'http://example.com/'}},
{expected: true, context: {depth: 1, url: 'http://example.com/'}},
{expected: true, context: {depth: 2, url: 'http://example.com/'}},
{expected: false, context: {depth: 3, url: 'http://example.com/'}}
]
}
];
for (const {conditionGroups, expectedSchema, inputs} of data) {
const profileConditions = new ProfileConditions();
const schema = profileConditions.createSchema(conditionGroups);
if (typeof expectedSchema !== 'undefined') {
vm.assert.deepStrictEqual(schema, expectedSchema);
}
if (Array.isArray(inputs)) {
for (const {expected, context} of inputs) {
const normalizedContext = profileConditions.normalizeContext(context);
const actual = schemaValidate(normalizedContext, schema);
assert.strictEqual(actual, expected);
}
}
}
}
function main() {
testNormalizeContext();
testSchemas();
}
if (require.main === module) { testMain(main); }