diff options
Diffstat (limited to 'test/profile-conditions-util.test.js')
-rw-r--r-- | test/profile-conditions-util.test.js | 1090 |
1 files changed, 1090 insertions, 0 deletions
diff --git a/test/profile-conditions-util.test.js b/test/profile-conditions-util.test.js new file mode 100644 index 00000000..ca8b00ef --- /dev/null +++ b/test/profile-conditions-util.test.js @@ -0,0 +1,1090 @@ +/* + * Copyright (C) 2023 Yomitan Authors + * Copyright (C) 2020-2022 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/>. + */ + +import {expect, test} from 'vitest'; +import {ProfileConditionsUtil} from '../ext/js/background/profile-conditions-util.js'; + +function testNormalizeContext() { + test('NormalizeContext', () => { + const data = [ + // Empty + { + context: {}, + expected: {flags: []} + }, + + // Domain normalization + { + context: {url: ''}, + expected: {url: '', flags: []} + }, + { + context: {url: 'http://example.com/'}, + expected: {url: 'http://example.com/', domain: 'example.com', flags: []} + }, + { + context: {url: 'http://example.com:1234/'}, + expected: {url: 'http://example.com:1234/', domain: 'example.com', flags: []} + }, + { + context: {url: 'http://user@example.com:1234/'}, + expected: {url: 'http://user@example.com:1234/', domain: 'example.com', flags: []} + } + ]; + + for (const {context, expected} of data) { + const profileConditionsUtil = new ProfileConditionsUtil(); + const actual = profileConditionsUtil.normalizeContext(context); + expect(actual).toStrictEqual(expected); + } + }); +} + +function testSchemas() { + test('Schemas', () => { + 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']}} + ] + }, + + // flags tests + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'are', + value: '' + } + ] + } + ], + expectedSchema: { + required: ['flags'], + properties: { + flags: { + type: 'array', + maxItems: 0, + minItems: 0 + } + } + }, + inputs: [ + {expected: true, context: {}}, + {expected: true, context: {flags: []}}, + {expected: false, context: {flags: ['test1']}}, + {expected: false, context: {flags: ['test1', 'test2']}}, + {expected: false, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'are', + value: 'test1, test2' + } + ] + } + ], + expectedSchema: { + required: ['flags'], + properties: { + flags: { + type: 'array', + maxItems: 2, + minItems: 2, + allOf: [ + {contains: {const: 'test1'}}, + {contains: {const: 'test2'}} + ] + } + } + }, + inputs: [ + {expected: false, context: {}}, + {expected: false, context: {flags: []}}, + {expected: false, context: {flags: ['test1']}}, + {expected: true, context: {flags: ['test1', 'test2']}}, + {expected: false, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'areNot', + value: '' + } + ] + } + ], + expectedSchema: { + not: [ + { + required: ['flags'], + properties: { + flags: { + type: 'array', + maxItems: 0, + minItems: 0 + } + } + } + ] + }, + inputs: [ + {expected: false, context: {}}, + {expected: false, context: {flags: []}}, + {expected: true, context: {flags: ['test1']}}, + {expected: true, context: {flags: ['test1', 'test2']}}, + {expected: true, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'areNot', + value: 'test1, test2' + } + ] + } + ], + expectedSchema: { + not: [ + { + required: ['flags'], + properties: { + flags: { + type: 'array', + maxItems: 2, + minItems: 2, + allOf: [ + {contains: {const: 'test1'}}, + {contains: {const: 'test2'}} + ] + } + } + } + ] + }, + inputs: [ + {expected: true, context: {}}, + {expected: true, context: {flags: []}}, + {expected: true, context: {flags: ['test1']}}, + {expected: false, context: {flags: ['test1', 'test2']}}, + {expected: true, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'include', + value: '' + } + ] + } + ], + expectedSchema: { + required: ['flags'], + properties: { + flags: { + type: 'array', + minItems: 0 + } + } + }, + inputs: [ + {expected: true, context: {}}, + {expected: true, context: {flags: []}}, + {expected: true, context: {flags: ['test1']}}, + {expected: true, context: {flags: ['test1', 'test2']}}, + {expected: true, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'include', + value: 'test1, test2' + } + ] + } + ], + expectedSchema: { + required: ['flags'], + properties: { + flags: { + type: 'array', + minItems: 2, + allOf: [ + {contains: {const: 'test1'}}, + {contains: {const: 'test2'}} + ] + } + } + }, + inputs: [ + {expected: false, context: {}}, + {expected: false, context: {flags: []}}, + {expected: false, context: {flags: ['test1']}}, + {expected: true, context: {flags: ['test1', 'test2']}}, + {expected: true, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'notInclude', + value: '' + } + ] + } + ], + expectedSchema: { + required: ['flags'], + properties: { + flags: { + type: 'array' + } + } + }, + inputs: [ + {expected: true, context: {}}, + {expected: true, context: {flags: []}}, + {expected: true, context: {flags: ['test1']}}, + {expected: true, context: {flags: ['test1', 'test2']}}, + {expected: true, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + { + conditionGroups: [ + { + conditions: [ + { + type: 'flags', + operator: 'notInclude', + value: 'test1, test2' + } + ] + } + ], + expectedSchema: { + required: ['flags'], + properties: { + flags: { + type: 'array', + not: [ + {contains: {const: 'test1'}}, + {contains: {const: 'test2'}} + ] + } + } + }, + inputs: [ + {expected: true, context: {}}, + {expected: true, context: {flags: []}}, + {expected: false, context: {flags: ['test1']}}, + {expected: false, context: {flags: ['test1', 'test2']}}, + {expected: false, context: {flags: ['test1', 'test2', 'test3']}} + ] + }, + + // 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 profileConditionsUtil = new ProfileConditionsUtil(); + const schema = profileConditionsUtil.createSchema(conditionGroups); + if (typeof expectedSchema !== 'undefined') { + expect(schema.schema).toStrictEqual(expectedSchema); + } + if (Array.isArray(inputs)) { + for (const {expected, context} of inputs) { + const normalizedContext = profileConditionsUtil.normalizeContext(context); + const actual = schema.isValid(normalizedContext); + expect(actual).toStrictEqual(expected); + } + } + } + }); +} + + +function main() { + testNormalizeContext(); + testSchemas(); +} + +main(); |