From 60276d41ffd90044acc2f95e70b9b0c9a770417a Mon Sep 17 00:00:00 2001 From: Cashew <52880648+Scrub1492@users.noreply.github.com> Date: Sat, 6 Jan 2024 08:00:37 +0700 Subject: [PATCH] Test updates (#501) * update tests * japanese-util updates * update json-schema tests --- test/cache-map.test.js | 34 ++++------ test/core.test.js | 130 ++++++++++++++++++++++-------------- test/css-json.test.js | 8 +-- test/hotkey-util.test.js | 33 ++++++---- test/japanese-util.test.js | 132 ++++++++++++++++++++----------------- test/json-schema.test.js | 52 ++++++++++----- types/test/core.d.ts | 38 +++++++++++ 7 files changed, 261 insertions(+), 166 deletions(-) create mode 100644 types/test/core.d.ts diff --git a/test/cache-map.test.js b/test/cache-map.test.js index 9db306772b..5db35cf0c5 100644 --- a/test/cache-map.test.js +++ b/test/cache-map.test.js @@ -18,35 +18,27 @@ /* eslint-disable no-multi-spaces */ -import {expect, test} from 'vitest'; +import {describe, expect, test} from 'vitest'; import {CacheMap} from '../ext/js/general/cache-map.js'; /** */ function testConstructor() { - test('constructor', () => { - const data = [ - [false, () => new CacheMap(0)], - [false, () => new CacheMap(1)], - [false, () => new CacheMap(Number.MAX_VALUE)], - [true, () => new CacheMap(-1)], - [true, () => new CacheMap(1.5)], - [true, () => new CacheMap(Number.NaN)], - [true, () => new CacheMap(Number.POSITIVE_INFINITY)] - ]; + describe('constructor', () => { + const shouldThrow = [-1, 1.5, Number.NaN, Number.POSITIVE_INFINITY]; + const shouldNotThrow = [0, 1, Number.MAX_VALUE]; - for (const [throws, create] of data) { - if (throws) { - expect(create).toThrowError(); - } else { - expect(create).not.toThrowError(); - } - } + test.each(shouldNotThrow)('`() => new CacheMap(%d)` should not throw', (param) => { + expect(() => new CacheMap(param)).not.toThrowError(); + }); + test.each(shouldThrow)('`() => new CacheMap(%d)` should throw', (param) => { + expect(() => new CacheMap(param)).toThrowError(); + }); }); } /** */ function testApi() { - test('api', () => { + describe('api', () => { const data = [ { maxSize: 1, @@ -99,7 +91,7 @@ function testApi() { } ]; - for (const {maxSize, expectedSize, calls} of data) { + test.each(data)('api-test-%#', ({maxSize, expectedSize, calls}) => { const cache = new CacheMap(maxSize); expect(cache.maxSize).toStrictEqual(maxSize); for (const call of calls) { @@ -117,7 +109,7 @@ function testApi() { } } expect(cache.size).toStrictEqual(expectedSize); - } + }); }); } diff --git a/test/core.test.js b/test/core.test.js index 685bf9dcca..127df78300 100644 --- a/test/core.test.js +++ b/test/core.test.js @@ -21,11 +21,11 @@ import {DynamicProperty, deepEqual} from '../ext/js/core.js'; /** */ function testDynamicProperty() { - test('DynamicProperty', () => { + describe('DynamicProperty', () => { + /** @type {import('test/core').DynamicPropertyTestData} */ const data = [ { initialValue: 0, - /** @type {{operation: ?string, expectedDefaultValue: number, expectedValue: number, expectedOverrideCount: number, expeectedEventOccurred: boolean, args: [value: number, priority?: number]}[]} */ operations: [ { operation: null, @@ -33,7 +33,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 0, expectedOverrideCount: 0, - expeectedEventOccurred: false + expectedEventOccurred: false }, { operation: 'set.defaultValue', @@ -41,7 +41,7 @@ function testDynamicProperty() { expectedDefaultValue: 1, expectedValue: 1, expectedOverrideCount: 0, - expeectedEventOccurred: true + expectedEventOccurred: true }, { operation: 'set.defaultValue', @@ -49,7 +49,7 @@ function testDynamicProperty() { expectedDefaultValue: 1, expectedValue: 1, expectedOverrideCount: 0, - expeectedEventOccurred: false + expectedEventOccurred: false }, { operation: 'set.defaultValue', @@ -57,7 +57,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 0, expectedOverrideCount: 0, - expeectedEventOccurred: true + expectedEventOccurred: true }, { operation: 'setOverride', @@ -65,7 +65,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 8, expectedOverrideCount: 1, - expeectedEventOccurred: true + expectedEventOccurred: true }, { operation: 'setOverride', @@ -73,7 +73,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 8, expectedOverrideCount: 2, - expeectedEventOccurred: false + expectedEventOccurred: false }, { operation: 'setOverride', @@ -81,7 +81,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 32, expectedOverrideCount: 3, - expeectedEventOccurred: true + expectedEventOccurred: true }, { operation: 'setOverride', @@ -89,7 +89,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 32, expectedOverrideCount: 4, - expeectedEventOccurred: false + expectedEventOccurred: false }, { operation: 'clearOverride', @@ -97,7 +97,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 32, expectedOverrideCount: 3, - expeectedEventOccurred: false + expectedEventOccurred: false }, { operation: 'clearOverride', @@ -105,7 +105,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 32, expectedOverrideCount: 2, - expeectedEventOccurred: false + expectedEventOccurred: false }, { operation: 'clearOverride', @@ -113,7 +113,7 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 64, expectedOverrideCount: 1, - expeectedEventOccurred: true + expectedEventOccurred: true }, { operation: 'clearOverride', @@ -121,40 +121,42 @@ function testDynamicProperty() { expectedDefaultValue: 0, expectedValue: 0, expectedOverrideCount: 0, - expeectedEventOccurred: true + expectedEventOccurred: true } ] } ]; - for (const {initialValue, operations} of data) { - const property = new DynamicProperty(initialValue); - const overrideTokens = []; - let eventOccurred = false; - const onChange = () => { eventOccurred = true; }; - property.on('change', onChange); - for (const {operation, args, expectedDefaultValue, expectedValue, expectedOverrideCount, expeectedEventOccurred} of operations) { - eventOccurred = false; - switch (operation) { - case 'set.defaultValue': property.defaultValue = args[0]; break; - case 'setOverride': overrideTokens.push(property.setOverride(...args)); break; - case 'clearOverride': property.clearOverride(overrideTokens[overrideTokens.length + args[0]]); break; + describe.each(data)('Test DynamicProperty($initialValue)', ({initialValue, operations}) => { + test('works as expected', () => { + const property = new DynamicProperty(initialValue); + const overrideTokens = []; + let eventOccurred = false; + const onChange = () => { eventOccurred = true; }; + property.on('change', onChange); + for (const {operation, args, expectedDefaultValue, expectedValue, expectedOverrideCount, expectedEventOccurred} of operations) { + eventOccurred = false; + switch (operation) { + case 'set.defaultValue': property.defaultValue = args[0]; break; + case 'setOverride': overrideTokens.push(property.setOverride(...args)); break; + case 'clearOverride': property.clearOverride(overrideTokens[overrideTokens.length + args[0]]); break; + } + expect(eventOccurred).toStrictEqual(expectedEventOccurred); + expect(property.defaultValue).toStrictEqual(expectedDefaultValue); + expect(property.value).toStrictEqual(expectedValue); + expect(property.overrideCount).toStrictEqual(expectedOverrideCount); } - expect(eventOccurred).toStrictEqual(expeectedEventOccurred); - expect(property.defaultValue).toStrictEqual(expectedDefaultValue); - expect(property.value).toStrictEqual(expectedValue); - expect(property.overrideCount).toStrictEqual(expectedOverrideCount); - } - property.off('change', onChange); - } + property.off('change', onChange); + }); + }); }); } /** */ function testDeepEqual() { describe('deepEqual', () => { - const data = [ - // Simple tests + /** @type {import('test/core').DeepEqualTestData} */ + const simpleTestsData = [ { value1: 0, value2: 0, @@ -194,9 +196,10 @@ function testDeepEqual() { value1: true, value2: false, expected: false - }, - - // Simple object tests + } + ]; + /** @type {import('test/core').DeepEqualTestData} */ + const simpleObjectTestsData = [ { value1: {}, value2: {}, @@ -216,9 +219,10 @@ function testDeepEqual() { value1: {}, value2: null, expected: false - }, - - // Complex object tests + } + ]; + /** @type {import('test/core').DeepEqualTestData} */ + const complexObjectTestsData = [ { value1: [1], value2: [], @@ -259,27 +263,55 @@ function testDeepEqual() { value1: {test: {test2: [true]}}, value2: {test: {test2: [true]}}, expected: true - }, - - // Recursive + } + ]; + /** @type {import('test/core').DeepEqualTestData} */ + const recursiveTestsData = [ { value1: (() => { const x = {}; x.x = x; return x; })(), value2: (() => { const x = {}; x.x = x; return x; })(), expected: false } ]; + describe('simple tests', () => { + test.each(simpleTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { + const actual1 = deepEqual(value1, value2); + expect(actual1).toStrictEqual(expected); + + const actual2 = deepEqual(value2, value1); + expect(actual2).toStrictEqual(expected); + }); + }); + + describe('simple object tests', () => { + test.each(simpleObjectTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { + const actual1 = deepEqual(value1, value2); + expect(actual1).toStrictEqual(expected); + + const actual2 = deepEqual(value2, value1); + expect(actual2).toStrictEqual(expected); + }); + }); + + describe('complex object tests', () => { + test.each(complexObjectTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { + const actual1 = deepEqual(value1, value2); + expect(actual1).toStrictEqual(expected); + + const actual2 = deepEqual(value2, value1); + expect(actual2).toStrictEqual(expected); + }); + }); - let index = 0; - for (const {value1, value2, expected} of data) { - test(`${index}`, () => { + describe('recursive tests', () => { + test.each(recursiveTestsData)('deepEqual($value1, $value2) -> $expected', ({value1, value2, expected}) => { const actual1 = deepEqual(value1, value2); expect(actual1).toStrictEqual(expected); const actual2 = deepEqual(value2, value1); expect(actual2).toStrictEqual(expected); }); - ++index; - } + }); }); } diff --git a/test/css-json.test.js b/test/css-json.test.js index e4155ca3ab..588651d280 100644 --- a/test/css-json.test.js +++ b/test/css-json.test.js @@ -17,17 +17,17 @@ */ import fs from 'fs'; -import {expect, test} from 'vitest'; +import {describe, expect, test} from 'vitest'; import {formatRulesJson, generateRules, getTargets} from '../dev/generate-css-json'; /** */ function main() { - test('css-json', () => { - for (const {cssFilePath, overridesCssFilePath, outputPath} of getTargets()) { + describe('css-json', () => { + test.each(getTargets())('css-json-test-%#', ({cssFilePath, overridesCssFilePath, outputPath}) => { const actual = fs.readFileSync(outputPath, {encoding: 'utf8'}); const expected = formatRulesJson(generateRules(cssFilePath, overridesCssFilePath)); expect(actual).toStrictEqual(expected); - } + }); }); } diff --git a/test/hotkey-util.test.js b/test/hotkey-util.test.js index 5b8c4e73d1..d89d571d84 100644 --- a/test/hotkey-util.test.js +++ b/test/hotkey-util.test.js @@ -18,12 +18,12 @@ /* eslint-disable no-multi-spaces */ -import {expect, test} from 'vitest'; +import {describe, expect, test} from 'vitest'; import {HotkeyUtil} from '../ext/js/input/hotkey-util.js'; /** */ function testCommandConversions() { - test('CommandConversions', () => { + describe('CommandConversions', () => { /** @type {{os: import('environment').OperatingSystem, command: string, expectedCommand: string, expectedInput: {key: string, modifiers: import('input').Modifier[]}}[]} */ const data = [ {os: 'win', command: 'Alt+F', expectedCommand: 'Alt+F', expectedInput: {key: 'KeyF', modifiers: ['alt']}}, @@ -44,18 +44,20 @@ function testCommandConversions() { const hotkeyUtil = new HotkeyUtil(); for (const {command, os, expectedInput, expectedCommand} of data) { - hotkeyUtil.os = os; - const input = structuredClone(hotkeyUtil.convertCommandToInput(command)); - expect(input).toStrictEqual(expectedInput); - const command2 = hotkeyUtil.convertInputToCommand(input.key, input.modifiers); - expect(command2).toStrictEqual(expectedCommand); + test(`${command} on ${os} -> ${JSON.stringify(expectedInput)}`, () => { + hotkeyUtil.os = os; + const input = structuredClone(hotkeyUtil.convertCommandToInput(command)); + expect(input).toStrictEqual(expectedInput); + const command2 = hotkeyUtil.convertInputToCommand(input.key, input.modifiers); + expect(command2).toStrictEqual(expectedCommand); + }); } }); } /** */ function testDisplayNames() { - test('DisplayNames', () => { + describe('DisplayNames', () => { /** @type {{os: import('environment').OperatingSystem, key: ?string, modifiers: import('input').Modifier[], expected: string}[]} */ const data = [ {os: 'win', key: null, modifiers: [], expected: ''}, @@ -136,17 +138,18 @@ function testDisplayNames() { ]; const hotkeyUtil = new HotkeyUtil(); - for (const {os, key, modifiers, expected} of data) { + + test.each(data)('$key with $modifiers on $os -> display value $expected', ({os, key, modifiers, expected}) => { hotkeyUtil.os = os; const displayName = hotkeyUtil.getInputDisplayValue(key, modifiers); expect(displayName).toStrictEqual(expected); - } + }); }); } /** */ function testSortModifiers() { - test('SortModifiers', () => { + describe('SortModifiers', () => { /** @type {{modifiers: import('input').Modifier[], expected: import('input').Modifier[]}[]} */ const data = [ {modifiers: [], expected: []}, @@ -155,9 +158,11 @@ function testSortModifiers() { const hotkeyUtil = new HotkeyUtil(); for (const {modifiers, expected} of data) { - const modifiers2 = hotkeyUtil.sortModifiers(modifiers); - expect(modifiers2).toStrictEqual(modifiers); - expect(modifiers2).toStrictEqual(expected); + test(`[${modifiers}] -> [${expected}]`, () => { + const modifiers2 = hotkeyUtil.sortModifiers(modifiers); + expect(modifiers2).toStrictEqual(modifiers); + expect(modifiers2).toStrictEqual(expected); + }); } }); } diff --git a/test/japanese-util.test.js b/test/japanese-util.test.js index 6e594a2f97..177af4d5cf 100644 --- a/test/japanese-util.test.js +++ b/test/japanese-util.test.js @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import {expect, test} from 'vitest'; +import {describe, expect, test} from 'vitest'; import {TextSourceMap} from '../ext/js/general/text-source-map.js'; import {JapaneseUtil} from '../ext/js/language/sandbox/japanese-util.js'; import * as wanakana from '../ext/lib/wanakana.js'; @@ -25,7 +25,7 @@ const jp = new JapaneseUtil(wanakana); /** */ function testIsCodePointKanji() { - test('isCodePointKanji', () => { + describe('isCodePointKanji', () => { /** @type {[characters: string, expected: boolean][]} */ const data = [ ['力方', true], @@ -34,19 +34,19 @@ function testIsCodePointKanji() { ['逸逸', true] ]; - for (const [characters, expected] of data) { + test.each(data)('%s -> %o', (characters, expected) => { for (const character of characters) { const codePoint = /** @type {number} */ (character.codePointAt(0)); const actual = jp.isCodePointKanji(codePoint); expect(actual).toStrictEqual(expected); // `isCodePointKanji failed for ${character} (\\u{${codePoint.toString(16)}})` } - } + }); }); } /** */ function testIsCodePointKana() { - test('isCodePointKana', () => { + describe('isCodePointKana', () => { /** @type {[characters: string, expected: boolean][]} */ const data = [ ['かたカタ', true], @@ -54,19 +54,19 @@ function testIsCodePointKana() { ['\u53f1\u{20b9f}', false] ]; - for (const [characters, expected] of data) { + test.each(data)('%s -> %o', (characters, expected) => { for (const character of characters) { const codePoint = /** @type {number} */ (character.codePointAt(0)); const actual = jp.isCodePointKana(codePoint); expect(actual).toStrictEqual(expected); // `isCodePointKana failed for ${character} (\\u{${codePoint.toString(16)}})` } - } + }); }); } /** */ function testIsCodePointJapanese() { - test('isCodePointJapanese', () => { + describe('isCodePointJapanese', () => { /** @type {[characters: string, expected: boolean][]} */ const data = [ ['かたカタ力方々、。?', true], @@ -75,19 +75,19 @@ function testIsCodePointJapanese() { ['逸逸', true] ]; - for (const [characters, expected] of data) { + test.each(data)('%s -> %o', (characters, expected) => { for (const character of characters) { const codePoint = /** @type {number} */ (character.codePointAt(0)); const actual = jp.isCodePointJapanese(codePoint); expect(actual).toStrictEqual(expected); // `isCodePointJapanese failed for ${character} (\\u{${codePoint.toString(16)}})` } - } + }); }); } /** */ function testIsStringEntirelyKana() { - test('isStringEntirelyKana', () => { + describe('isStringEntirelyKana', () => { /** @type {[string: string, expected: boolean][]} */ const data = [ ['かたかな', true], @@ -103,15 +103,15 @@ function testIsStringEntirelyKana() { ['kata,.?かた', false] ]; - for (const [string, expected] of data) { + test.each(data)('%s -> %o', (string, expected) => { expect(jp.isStringEntirelyKana(string)).toStrictEqual(expected); - } + }); }); } /** */ function testIsStringPartiallyJapanese() { - test('isStringPartiallyJapanese', () => { + describe('isStringPartiallyJapanese', () => { /** @type {[string: string, expected: boolean][]} */ const data = [ ['かたかな', true], @@ -128,15 +128,15 @@ function testIsStringPartiallyJapanese() { ['逸逸', true] ]; - for (const [string, expected] of data) { + test.each(data)('%s -> %o', (string, expected) => { expect(jp.isStringPartiallyJapanese(string)).toStrictEqual(expected); - } + }); }); } /** */ function testConvertKatakanaToHiragana() { - test('convertKatakanaToHiragana', () => { + describe('convertKatakanaToHiragana', () => { /** @type {[string: string, expected: string, keepProlongedSoundMarks?: boolean][]} */ const data = [ ['かたかな', 'かたかな'], @@ -153,14 +153,16 @@ function testConvertKatakanaToHiragana() { ]; for (const [string, expected, keepProlongedSoundMarks = false] of data) { - expect(jp.convertKatakanaToHiragana(string, keepProlongedSoundMarks)).toStrictEqual(expected); + test(`${string}${keepProlongedSoundMarks ? ' keeping prolonged sound marks' : ''} -> ${expected}`, () => { + expect(jp.convertKatakanaToHiragana(string, keepProlongedSoundMarks)).toStrictEqual(expected); + }); } }); } /** */ function testConvertHiraganaToKatakana() { - test('ConvertHiraganaToKatakana', () => { + describe('ConvertHiraganaToKatakana', () => { /** @type {[string: string, expected: string][]} */ const data = [ ['かたかな', 'カタカナ'], @@ -174,15 +176,15 @@ function testConvertHiraganaToKatakana() { ['hiragana', 'hiragana'] ]; - for (const [string, expected] of data) { + test.each(data)('%s -> %o', (string, expected) => { expect(jp.convertHiraganaToKatakana(string)).toStrictEqual(expected); - } + }); }); } /** */ function testConvertToRomaji() { - test('ConvertToRomaji', () => { + describe('ConvertToRomaji', () => { /** @type {[string: string, expected: string][]} */ const data = [ ['かたかな', 'katakana'], @@ -196,15 +198,15 @@ function testConvertToRomaji() { ['hiragana', 'hiragana'] ]; - for (const [string, expected] of data) { + test.each(data)('%s -> %o', (string, expected) => { expect(jp.convertToRomaji(string)).toStrictEqual(expected); - } + }); }); } /** */ function testConvertNumericToFullWidth() { - test('ConvertNumericToFullWidth', () => { + describe('ConvertNumericToFullWidth', () => { /** @type {[string: string, expected: string][]} */ const data = [ ['0123456789', '0123456789'], @@ -213,15 +215,15 @@ function testConvertNumericToFullWidth() { ['ひらがな', 'ひらがな'] ]; - for (const [string, expected] of data) { + test.each(data)('%s -> %o', (string, expected) => { expect(jp.convertNumericToFullWidth(string)).toStrictEqual(expected); - } + }); }); } /** */ function testConvertHalfWidthKanaToFullWidth() { - test('ConvertHalfWidthKanaToFullWidth', () => { + describe('ConvertHalfWidthKanaToFullWidth', () => { /** @type {[string: string, expected: string, expectedSourceMapping?: number[]][]} */ const data = [ ['0123456789', '0123456789'], @@ -235,21 +237,23 @@ function testConvertHalfWidthKanaToFullWidth() { ]; for (const [string, expected, expectedSourceMapping] of data) { - const sourceMap = new TextSourceMap(string); - const actual1 = jp.convertHalfWidthKanaToFullWidth(string, null); - const actual2 = jp.convertHalfWidthKanaToFullWidth(string, sourceMap); - expect(actual1).toStrictEqual(expected); - expect(actual2).toStrictEqual(expected); - if (typeof expectedSourceMapping !== 'undefined') { - expect(sourceMap.equals(new TextSourceMap(string, expectedSourceMapping))).toBe(true); - } + test(`${string} -> ${expected}${typeof expectedSourceMapping !== 'undefined' ? ', ' + JSON.stringify(expectedSourceMapping) : ''}`, () => { + const sourceMap = new TextSourceMap(string); + const actual1 = jp.convertHalfWidthKanaToFullWidth(string, null); + const actual2 = jp.convertHalfWidthKanaToFullWidth(string, sourceMap); + expect(actual1).toStrictEqual(expected); + expect(actual2).toStrictEqual(expected); + if (typeof expectedSourceMapping !== 'undefined') { + expect(sourceMap.equals(new TextSourceMap(string, expectedSourceMapping))).toBe(true); + } + }); } }); } /** */ function testConvertAlphabeticToKana() { - test('ConvertAlphabeticToKana', () => { + describe('ConvertAlphabeticToKana', () => { /** @type {[string: string, expected: string, expectedSourceMapping?: number[]][]} */ const data = [ ['0123456789', '0123456789'], @@ -262,21 +266,23 @@ function testConvertAlphabeticToKana() { ]; for (const [string, expected, expectedSourceMapping] of data) { - const sourceMap = new TextSourceMap(string); - const actual1 = jp.convertAlphabeticToKana(string, null); - const actual2 = jp.convertAlphabeticToKana(string, sourceMap); - expect(actual1).toStrictEqual(expected); - expect(actual2).toStrictEqual(expected); - if (typeof expectedSourceMapping !== 'undefined') { - expect(sourceMap.equals(new TextSourceMap(string, expectedSourceMapping))).toBe(true); - } + test(`${string} -> ${string}${typeof expectedSourceMapping !== 'undefined' ? ', ' + JSON.stringify(expectedSourceMapping) : ''}`, () => { + const sourceMap = new TextSourceMap(string); + const actual1 = jp.convertAlphabeticToKana(string, null); + const actual2 = jp.convertAlphabeticToKana(string, sourceMap); + expect(actual1).toStrictEqual(expected); + expect(actual2).toStrictEqual(expected); + if (typeof expectedSourceMapping !== 'undefined') { + expect(sourceMap.equals(new TextSourceMap(string, expectedSourceMapping))).toBe(true); + } + }); } }); } /** */ function testDistributeFurigana() { - test('DistributeFurigana', () => { + describe('DistributeFurigana', () => { /** @type {[input: [term: string, reading: string], expected: {text: string, reading: string}[]][]} */ const data = [ [ @@ -736,16 +742,17 @@ function testDistributeFurigana() { ] ]; - for (const [[term, reading], expected] of data) { + test.each(data)('%o -> %o', (input, expected) => { + const [term, reading] = input; const actual = jp.distributeFurigana(term, reading); expect(actual).toStrictEqual(expected); - } + }); }); } /** */ function testDistributeFuriganaInflected() { - test('DistributeFuriganaInflected', () => { + describe('DistributeFuriganaInflected', () => { /** @type {[input: [term: string, reading: string, source: string], expected: {text: string, reading: string}[]][]} */ const data = [ [ @@ -789,16 +796,17 @@ function testDistributeFuriganaInflected() { ] ]; - for (const [[term, reading, source], expected] of data) { + test.each(data)('%o -> %o', (input, expected) => { + const [term, reading, source] = input; const actual = jp.distributeFuriganaInflected(term, reading, source); expect(actual).toStrictEqual(expected); - } + }); }); } /** */ function testCollapseEmphaticSequences() { - test('CollapseEmphaticSequences', () => { + describe('CollapseEmphaticSequences', () => { /** @type {[input: [text: string, fullCollapse: boolean], output: [expected: string, expectedSourceMapping: number[]]][]} */ const data = [ [['かこい', false], ['かこい', [1, 1, 1]]], @@ -840,7 +848,10 @@ function testCollapseEmphaticSequences() { [['っっっ', true], ['', [3]]] ]; - for (const [[text, fullCollapse], [expected, expectedSourceMapping]] of data) { + test.each(data)('%o -> %o', (input, output) => { + const [text, fullCollapse] = input; + const [expected, expectedSourceMapping] = output; + const sourceMap = new TextSourceMap(text); const actual1 = jp.collapseEmphaticSequences(text, fullCollapse, null); const actual2 = jp.collapseEmphaticSequences(text, fullCollapse, sourceMap); @@ -849,13 +860,13 @@ function testCollapseEmphaticSequences() { if (typeof expectedSourceMapping !== 'undefined') { expect(sourceMap.equals(new TextSourceMap(text, expectedSourceMapping))).toBe(true); } - } + }); }); } /** */ function testIsMoraPitchHigh() { - test('IsMoraPitchHigh', () => { + describe('IsMoraPitchHigh', () => { /** @type {[input: [moraIndex: number, pitchAccentDownstepPosition: number], expected: boolean][]} */ const data = [ [[0, 0], false], @@ -884,16 +895,17 @@ function testIsMoraPitchHigh() { [[3, 4], true] ]; - for (const [[moraIndex, pitchAccentDownstepPosition], expected] of data) { + test.each(data)('%o -> %o', (input, expected) => { + const [moraIndex, pitchAccentDownstepPosition] = input; const actual = jp.isMoraPitchHigh(moraIndex, pitchAccentDownstepPosition); expect(actual).toStrictEqual(expected); - } + }); }); } /** */ function testGetKanaMorae() { - test('GetKanaMorae', () => { + describe('GetKanaMorae', () => { /** @type {[text: string, expected: string[]][]} */ const data = [ ['かこ', ['か', 'こ']], @@ -907,10 +919,10 @@ function testGetKanaMorae() { ['ディスコ', ['ディ', 'ス', 'コ']] ]; - for (const [text, expected] of data) { + test.each(data)('%s -> %o', (text, expected) => { const actual = jp.getKanaMorae(text); expect(actual).toStrictEqual(expected); - } + }); }); } diff --git a/test/json-schema.test.js b/test/json-schema.test.js index 0c1a483bd8..4773e8986c 100644 --- a/test/json-schema.test.js +++ b/test/json-schema.test.js @@ -18,7 +18,7 @@ /* eslint-disable no-multi-spaces */ -import {expect, test} from 'vitest'; +import {describe, expect, test} from 'vitest'; import {parseJson} from '../dev/json.js'; import {JsonSchema} from '../ext/js/data/json-schema.js'; @@ -61,7 +61,7 @@ function clone(value) { /** */ function testValidate1() { - test('Validate1', () => { + describe('Validate1', () => { /** @type {import('ext/json-schema').Schema} */ const schema = { allOf: [ @@ -112,17 +112,19 @@ function testValidate1() { ); }; - for (let i = -111; i <= 111; i++) { - const actual = schemaValidate(schema, i); - const expected = jsValidate(i); - expect(actual).toStrictEqual(expected); - } + test('works as expected', () => { + for (let i = -111; i <= 111; i++) { + const actual = schemaValidate(schema, i); + const expected = jsValidate(i); + expect(actual).toStrictEqual(expected); + } + }); }); } /** */ function testValidate2() { - test('Validate2', () => { + describe('Validate2', () => { /** @type {{schema: import('ext/json-schema').Schema, inputs: {expected: boolean, value: unknown}[]}[]} */ const data = [ // String tests @@ -517,19 +519,19 @@ function testValidate2() { } ]; - for (const {schema, inputs} of data) { - for (const {expected, value} of inputs) { + describe.each(data)('Schema %#', ({schema, inputs}) => { + test.each(inputs)(`schemaValidate(${schema}, $value) -> $expected`, ({expected, value}) => { const actual = schemaValidate(schema, value); expect(actual).toStrictEqual(expected); - } - } + }); + }); }); } /** */ function testGetValidValueOrDefault1() { - test('GetValidValueOrDefault1', () => { + describe('GetValidValueOrDefault1', () => { /** @type {{schema: import('ext/json-schema').Schema, inputs: [value: unknown, expected: unknown][]}[]} */ const data = [ // Test value defaulting on objects with additionalProperties=false @@ -875,19 +877,19 @@ function testGetValidValueOrDefault1() { } ]; - for (const {schema, inputs} of data) { - for (const [value, expected] of inputs) { + describe.each(data)('Schema %#', ({schema, inputs}) => { + test.each(inputs)(`getValidValueOrDefault(${schema}, %o) -> %o`, (value, expected) => { const actual = getValidValueOrDefault(schema, value); expect(actual).toStrictEqual(expected); - } - } + }); + }); }); } /** */ function testProxy1() { - test('Proxy1', () => { + describe('Proxy1', () => { /** @type {{schema: import('ext/json-schema').Schema, tests: {error: boolean, value?: import('ext/json-schema').Value, action: (value: import('core').SafeAny) => void}[]}[]} */ const data = [ // Object tests @@ -1018,6 +1020,20 @@ function testProxy1() { } ]; + describe.each(data)('Schema %#', ({schema, tests}) => { + test.each(tests)('proxy %#', ({error, value, action}) => { + if (typeof value === 'undefined') { value = getValidValueOrDefault(schema, void 0); } + value = clone(value); + expect(schemaValidate(schema, value)).toBe(true); + const valueProxy = createProxy(schema, value); + if (error) { + expect(() => action(valueProxy)).toThrow(); + } else { + expect(() => action(valueProxy)).not.toThrow(); + } + }); + }); + for (const {schema, tests} of data) { for (let {error, value, action} of tests) { if (typeof value === 'undefined') { value = getValidValueOrDefault(schema, void 0); } diff --git a/types/test/core.d.ts b/types/test/core.d.ts new file mode 100644 index 0000000000..c01737e6bf --- /dev/null +++ b/types/test/core.d.ts @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2023 Yomitan 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 . + */ + +type Operation = 'set.defaultValue' | 'setOverride' | 'clearOverride'; + +type DynamicPropertyTestOperation = { + operation: Operation | null; + expectedDefaultValue: number; + expectedValue: number; + expectedOverrideCount: number; + expectedEventOccurred: boolean; + args: [value: number, priority?: number]; +}; + +export type DynamicPropertyTestData = { + initialValue: number; + operations: DynamicPropertyTestOperation[]; +}[]; + +export type DeepEqualTestData = { + value1: unknown; + value2: unknown; + expected: boolean; +}[];