diff options
| author | Darius Jahandarie <djahandarie@gmail.com> | 2023-12-06 03:53:16 +0000 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-06 03:53:16 +0000 | 
| commit | bd5bc1a5db29903bc098995cd9262c4576bf76af (patch) | |
| tree | c9214189e0214480fcf6539ad1c6327aef6cbd1c /test | |
| parent | fd6bba8a2a869eaf2b2c1fa49001f933fce3c618 (diff) | |
| parent | 23e6fb76319c9ed7c9bcdc3efba39bc5dd38f288 (diff) | |
Merge pull request #339 from toasted-nutbread/type-annotations
Type annotations
Diffstat (limited to 'test')
26 files changed, 1085 insertions, 549 deletions
| diff --git a/test/anki-note-builder.test.js b/test/anki-note-builder.test.js index e21aa993..96dacab6 100644 --- a/test/anki-note-builder.test.js +++ b/test/anki-note-builder.test.js @@ -26,8 +26,14 @@ import {TranslatorVM} from '../dev/translator-vm.js';  import {AnkiNoteBuilder} from '../ext/js/data/anki-note-builder.js';  import {JapaneseUtil} from '../ext/js/language/sandbox/japanese-util.js'; -vi.stubGlobal('fetch', async (url2) => { -    const extDir = path.join(__dirname, '..', 'ext'); +const dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * @param {string} url2 + * @returns {Promise<import('dev/vm').PseudoFetchResponse>} + */ +async function fetch(url2) { +    const extDir = path.join(dirname, '..', 'ext');      let filePath;      try {          filePath = url.fileURLToPath(url2); @@ -43,11 +49,13 @@ vi.stubGlobal('fetch', async (url2) => {          text: async () => Promise.resolve(content.toString('utf8')),          json: async () => Promise.resolve(JSON.parse(content.toString('utf8')))      }; -}); +} +vi.stubGlobal('fetch', fetch);  vi.mock('../ext/js/templates/template-renderer-proxy.js'); -const dirname = path.dirname(fileURLToPath(import.meta.url)); - +/** + * @returns {Promise<TranslatorVM>} + */  async function createVM() {      const dictionaryDirectory = path.join(dirname, 'data', 'dictionaries', 'valid-dictionary1');      const vm = new TranslatorVM(); @@ -57,6 +65,10 @@ async function createVM() {      return vm;  } +/** + * @param {'terms'|'kanji'} type + * @returns {string[]} + */  function getFieldMarkers(type) {      switch (type) {          case 'terms': @@ -117,8 +129,17 @@ function getFieldMarkers(type) {      }  } +/** + * @param {import('dictionary').DictionaryEntry[]} dictionaryEntries + * @param {'terms'|'kanji'} type + * @param {import('settings').ResultOutputMode} mode + * @param {string} template + * @param {import('@vitest/expect').ExpectStatic} expect + * @returns {Promise<import('anki').NoteFields[]>} + */  async function getRenderResults(dictionaryEntries, type, mode, template, expect) {      const markers = getFieldMarkers(type); +    /** @type {import('anki-note-builder').Field[]} */      const fields = [];      for (const marker of markers) {          fields.push([marker, `{${marker}}`]); @@ -151,9 +172,10 @@ async function getRenderResults(dictionaryEntries, type, mode, template, expect)              query: 'query',              fullQuery: 'fullQuery'          }; -        const {note: {fields: noteFields}, errors} = await ankiNoteBuilder.createNote({ +        /** @type {import('anki-note-builder').CreateNoteDetails} */ +        const details = {              dictionaryEntry, -            mode: null, +            mode: 'test',              context,              template,              deckName: 'deckName', @@ -165,8 +187,11 @@ async function getRenderResults(dictionaryEntries, type, mode, template, expect)              duplicateScopeCheckAllModels: false,              resultOutputMode: mode,              glossaryLayoutMode: 'default', -            compactTags: false -        }); +            compactTags: false, +            requirements: [], +            mediaOptions: null +        }; +        const {note: {fields: noteFields}, errors} = await ankiNoteBuilder.createNote(details);          for (const error of errors) {              console.error(error);          } @@ -178,6 +203,7 @@ async function getRenderResults(dictionaryEntries, type, mode, template, expect)  } +/** */  async function main() {      const vm = await createVM(); @@ -199,6 +225,7 @@ async function main() {                      case 'findTerms':                          {                              const {name, mode, text} = t; +                            /** @type {import('translation').FindTermsOptions} */                              const options = vm.buildOptions(optionsPresets, t.options);                              const {dictionaryEntries} = structuredClone(await vm.translator.findTerms(mode, text, options));                              const results = mode !== 'simple' ? structuredClone(await getRenderResults(dictionaryEntries, 'terms', mode, template, expect)) : null; @@ -209,9 +236,10 @@ async function main() {                      case 'findKanji':                          {                              const {name, text} = t; +                            /** @type {import('translation').FindKanjiOptions} */                              const options = vm.buildOptions(optionsPresets, t.options);                              const dictionaryEntries = structuredClone(await vm.translator.findKanji(text, options)); -                            const results = structuredClone(await getRenderResults(dictionaryEntries, 'kanji', null, template, expect)); +                            const results = structuredClone(await getRenderResults(dictionaryEntries, 'kanji', 'split', template, expect));                              actualResults1.push({name, results});                              expect(results).toStrictEqual(expected1.results);                          } diff --git a/test/cache-map.test.js b/test/cache-map.test.js index 9d10a719..df891188 100644 --- a/test/cache-map.test.js +++ b/test/cache-map.test.js @@ -19,6 +19,7 @@  import {expect, test} from 'vitest';  import {CacheMap} from '../ext/js/general/cache-map.js'; +/** */  function testConstructor() {      test('constructor', () => {          const data = [ @@ -29,6 +30,7 @@ function testConstructor() {              [true,  () => new CacheMap(1.5)],              [true,  () => new CacheMap(Number.NaN)],              [true,  () => new CacheMap(Number.POSITIVE_INFINITY)], +            // @ts-expect-error - Ignore because it should throw an error              [true,  () => new CacheMap('a')]          ]; @@ -42,6 +44,7 @@ function testConstructor() {      });  } +/** */  function testApi() {      test('api', () => {          const data = [ @@ -103,10 +106,10 @@ function testApi() {                  const {func, args} = call;                  let returnValue;                  switch (func) { -                    case 'get': returnValue = cache.get(...args); break; -                    case 'set': returnValue = cache.set(...args); break; -                    case 'has': returnValue = cache.has(...args); break; -                    case 'clear': returnValue = cache.clear(...args); break; +                    case 'get': returnValue = cache.get(args[0]); break; +                    case 'set': returnValue = cache.set(args[0], args[1]); break; +                    case 'has': returnValue = cache.has(args[0]); break; +                    case 'clear': returnValue = cache.clear(); break;                  }                  if (Object.prototype.hasOwnProperty.call(call, 'returnValue')) {                      const {returnValue: expectedReturnValue} = call; @@ -119,6 +122,7 @@ function testApi() {  } +/** */  function main() {      testConstructor();      testApi(); diff --git a/test/core.test.js b/test/core.test.js index 203460f4..685bf9dc 100644 --- a/test/core.test.js +++ b/test/core.test.js @@ -19,14 +19,17 @@  import {describe, expect, test} from 'vitest';  import {DynamicProperty, deepEqual} from '../ext/js/core.js'; +/** */  function testDynamicProperty() {      test('DynamicProperty', () => {          const data = [              {                  initialValue: 0, +                /** @type {{operation: ?string, expectedDefaultValue: number, expectedValue: number, expectedOverrideCount: number, expeectedEventOccurred: boolean, args: [value: number, priority?: number]}[]} */                  operations: [                      {                          operation: null, +                        args: [0],                          expectedDefaultValue: 0,                          expectedValue: 0,                          expectedOverrideCount: 0, @@ -147,6 +150,7 @@ function testDynamicProperty() {      });  } +/** */  function testDeepEqual() {      describe('deepEqual', () => {          const data = [ @@ -280,6 +284,7 @@ function testDeepEqual() {  } +/** */  function main() {      testDynamicProperty();      testDeepEqual(); diff --git a/test/css-json.test.js b/test/css-json.test.js index 0aaf7d10..66ecfeba 100644 --- a/test/css-json.test.js +++ b/test/css-json.test.js @@ -20,6 +20,7 @@ import fs from 'fs';  import {expect, test} from 'vitest';  import {formatRulesJson, generateRules, getTargets} from '../dev/generate-css-json'; +/** */  function main() {      test('css-json', () => {          for (const {cssFile, overridesCssFile, outputPath} of getTargets()) { diff --git a/test/data/anki-note-builder-test-results.json b/test/data/anki-note-builder-test-results.json index b752e878..49542e39 100644 --- a/test/data/anki-note-builder-test-results.json +++ b/test/data/anki-note-builder-test-results.json @@ -194,7 +194,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -224,7 +224,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", @@ -379,7 +379,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 24</li><li>Test Dictionary 2: 30</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: eighteen</li><li>Test Dictionary 2: twenty-four (24)</li><li>Test Dictionary 2: 30</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[う]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>uchikomu definition 3</li><li>uchikomu definition 4</li></ul></div>", @@ -409,7 +409,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 25</li><li>Test Dictionary 2: 31</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: nineteen</li><li>Test Dictionary 2: twenty-five (25)</li><li>Test Dictionary 2: thirty-one</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[ぶ]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>buchikomu definition 3</li><li>buchikomu definition 4</li></ul></div>", @@ -499,7 +499,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -529,7 +529,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", @@ -759,7 +759,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -824,7 +824,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", @@ -889,7 +889,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 24</li><li>Test Dictionary 2: 30</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: eighteen</li><li>Test Dictionary 2: twenty-four (24)</li><li>Test Dictionary 2: 30</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[う]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>uchikomu definition 3</li><li>uchikomu definition 4</li></ul></div>", @@ -949,7 +949,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -1014,7 +1014,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 25</li><li>Test Dictionary 2: 31</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: nineteen</li><li>Test Dictionary 2: twenty-five (25)</li><li>Test Dictionary 2: thirty-one</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[ぶ]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>buchikomu definition 3</li><li>buchikomu definition 4</li></ul></div>", @@ -1074,7 +1074,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", @@ -1526,7 +1526,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 24</li><li>Test Dictionary 2: 30</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: eighteen</li><li>Test Dictionary 2: twenty-four (24)</li><li>Test Dictionary 2: 30</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[う]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>uchikomu definition 3</li><li>uchikomu definition 4</li></ul></div>", @@ -1556,7 +1556,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 25</li><li>Test Dictionary 2: 31</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: nineteen</li><li>Test Dictionary 2: twenty-five (25)</li><li>Test Dictionary 2: thirty-one</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[ぶ]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>buchikomu definition 3</li><li>buchikomu definition 4</li></ul></div>", @@ -1646,7 +1646,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -1676,7 +1676,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", @@ -1831,7 +1831,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 24</li><li>Test Dictionary 2: 30</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: eighteen</li><li>Test Dictionary 2: twenty-four (24)</li><li>Test Dictionary 2: 30</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[う]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>uchikomu definition 3</li><li>uchikomu definition 4</li></ul></div>", @@ -1861,7 +1861,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 25</li><li>Test Dictionary 2: 31</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: nineteen</li><li>Test Dictionary 2: twenty-five (25)</li><li>Test Dictionary 2: thirty-one</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[ぶ]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>buchikomu definition 3</li><li>buchikomu definition 4</li></ul></div>", @@ -1951,7 +1951,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -1981,7 +1981,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", @@ -2136,7 +2136,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 24</li><li>Test Dictionary 2: 30</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 12</li><li>Test Dictionary 2: eighteen</li><li>Test Dictionary 2: twenty-four (24)</li><li>Test Dictionary 2: 30</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[う]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>uchikomu definition 3</li><li>uchikomu definition 4</li></ul></div>", @@ -2166,7 +2166,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打ち込む", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: 7</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 25</li><li>Test Dictionary 2: 31</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 3</li><li>Test Dictionary 2: seven</li><li>Test Dictionary 2: 13</li><li>Test Dictionary 2: nineteen</li><li>Test Dictionary 2: twenty-five (25)</li><li>Test Dictionary 2: thirty-one</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>ち<ruby>込<rt>こ</rt></ruby>む",          "furigana-plain": "打[ぶ]ち 込[こ]む",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>buchikomu definition 3</li><li>buchikomu definition 4</li></ul></div>", @@ -2256,7 +2256,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 22</li><li>Test Dictionary 2: 28</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 10</li><li>Test Dictionary 2: sixteen</li><li>Test Dictionary 2: twenty-two (22)</li><li>Test Dictionary 2: 28</li></ul>",          "furigana": "<ruby>打<rt>う</rt></ruby>つ",          "furigana-plain": "打[う]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>utsu definition 3</li><li>utsu definition 4</li></ul></div>", @@ -2286,7 +2286,7 @@          "dictionary": "Test Dictionary 2",          "document-title": "title",          "expression": "打つ", -        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: 0</li><li>Test Dictionary 2: 23</li><li>Test Dictionary 2: 29</li></ul>", +        "frequencies": "<ul style=\"text-align: left;\"><li>Test Dictionary 2: 2</li><li>Test Dictionary 2: 6</li><li>Test Dictionary 2: 11</li><li>Test Dictionary 2: seventeen</li><li>Test Dictionary 2: twenty-three (23)</li><li>Test Dictionary 2: twenty-nine</li></ul>",          "furigana": "<ruby>打<rt>ぶ</rt></ruby>つ",          "furigana-plain": "打[ぶ]つ",          "glossary": "<div style=\"text-align: left;\"><i>(vt, Test Dictionary 2)</i> <ul><li>butsu definition 3</li><li>butsu definition 4</li></ul></div>", diff --git a/test/data/html/test-document2-script.js b/test/data/html/test-document2-script.js index 8a183019..f6082802 100644 --- a/test/data/html/test-document2-script.js +++ b/test/data/html/test-document2-script.js @@ -16,40 +16,65 @@   * along with this program.  If not, see <https://www.gnu.org/licenses/>.   */ +/** + * @param {Element} element + */  function requestFullscreen(element) {      if (element.requestFullscreen) {          element.requestFullscreen(); +        // @ts-expect-error - Browser compatibility      } else if (element.mozRequestFullScreen) { +        // @ts-expect-error - Browser compatibility          element.mozRequestFullScreen(); +        // @ts-expect-error - Browser compatibility      } else if (element.webkitRequestFullscreen) { +        // @ts-expect-error - Browser compatibility          element.webkitRequestFullscreen(); +        // @ts-expect-error - Browser compatibility      } else if (element.msRequestFullscreen) { +        // @ts-expect-error - Browser compatibility          element.msRequestFullscreen();      }  } +/** */  function exitFullscreen() {      if (document.exitFullscreen) {          document.exitFullscreen(); +        // @ts-expect-error - Browser compatibility      } else if (document.mozCancelFullScreen) { +        // @ts-expect-error - Browser compatibility          document.mozCancelFullScreen(); +        // @ts-expect-error - Browser compatibility      } else if (document.webkitExitFullscreen) { +        // @ts-expect-error - Browser compatibility          document.webkitExitFullscreen(); +        // @ts-expect-error - Browser compatibility      } else if (document.msExitFullscreen) { +        // @ts-expect-error - Browser compatibility          document.msExitFullscreen();      }  } +/** + * @returns {?Element} + */  function getFullscreenElement() {      return (          document.fullscreenElement || +        // @ts-expect-error - Browser compatibility          document.msFullscreenElement || +        // @ts-expect-error - Browser compatibility          document.mozFullScreenElement || +        // @ts-expect-error - Browser compatibility          document.webkitFullscreenElement ||          null      );  } +/** + * @param {Element} element + */  function toggleFullscreen(element) {      if (getFullscreenElement()) {          exitFullscreen(); @@ -58,6 +83,10 @@ function toggleFullscreen(element) {      }  } +/** + * @param {HTMLElement|DocumentFragment} container + * @param {?Element} [fullscreenElement] + */  function setup(container, fullscreenElement=null) {      const fullscreenLink = container.querySelector('.fullscreen-link');      if (fullscreenLink !== null) { @@ -65,6 +94,7 @@ function setup(container, fullscreenElement=null) {              fullscreenElement = container.querySelector('.fullscreen-element');          }          fullscreenLink.addEventListener('click', (e) => { +            if (fullscreenElement === null) { return; }              toggleFullscreen(fullscreenElement);              e.preventDefault();              return false; @@ -74,11 +104,15 @@ function setup(container, fullscreenElement=null) {      const template = container.querySelector('template');      const templateContentContainer = container.querySelector('.template-content-container');      if (template !== null && templateContentContainer !== null) { -        const mode = container.dataset.shadowMode; -        const shadow = templateContentContainer.attachShadow({mode}); +        const mode = (container instanceof HTMLElement ? container.dataset.shadowMode : void 0); +        const shadow = templateContentContainer.attachShadow({ +            mode: (mode === 'open' || mode === 'closed' ? mode : 'open') +        });          const containerStyles = document.querySelector('#container-styles'); -        shadow.appendChild(containerStyles.cloneNode(true)); +        if (containerStyles !== null) { +            shadow.appendChild(containerStyles.cloneNode(true)); +        }          const content = document.importNode(template.content, true);          setup(content); diff --git a/test/data/translator-test-results-note-data1.json b/test/data/translator-test-results-note-data1.json index d686563c..34f7c21a 100644 --- a/test/data/translator-test-results-note-data1.json +++ b/test/data/translator-test-results-note-data1.json @@ -1659,7 +1659,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -1672,7 +1672,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -1791,7 +1791,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -1804,7 +1804,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -1963,7 +1963,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -1976,7 +1976,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -1989,7 +1989,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -2095,7 +2095,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -2108,7 +2108,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -2121,7 +2121,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], @@ -3651,7 +3651,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -3677,7 +3677,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "eighteen"                  },                  {                    "index": 4, @@ -3690,7 +3690,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 24 +                  "frequency": "twenty-four (24)"                  },                  {                    "index": 5, @@ -3813,7 +3813,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -3839,7 +3839,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "eighteen"              },              {                "index": 4, @@ -3852,7 +3852,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 24 +              "frequency": "twenty-four (24)"              },              {                "index": 5, @@ -4045,7 +4045,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -4071,7 +4071,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "nineteen"                  },                  {                    "index": 4, @@ -4084,7 +4084,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 25 +                  "frequency": "twenty-five (25)"                  },                  {                    "index": 5, @@ -4097,7 +4097,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 31 +                  "frequency": "thirty-one"                  }                ],                "pitches": [ @@ -4207,7 +4207,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -4233,7 +4233,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "nineteen"              },              {                "index": 4, @@ -4246,7 +4246,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 25 +              "frequency": "twenty-five (25)"              },              {                "index": 5, @@ -4259,7 +4259,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 31 +              "frequency": "thirty-one"              }            ],            "pitches": [ @@ -5079,7 +5079,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -5092,7 +5092,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -5211,7 +5211,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -5224,7 +5224,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -5385,7 +5385,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -5398,7 +5398,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -5411,7 +5411,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -5517,7 +5517,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -5530,7 +5530,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -5543,7 +5543,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], @@ -7394,7 +7394,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -7407,7 +7407,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -7526,7 +7526,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -7539,7 +7539,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -8007,7 +8007,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -8020,7 +8020,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -8033,7 +8033,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -8139,7 +8139,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -8152,7 +8152,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -8165,7 +8165,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], @@ -8684,7 +8684,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -8710,7 +8710,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "eighteen"                  },                  {                    "index": 4, @@ -8723,7 +8723,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 24 +                  "frequency": "twenty-four (24)"                  },                  {                    "index": 5, @@ -8846,7 +8846,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -8872,7 +8872,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "eighteen"              },              {                "index": 4, @@ -8885,7 +8885,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 24 +              "frequency": "twenty-four (24)"              },              {                "index": 5, @@ -9412,7 +9412,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -9425,7 +9425,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -9544,7 +9544,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -9557,7 +9557,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -10089,7 +10089,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -10115,7 +10115,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "nineteen"                  },                  {                    "index": 4, @@ -10128,7 +10128,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 25 +                  "frequency": "twenty-five (25)"                  },                  {                    "index": 5, @@ -10141,7 +10141,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 31 +                  "frequency": "thirty-one"                  }                ],                "pitches": [ @@ -10251,7 +10251,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -10277,7 +10277,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "nineteen"              },              {                "index": 4, @@ -10290,7 +10290,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 25 +              "frequency": "twenty-five (25)"              },              {                "index": 5, @@ -10303,7 +10303,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 31 +              "frequency": "thirty-one"              }            ],            "pitches": [ @@ -10817,7 +10817,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -10830,7 +10830,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -10843,7 +10843,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -10949,7 +10949,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -10962,7 +10962,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -10975,7 +10975,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], @@ -16097,7 +16097,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -16123,7 +16123,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "eighteen"                  },                  {                    "index": 4, @@ -16136,7 +16136,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 24 +                  "frequency": "twenty-four (24)"                  },                  {                    "index": 5, @@ -16259,7 +16259,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -16285,7 +16285,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "eighteen"              },              {                "index": 4, @@ -16298,7 +16298,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 24 +              "frequency": "twenty-four (24)"              },              {                "index": 5, @@ -16495,7 +16495,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -16521,7 +16521,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "nineteen"                  },                  {                    "index": 4, @@ -16534,7 +16534,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 25 +                  "frequency": "twenty-five (25)"                  },                  {                    "index": 5, @@ -16547,7 +16547,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 31 +                  "frequency": "thirty-one"                  }                ],                "pitches": [ @@ -16657,7 +16657,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -16683,7 +16683,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "nineteen"              },              {                "index": 4, @@ -16696,7 +16696,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 25 +              "frequency": "twenty-five (25)"              },              {                "index": 5, @@ -16709,7 +16709,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 31 +              "frequency": "thirty-one"              }            ],            "pitches": [ @@ -17529,7 +17529,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -17542,7 +17542,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -17661,7 +17661,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -17674,7 +17674,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -17835,7 +17835,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -17848,7 +17848,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -17861,7 +17861,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -17967,7 +17967,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -17980,7 +17980,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -17993,7 +17993,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], @@ -19523,7 +19523,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -19549,7 +19549,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "eighteen"                  },                  {                    "index": 4, @@ -19562,7 +19562,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 24 +                  "frequency": "twenty-four (24)"                  },                  {                    "index": 5, @@ -19685,7 +19685,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -19711,7 +19711,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "eighteen"              },              {                "index": 4, @@ -19724,7 +19724,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 24 +              "frequency": "twenty-four (24)"              },              {                "index": 5, @@ -19917,7 +19917,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -19943,7 +19943,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "nineteen"                  },                  {                    "index": 4, @@ -19956,7 +19956,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 25 +                  "frequency": "twenty-five (25)"                  },                  {                    "index": 5, @@ -19969,7 +19969,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 31 +                  "frequency": "thirty-one"                  }                ],                "pitches": [ @@ -20079,7 +20079,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -20105,7 +20105,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "nineteen"              },              {                "index": 4, @@ -20118,7 +20118,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 25 +              "frequency": "twenty-five (25)"              },              {                "index": 5, @@ -20131,7 +20131,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 31 +              "frequency": "thirty-one"              }            ],            "pitches": [ @@ -20951,7 +20951,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -20964,7 +20964,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -21083,7 +21083,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -21096,7 +21096,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -21257,7 +21257,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -21270,7 +21270,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -21283,7 +21283,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -21389,7 +21389,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -21402,7 +21402,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -21415,7 +21415,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], @@ -22945,7 +22945,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -22971,7 +22971,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "eighteen"                  },                  {                    "index": 4, @@ -22984,7 +22984,7 @@                    "expression": "打ち込む",                    "reading": "うちこむ",                    "hasReading": true, -                  "frequency": 24 +                  "frequency": "twenty-four (24)"                  },                  {                    "index": 5, @@ -23107,7 +23107,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -23133,7 +23133,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "eighteen"              },              {                "index": 4, @@ -23146,7 +23146,7 @@                "expression": "打ち込む",                "reading": "うちこむ",                "hasReading": true, -              "frequency": 24 +              "frequency": "twenty-four (24)"              },              {                "index": 5, @@ -23339,7 +23339,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": false, -                  "frequency": 7 +                  "frequency": "seven"                  },                  {                    "index": 2, @@ -23365,7 +23365,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "nineteen"                  },                  {                    "index": 4, @@ -23378,7 +23378,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 25 +                  "frequency": "twenty-five (25)"                  },                  {                    "index": 5, @@ -23391,7 +23391,7 @@                    "expression": "打ち込む",                    "reading": "ぶちこむ",                    "hasReading": true, -                  "frequency": 31 +                  "frequency": "thirty-one"                  }                ],                "pitches": [ @@ -23501,7 +23501,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": false, -              "frequency": 7 +              "frequency": "seven"              },              {                "index": 2, @@ -23527,7 +23527,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 0 +              "frequency": "nineteen"              },              {                "index": 4, @@ -23540,7 +23540,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 25 +              "frequency": "twenty-five (25)"              },              {                "index": 5, @@ -23553,7 +23553,7 @@                "expression": "打ち込む",                "reading": "ぶちこむ",                "hasReading": true, -              "frequency": 31 +              "frequency": "thirty-one"              }            ],            "pitches": [ @@ -24373,7 +24373,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "sixteen"                  },                  {                    "index": 4, @@ -24386,7 +24386,7 @@                    "expression": "打つ",                    "reading": "うつ",                    "hasReading": true, -                  "frequency": 22 +                  "frequency": "twenty-two (22)"                  },                  {                    "index": 5, @@ -24505,7 +24505,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "sixteen"              },              {                "index": 4, @@ -24518,7 +24518,7 @@                "expression": "打つ",                "reading": "うつ",                "hasReading": true, -              "frequency": 22 +              "frequency": "twenty-two (22)"              },              {                "index": 5, @@ -24679,7 +24679,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 0 +                  "frequency": "seventeen"                  },                  {                    "index": 4, @@ -24692,7 +24692,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 23 +                  "frequency": "twenty-three (23)"                  },                  {                    "index": 5, @@ -24705,7 +24705,7 @@                    "expression": "打つ",                    "reading": "ぶつ",                    "hasReading": true, -                  "frequency": 29 +                  "frequency": "twenty-nine"                  }                ],                "pitches": [], @@ -24811,7 +24811,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 0 +              "frequency": "seventeen"              },              {                "index": 4, @@ -24824,7 +24824,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 23 +              "frequency": "twenty-three (23)"              },              {                "index": 5, @@ -24837,7 +24837,7 @@                "expression": "打つ",                "reading": "ぶつ",                "hasReading": true, -              "frequency": 29 +              "frequency": "twenty-nine"              }            ],            "pitches": [], diff --git a/test/data/translator-test-results.json b/test/data/translator-test-results.json index 98db0ef4..0a7155b8 100644 --- a/test/data/translator-test-results.json +++ b/test/data/translator-test-results.json @@ -1101,8 +1101,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -1112,8 +1112,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -1266,8 +1266,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -1277,8 +1277,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -1288,7 +1288,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] @@ -2150,7 +2150,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -2172,8 +2172,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "eighteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -2183,8 +2183,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 24, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-four (24)", +            "displayValueParsed": true            },            {              "index": 5, @@ -2337,7 +2337,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -2359,8 +2359,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "nineteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -2370,8 +2370,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 25, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-five (25)", +            "displayValueParsed": true            },            {              "index": 5, @@ -2381,7 +2381,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 31, -            "displayValue": null, +            "displayValue": "thirty-one",              "displayValueParsed": false            }          ] @@ -2860,8 +2860,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -2871,8 +2871,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -3027,8 +3027,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -3038,8 +3038,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -3049,7 +3049,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] @@ -4166,8 +4166,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -4177,8 +4177,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -4502,8 +4502,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -4513,8 +4513,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -4524,7 +4524,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] @@ -4860,7 +4860,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -4882,8 +4882,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "eighteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -4893,8 +4893,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 24, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-four (24)", +            "displayValueParsed": true            },            {              "index": 5, @@ -5216,8 +5216,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -5227,8 +5227,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -5574,7 +5574,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -5596,8 +5596,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "nineteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -5607,8 +5607,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 25, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-five (25)", +            "displayValueParsed": true            },            {              "index": 5, @@ -5618,7 +5618,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 31, -            "displayValue": null, +            "displayValue": "thirty-one",              "displayValueParsed": false            }          ] @@ -5930,8 +5930,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -5941,8 +5941,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -5952,7 +5952,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] @@ -9645,7 +9645,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -9667,8 +9667,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "eighteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -9678,8 +9678,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 24, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-four (24)", +            "displayValueParsed": true            },            {              "index": 5, @@ -9836,7 +9836,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -9858,8 +9858,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "nineteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -9869,8 +9869,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 25, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-five (25)", +            "displayValueParsed": true            },            {              "index": 5, @@ -9880,7 +9880,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 31, -            "displayValue": null, +            "displayValue": "thirty-one",              "displayValueParsed": false            }          ] @@ -10359,8 +10359,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -10370,8 +10370,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -10526,8 +10526,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -10537,8 +10537,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -10548,7 +10548,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] @@ -11410,7 +11410,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -11432,8 +11432,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "eighteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -11443,8 +11443,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 24, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-four (24)", +            "displayValueParsed": true            },            {              "index": 5, @@ -11597,7 +11597,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -11619,8 +11619,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "nineteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -11630,8 +11630,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 25, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-five (25)", +            "displayValueParsed": true            },            {              "index": 5, @@ -11641,7 +11641,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 31, -            "displayValue": null, +            "displayValue": "thirty-one",              "displayValueParsed": false            }          ] @@ -12120,8 +12120,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -12131,8 +12131,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -12287,8 +12287,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -12298,8 +12298,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -12309,7 +12309,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] @@ -13171,7 +13171,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -13193,8 +13193,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "eighteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -13204,8 +13204,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 24, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-four (24)", +            "displayValueParsed": true            },            {              "index": 5, @@ -13358,7 +13358,7 @@              "dictionaryPriority": 0,              "hasReading": false,              "frequency": 7, -            "displayValue": null, +            "displayValue": "seven",              "displayValueParsed": false            },            { @@ -13380,8 +13380,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "nineteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -13391,8 +13391,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 25, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-five (25)", +            "displayValueParsed": true            },            {              "index": 5, @@ -13402,7 +13402,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 31, -            "displayValue": null, +            "displayValue": "thirty-one",              "displayValueParsed": false            }          ] @@ -13881,8 +13881,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "sixteen", +            "displayValueParsed": true            },            {              "index": 4, @@ -13892,8 +13892,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 22, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-two (22)", +            "displayValueParsed": true            },            {              "index": 5, @@ -14048,8 +14048,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 0, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "seventeen", +            "displayValueParsed": true            },            {              "index": 4, @@ -14059,8 +14059,8 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 23, -            "displayValue": null, -            "displayValueParsed": false +            "displayValue": "twenty-three (23)", +            "displayValueParsed": true            },            {              "index": 5, @@ -14070,7 +14070,7 @@              "dictionaryPriority": 0,              "hasReading": true,              "frequency": 29, -            "displayValue": null, +            "displayValue": "twenty-nine",              "displayValueParsed": false            }          ] diff --git a/test/database.test.js b/test/database.test.js index b53d0e65..80871f95 100644 --- a/test/database.test.js +++ b/test/database.test.js @@ -17,6 +17,7 @@   */  import {IDBFactory, IDBKeyRange} from 'fake-indexeddb'; +import {fileURLToPath} from 'node:url';  import path from 'path';  import {beforeEach, describe, expect, test, vi} from 'vitest';  import {createDictionaryArchive} from '../dev/util.js'; @@ -24,16 +25,27 @@ import {DictionaryDatabase} from '../ext/js/language/dictionary-database.js';  import {DictionaryImporterMediaLoader} from '../ext/js/language/dictionary-importer-media-loader.js';  import {DictionaryImporter} from '../ext/js/language/dictionary-importer.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); +  vi.stubGlobal('IDBKeyRange', IDBKeyRange);  vi.mock('../ext/js/language/dictionary-importer-media-loader.js'); +/** + * @param {string} dictionary + * @param {string} [dictionaryName] + * @returns {import('jszip')} + */  function createTestDictionaryArchive(dictionary, dictionaryName) { -    const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary); +    const dictionaryDirectory = path.join(dirname, 'data', 'dictionaries', dictionary);      return createDictionaryArchive(dictionaryDirectory, dictionaryName);  } +/** + * @param {import('dictionary-importer').OnProgressCallback} [onProgress] + * @returns {DictionaryImporter} + */  function createDictionaryImporter(onProgress) {      const dictionaryImporterMediaLoader = new DictionaryImporterMediaLoader();      return new DictionaryImporter(dictionaryImporterMediaLoader, (...args) => { @@ -47,24 +59,53 @@ function createDictionaryImporter(onProgress) {  } +/** + * @param {import('dictionary-database').TermEntry[]} dictionaryDatabaseEntries + * @param {string} term + * @returns {number} + */  function countDictionaryDatabaseEntriesWithTerm(dictionaryDatabaseEntries, term) {      return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.term === term ? 1 : 0)), 0);  } +/** + * @param {import('dictionary-database').TermEntry[]} dictionaryDatabaseEntries + * @param {string} reading + * @returns {number} + */  function countDictionaryDatabaseEntriesWithReading(dictionaryDatabaseEntries, reading) {      return dictionaryDatabaseEntries.reduce((i, v) => (i + (v.reading === reading ? 1 : 0)), 0);  } +/** + * @param {import('dictionary-database').TermMeta[]|import('dictionary-database').KanjiMeta[]} metas + * @param {import('dictionary-database').TermMetaType|import('dictionary-database').KanjiMetaType} mode + * @returns {number} + */  function countMetasWithMode(metas, mode) { -    return metas.reduce((i, v) => (i + (v.mode === mode ? 1 : 0)), 0); +    let i = 0; +    for (const item of metas) { +        if (item.mode === mode) { ++i; } +    } +    return i;  } +/** + * @param {import('dictionary-database').KanjiEntry[]} kanji + * @param {string} character + * @returns {number} + */  function countKanjiWithCharacter(kanji, character) { -    return kanji.reduce((i, v) => (i + (v.character === character ? 1 : 0)), 0); +    let i = 0; +    for (const item of kanji) { +        if (item.character === character) { ++i; } +    } +    return i;  } +/** */  async function testDatabase1() {      test('Database1', async () => {    // Load dictionary data          const testDictionary = createTestDictionaryArchive('valid-dictionary1'); @@ -172,6 +213,9 @@ async function testDatabase1() {      });  } +/** + * @param {DictionaryDatabase} database + */  async function testDatabaseEmpty1(database) {      test('DatabaseEmpty1', async () => {          const info = await database.getDictionaryInfo(); @@ -185,17 +229,22 @@ async function testDatabaseEmpty1(database) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {import('dictionary-database').DictionarySet} titles + */  async function testFindTermsBulkTest1(database, titles) {      test('FindTermsBulkTest1', async () => { +        /** @type {{inputs: {matchType: import('dictionary-database').MatchType, termList: string[]}[], expectedResults: {total: number, terms: [key: string, count: number][], readings: [key: string, count: number][]}}[]} */          const data = [              {                  inputs: [                      { -                        matchType: null, +                        matchType: 'exact',                          termList: ['打', '打つ', '打ち込む']                      },                      { -                        matchType: null, +                        matchType: 'exact',                          termList: ['だ', 'ダース', 'うつ', 'ぶつ', 'うちこむ', 'ぶちこむ']                      },                      { @@ -223,7 +272,7 @@ async function testFindTermsBulkTest1(database, titles) {              {                  inputs: [                      { -                        matchType: null, +                        matchType: 'exact',                          termList: ['込む']                      }                  ], @@ -254,7 +303,7 @@ async function testFindTermsBulkTest1(database, titles) {              {                  inputs: [                      { -                        matchType: null, +                        matchType: 'exact',                          termList: []                      }                  ], @@ -281,8 +330,13 @@ async function testFindTermsBulkTest1(database, titles) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {import('dictionary-database').DictionarySet} titles + */  async function testTindTermsExactBulk1(database, titles) {      test('TindTermsExactBulk1', async () => { +        /** @type {{inputs: {termList: {term: string, reading: string}[]}[], expectedResults: {total: number, terms: [key: string, count: number][], readings: [key: string, count: number][]}}[]} */          const data = [              {                  inputs: [ @@ -387,8 +441,13 @@ async function testTindTermsExactBulk1(database, titles) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {string} mainDictionary + */  async function testFindTermsBySequenceBulk1(database, mainDictionary) {      test('FindTermsBySequenceBulk1', async () => { +        /** @type {{inputs: {sequenceList: number[]}[], expectedResults: {total: number, terms: [key: string, count: number][], readings: [key: string, count: number][]}}[]} */          const data = [              {                  inputs: [ @@ -538,8 +597,13 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {import('dictionary-database').DictionarySet} titles + */  async function testFindTermMetaBulk1(database, titles) {      test('FindTermMetaBulk1', async () => { +        /** @type {{inputs: {termList: string[]}[], expectedResults: {total: number, modes: [key: import('dictionary-database').TermMetaType, count: number][]}}[]} */          const data = [              {                  inputs: [ @@ -606,8 +670,13 @@ async function testFindTermMetaBulk1(database, titles) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {import('dictionary-database').DictionarySet} titles + */  async function testFindKanjiBulk1(database, titles) {      test('FindKanjiBulk1', async () => { +        /** @type {{inputs: {kanjiList: string[]}[], expectedResults: {total: number, kanji: [key: string, count: number][]}}[]} */          const data = [              {                  inputs: [ @@ -660,8 +729,13 @@ async function testFindKanjiBulk1(database, titles) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {import('dictionary-database').DictionarySet} titles + */  async function testFindKanjiMetaBulk1(database, titles) {      test('FindKanjiMetaBulk1', async () => { +        /** @type {{inputs: {kanjiList: string[]}[], expectedResults: {total: number, modes: [key: import('dictionary-database').KanjiMetaType, count: number][]}}[]} */          const data = [              {                  inputs: [ @@ -714,6 +788,10 @@ async function testFindKanjiMetaBulk1(database, titles) {      });  } +/** + * @param {DictionaryDatabase} database + * @param {string} title + */  async function testFindTagForTitle1(database, title) {      test('FindTagForTitle1', async () => {          const data = [ @@ -769,6 +847,7 @@ async function testFindTagForTitle1(database, title) {  } +/** */  async function testDatabase2() {      test('Database2', async () => {    // Load dictionary data          const testDictionary = createTestDictionaryArchive('valid-dictionary1'); @@ -782,10 +861,12 @@ async function testDatabase2() {          // Setup database          const dictionaryDatabase = new DictionaryDatabase(); +        /** @type {import('dictionary-importer').ImportDetails} */ +        const detaultImportDetails = {prefixWildcardsSupported: false};          // Database not open -        await expect(dictionaryDatabase.deleteDictionary(title, 1000)).rejects.toThrow('Database not open'); -        await expect(dictionaryDatabase.findTermsBulk(['?'], titles, null)).rejects.toThrow('Database not open'); +        await expect(dictionaryDatabase.deleteDictionary(title, 1000, () => {})).rejects.toThrow('Database not open'); +        await expect(dictionaryDatabase.findTermsBulk(['?'], titles, 'exact')).rejects.toThrow('Database not open');          await expect(dictionaryDatabase.findTermsExactBulk([{term: '?', reading: '?'}], titles)).rejects.toThrow('Database not open');          await expect(dictionaryDatabase.findTermsBySequenceBulk([{query: 1, dictionary: title}])).rejects.toThrow('Database not open');          await expect(dictionaryDatabase.findTermMetaBulk(['?'], titles)).rejects.toThrow('Database not open'); @@ -794,24 +875,25 @@ async function testDatabase2() {          await expect(dictionaryDatabase.findKanjiMetaBulk(['?'], titles)).rejects.toThrow('Database not open');          await expect(dictionaryDatabase.findTagForTitle('tag', title)).rejects.toThrow('Database not open');          await expect(dictionaryDatabase.getDictionaryInfo()).rejects.toThrow('Database not open'); -        await expect(dictionaryDatabase.getDictionaryCounts(titles, true)).rejects.toThrow('Database not open'); -        await expect(createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {})).rejects.toThrow('Database is not ready'); +        await expect(dictionaryDatabase.getDictionaryCounts([...titles.keys()], true)).rejects.toThrow('Database not open'); +        await expect(createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails)).rejects.toThrow('Database is not ready');          await dictionaryDatabase.prepare();          // already prepared          await expect(dictionaryDatabase.prepare()).rejects.toThrow('Database already open'); -        await createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {}); +        await createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails);          // dictionary already imported -        await expect(createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {})).rejects.toThrow('Dictionary is already imported'); +        await expect(createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails)).rejects.toThrow('Dictionary is already imported');          await dictionaryDatabase.close();      });  } +/** */  async function testDatabase3() {      const invalidDictionaries = [          'invalid-dictionary1', @@ -828,12 +910,14 @@ async function testDatabase3() {              test(`${invalidDictionary}`, async () => {                  // Setup database                  const dictionaryDatabase = new DictionaryDatabase(); +                /** @type {import('dictionary-importer').ImportDetails} */ +                const detaultImportDetails = {prefixWildcardsSupported: false};                  await dictionaryDatabase.prepare();                  const testDictionary = createTestDictionaryArchive(invalidDictionary);                  const testDictionarySource = await testDictionary.generateAsync({type: 'arraybuffer'}); -                await expect(createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, {})).rejects.toThrow('Dictionary has invalid data'); +                await expect(createDictionaryImporter().importDictionary(dictionaryDatabase, testDictionarySource, detaultImportDetails)).rejects.toThrow('Dictionary has invalid data');                  await dictionaryDatabase.close();              });          } @@ -841,6 +925,7 @@ async function testDatabase3() {  } +/** */  async function main() {      beforeEach(async () => {          globalThis.indexedDB = new IDBFactory(); diff --git a/test/deinflector.test.js b/test/deinflector.test.js index edb85833..bd538428 100644 --- a/test/deinflector.test.js +++ b/test/deinflector.test.js @@ -17,12 +17,23 @@   */  import fs from 'fs'; +import {fileURLToPath} from 'node:url';  import path from 'path';  import {describe, expect, test} from 'vitest';  import {Deinflector} from '../ext/js/language/deinflector.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * @param {Deinflector} deinflector + * @param {string} source + * @param {string} expectedTerm + * @param {string} expectedRule + * @param {string[]|undefined} expectedReasons + * @returns {{has: false, reasons: null, rules: null}|{has: true, reasons: string[], rules: number}} + */  function hasTermReasons(deinflector, source, expectedTerm, expectedRule, expectedReasons) { -    for (const {term, reasons, rules} of deinflector.deinflect(source, source)) { +    for (const {term, reasons, rules} of deinflector.deinflect(source)) {          if (term !== expectedTerm) { continue; }          if (typeof expectedRule !== 'undefined') {              const expectedFlags = Deinflector.rulesToRuleFlags([expectedRule]); @@ -46,6 +57,7 @@ function hasTermReasons(deinflector, source, expectedTerm, expectedRule, expecte  } +/** */  function testDeinflections() {      const data = [          { @@ -915,7 +927,7 @@ function testDeinflections() {          }      ]; -    const deinflectionReasons = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ext', 'data/deinflect.json'))); +    const deinflectionReasons = JSON.parse(fs.readFileSync(path.join(dirname, '..', 'ext', 'data/deinflect.json'), {encoding: 'utf8'}));      const deinflector = new Deinflector(deinflectionReasons);      describe('deinflections', () => { @@ -939,6 +951,7 @@ function testDeinflections() {  } +/** */  function main() {      testDeinflections();  } diff --git a/test/dictionary.test.js b/test/dictionary.test.js index 8f160bc1..e516bd8e 100644 --- a/test/dictionary.test.js +++ b/test/dictionary.test.js @@ -24,12 +24,18 @@ import {createDictionaryArchive} from '../dev/util.js';  const dirname = path.dirname(fileURLToPath(import.meta.url)); +/** + * @param {string} dictionary + * @param {string} [dictionaryName] + * @returns {import('jszip')} + */  function createTestDictionaryArchive(dictionary, dictionaryName) {      const dictionaryDirectory = path.join(dirname, 'data', 'dictionaries', dictionary);      return createDictionaryArchive(dictionaryDirectory, dictionaryName);  } +/** */  async function main() {      const dictionaries = [          {name: 'valid-dictionary1', valid: true}, diff --git a/test/document-util.test.js b/test/document-util.test.js index f2552f78..8c6ab69b 100644 --- a/test/document-util.test.js +++ b/test/document-util.test.js @@ -30,24 +30,48 @@ const dirname = path.dirname(fileURLToPath(import.meta.url));  // DOMRect class definition  class DOMRect { +    /** +     * @param {number} x +     * @param {number} y +     * @param {number} width +     * @param {number} height +     */      constructor(x, y, width, height) { +        /** @type {number} */          this._x = x; +        /** @type {number} */          this._y = y; +        /** @type {number} */          this._width = width; +        /** @type {number} */          this._height = height;      } +    /** @type {number} */      get x() { return this._x; } +    /** @type {number} */      get y() { return this._y; } +    /** @type {number} */      get width() { return this._width; } +    /** @type {number} */      get height() { return this._height; } +    /** @type {number} */      get left() { return this._x + Math.min(0, this._width); } +    /** @type {number} */      get right() { return this._x + Math.max(0, this._width); } +    /** @type {number} */      get top() { return this._y + Math.min(0, this._height); } +    /** @type {number} */      get bottom() { return this._y + Math.max(0, this._height); } +    /** @returns {string} */ +    toJSON() { return '<not implemented>'; }  } +/** + * @param {string} fileName + * @returns {JSDOM} + */  function createJSDOM(fileName) {      const domSource = fs.readFileSync(fileName, {encoding: 'utf8'});      const dom = new JSDOM(domSource); @@ -65,10 +89,20 @@ function createJSDOM(fileName) {      return dom;  } +/** + * @param {Element} element + * @param {string|undefined} selector + * @returns {?Element} + */  function querySelectorChildOrSelf(element, selector) {      return selector ? element.querySelector(selector) : element;  } +/** + * @param {JSDOM} dom + * @param {?Node} node + * @returns {?Text|Node} + */  function getChildTextNodeOrSelf(dom, node) {      if (node === null) { return null; }      const Node = dom.window.Node; @@ -76,6 +110,10 @@ function getChildTextNodeOrSelf(dom, node) {      return (childNode !== null && childNode.nodeType === Node.TEXT_NODE ? childNode : node);  } +/** + * @param {unknown} value + * @returns {unknown} + */  function getPrototypeOfOrNull(value) {      try {          return Object.getPrototypeOf(value); @@ -84,12 +122,17 @@ function getPrototypeOfOrNull(value) {      }  } +/** + * @param {Document} document + * @returns {?Element} + */  function findImposterElement(document) {      // Finds the imposter element based on it's z-index style      return document.querySelector('div[style*="2147483646"]>*');  } +/** */  async function testDocument1() {      const dom = createJSDOM(path.join(dirname, 'data', 'html', 'test-document1.html'));      const window = dom.window; @@ -102,13 +145,16 @@ async function testDocument1() {      }  } +/** + * @param {JSDOM} dom + */  async function testDocumentTextScanningFunctions(dom) {      const document = dom.window.document;      test('DocumentTextScanningFunctions', () => { -        for (const testElement of document.querySelectorAll('.test[data-test-type=scan]')) { -        // Get test parameters -            let { +        for (const testElement of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('.test[data-test-type=scan]'))) { +            // Get test parameters +            const {                  elementFromPointSelector,                  caretRangeFromPointSelector,                  startNodeSelector, @@ -127,10 +173,10 @@ async function testDocumentTextScanningFunctions(dom) {              const startNode = getChildTextNodeOrSelf(dom, querySelectorChildOrSelf(testElement, startNodeSelector));              const endNode = getChildTextNodeOrSelf(dom, querySelectorChildOrSelf(testElement, endNodeSelector)); -            startOffset = parseInt(startOffset, 10); -            endOffset = parseInt(endOffset, 10); -            sentenceScanExtent = parseInt(sentenceScanExtent, 10); -            terminateAtNewlines = (terminateAtNewlines !== 'false'); +            const startOffset2 = parseInt(/** @type {string} */ (startOffset), 10); +            const endOffset2 = parseInt(/** @type {string} */ (endOffset), 10); +            const sentenceScanExtent2 = parseInt(/** @type {string} */ (sentenceScanExtent), 10); +            const terminateAtNewlines2 = (terminateAtNewlines !== 'false');              expect(elementFromPointValue).not.toStrictEqual(null);              expect(caretRangeFromPointValue).not.toStrictEqual(null); @@ -145,11 +191,25 @@ async function testDocumentTextScanningFunctions(dom) {                  expect(!!imposter).toStrictEqual(hasImposter === 'true');                  const range = document.createRange(); -                range.setStart(imposter ? imposter : startNode, startOffset); -                range.setEnd(imposter ? imposter : startNode, endOffset); +                range.setStart(/** @type {Node} */ (imposter ? imposter : startNode), startOffset2); +                range.setEnd(/** @type {Node} */ (imposter ? imposter : startNode), endOffset2);                  // Override getClientRects to return a rect guaranteed to contain (x, y) -                range.getClientRects = () => [new DOMRect(x - 1, y - 1, 2, 2)]; +                range.getClientRects = () => { +                    /** @type {import('test/document-types').PseudoDOMRectList} */ +                    const domRectList = Object.assign( +                        [new DOMRect(x - 1, y - 1, 2, 2)], +                        { +                            /** +                             * @this {DOMRect[]} +                             * @param {number} index +                             * @returns {DOMRect} +                             */ +                            item: function item(index) { return this[index]; } +                        } +                    ); +                    return domRectList; +                };                  return range;              }; @@ -192,8 +252,8 @@ async function testDocumentTextScanningFunctions(dom) {              const sentenceActual = DocumentUtil.extractSentence(                  source,                  false, -                sentenceScanExtent, -                terminateAtNewlines, +                sentenceScanExtent2, +                terminateAtNewlines2,                  terminatorMap,                  forwardQuoteMap,                  backwardQuoteMap @@ -206,13 +266,16 @@ async function testDocumentTextScanningFunctions(dom) {      });  } +/** + * @param {JSDOM} dom + */  async function testTextSourceRangeSeekFunctions(dom) {      const document = dom.window.document;      test('TextSourceRangeSeekFunctions', async () => { -        for (const testElement of document.querySelectorAll('.test[data-test-type=text-source-range-seek]')) { -        // Get test parameters -            let { +        for (const testElement of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('.test[data-test-type=text-source-range-seek]'))) { +            // Get test parameters +            const {                  seekNodeSelector,                  seekNodeIsText,                  seekOffset, @@ -224,34 +287,37 @@ async function testTextSourceRangeSeekFunctions(dom) {                  expectedResultContent              } = testElement.dataset; -            seekOffset = parseInt(seekOffset, 10); -            seekLength = parseInt(seekLength, 10); -            expectedResultOffset = parseInt(expectedResultOffset, 10); +            const seekOffset2 = parseInt(/** @type {string} */ (seekOffset), 10); +            const seekLength2 = parseInt(/** @type {string} */ (seekLength), 10); +            const expectedResultOffset2 = parseInt(/** @type {string} */ (expectedResultOffset), 10); -            let seekNode = testElement.querySelector(seekNodeSelector); -            if (seekNodeIsText === 'true') { +            /** @type {?Node} */ +            let seekNode = testElement.querySelector(/** @type {string} */ (seekNodeSelector)); +            if (seekNodeIsText === 'true' && seekNode !== null) {                  seekNode = seekNode.firstChild;              } -            let expectedResultNode = testElement.querySelector(expectedResultNodeSelector); -            if (expectedResultNodeIsText === 'true') { +            /** @type {?Node} */ +            let expectedResultNode = testElement.querySelector(/** @type {string} */ (expectedResultNodeSelector)); +            if (expectedResultNodeIsText === 'true' && expectedResultNode !== null) {                  expectedResultNode = expectedResultNode.firstChild;              }              const {node, offset, content} = ( -            seekDirection === 'forward' ? -            new DOMTextScanner(seekNode, seekOffset, true, false).seek(seekLength) : -            new DOMTextScanner(seekNode, seekOffset, true, false).seek(-seekLength) +                seekDirection === 'forward' ? +                new DOMTextScanner(/** @type {Node} */ (seekNode), seekOffset2, true, false).seek(seekLength2) : +                new DOMTextScanner(/** @type {Node} */ (seekNode), seekOffset2, true, false).seek(-seekLength2)              );              expect(node).toStrictEqual(expectedResultNode); -            expect(offset).toStrictEqual(expectedResultOffset); +            expect(offset).toStrictEqual(expectedResultOffset2);              expect(content).toStrictEqual(expectedResultContent);          }      });  } +/** */  async function main() {      await testDocument1();  } diff --git a/test/dom-text-scanner.test.js b/test/dom-text-scanner.test.js index d1b31276..f6a7410a 100644 --- a/test/dom-text-scanner.test.js +++ b/test/dom-text-scanner.test.js @@ -18,15 +18,27 @@  import fs from 'fs';  import {JSDOM} from 'jsdom'; +import {fileURLToPath} from 'node:url';  import path from 'path';  import {expect, test} from 'vitest';  import {DOMTextScanner} from '../ext/js/dom/dom-text-scanner.js'; +const dirname = path.dirname(fileURLToPath(import.meta.url)); + +/** + * @param {string} fileName + * @returns {JSDOM} + */  function createJSDOM(fileName) {      const domSource = fs.readFileSync(fileName, {encoding: 'utf8'});      return new JSDOM(domSource);  } +/** + * @param {Element} element + * @param {string} selector + * @returns {?Node} + */  function querySelectorTextNode(element, selector) {      let textIndex = -1;      const match = /::text$|::nth-text\((\d+)\)$/.exec(selector); @@ -35,13 +47,16 @@ function querySelectorTextNode(element, selector) {          selector = selector.substring(0, selector.length - match[0].length);      }      const result = element.querySelector(selector); +    if (result === null) { +        return null; +    }      if (textIndex < 0) {          return result;      }      for (let n = result.firstChild; n !== null; n = n.nextSibling) { -        if (n.nodeType === n.constructor.TEXT_NODE) { +        if (n.nodeType === /** @type {typeof Node} */ (n.constructor).TEXT_NODE) {              if (textIndex === 0) { -                return n; +                return /** @type {Text} */ (n);              }              --textIndex;          } @@ -50,10 +65,16 @@ function querySelectorTextNode(element, selector) {  } +/** + * @param {import('jsdom').DOMWindow} window + * @param {(element: Element) => CSSStyleDeclaration} getComputedStyle + * @param {?Node} element + * @returns {number} + */  function getComputedFontSizeInPixels(window, getComputedStyle, element) {      for (; element !== null; element = element.parentNode) {          if (element.nodeType === window.Node.ELEMENT_NODE) { -            const fontSize = getComputedStyle(element).fontSize; +            const fontSize = getComputedStyle(/** @type {Element} */ (element)).fontSize;              if (fontSize.endsWith('px')) {                  const value = parseFloat(fontSize.substring(0, fontSize.length - 2));                  return value; @@ -64,14 +85,19 @@ function getComputedFontSizeInPixels(window, getComputedStyle, element) {      return defaultFontSize;  } +/** + * @param {import('jsdom').DOMWindow} window + * @returns {(element: Element, pseudoElement?: ?string) => CSSStyleDeclaration} + */  function createAbsoluteGetComputedStyle(window) {      // Wrapper to convert em units to px units      const getComputedStyleOld = window.getComputedStyle.bind(window); +    /** @type {(element: Element, pseudoElement?: ?string) => CSSStyleDeclaration} */      return (element, ...args) => {          const style = getComputedStyleOld(element, ...args);          return new Proxy(style, {              get: (target, property) => { -                let result = target[property]; +                let result = /** @type {import('core').SafeAny} */ (target)[property];                  if (typeof result === 'string') {                      result = result.replace(/([-+]?\d(?:\.\d)?(?:[eE][-+]?\d+)?)em/g, (g0, g1) => {                          const fontSize = getComputedFontSizeInPixels(window, getComputedStyleOld, element); @@ -85,12 +111,15 @@ function createAbsoluteGetComputedStyle(window) {  } +/** + * @param {JSDOM} dom + */  async function testDomTextScanner(dom) {      const document = dom.window.document;      test('DomTextScanner', () => { -        for (const testElement of document.querySelectorAll('y-test')) { -            let testData = JSON.parse(testElement.dataset.testData); +        for (const testElement of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('y-test'))) { +            let testData = JSON.parse(/** @type {string} */ (testElement.dataset.testData));              if (!Array.isArray(testData)) {                  testData = [testData];              } @@ -159,19 +188,21 @@ async function testDomTextScanner(dom) {  } +/** */  async function testDocument1() { -    const dom = createJSDOM(path.join(__dirname, 'data', 'html', 'test-dom-text-scanner.html')); +    const dom = createJSDOM(path.join(dirname, 'data', 'html', 'test-dom-text-scanner.html'));      const window = dom.window;      try {          window.getComputedStyle = createAbsoluteGetComputedStyle(window); -        await testDomTextScanner(dom, {DOMTextScanner}); +        await testDomTextScanner(dom);      } finally {          window.close();      }  } +/** */  async function main() {      await testDocument1();  } diff --git a/test/hotkey-util.test.js b/test/hotkey-util.test.js index 8666b98b..02622c40 100644 --- a/test/hotkey-util.test.js +++ b/test/hotkey-util.test.js @@ -19,8 +19,10 @@  import {expect, test} from 'vitest';  import {HotkeyUtil} from '../ext/js/input/hotkey-util.js'; +/** */  function testCommandConversions() {      test('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']}},              {os: 'win', command: 'F1',    expectedCommand: 'F1',    expectedInput: {key: 'F1', modifiers: []}}, @@ -49,8 +51,10 @@ function testCommandConversions() {      });  } +/** */  function testDisplayNames() {      test('DisplayNames', () => { +        /** @type {{os: import('environment').OperatingSystem, key: ?string, modifiers: import('input').Modifier[], expected: string}[]} */          const data = [              {os: 'win', key: null,   modifiers: [], expected: ''},              {os: 'win', key: 'KeyF', modifiers: [], expected: 'F'}, @@ -138,8 +142,10 @@ function testDisplayNames() {      });  } +/** */  function testSortModifiers() {      test('SortModifiers', () => { +        /** @type {{modifiers: import('input').Modifier[], expected: import('input').Modifier[]}[]} */          const data = [              {modifiers: [], expected: []},              {modifiers: ['shift', 'alt', 'ctrl', 'mouse4', 'meta', 'mouse1', 'mouse0'], expected: ['meta', 'ctrl', 'alt', 'shift', 'mouse0', 'mouse1', 'mouse4']} @@ -155,6 +161,7 @@ function testSortModifiers() {  } +/** */  function main() {      testCommandConversions();      testDisplayNames(); diff --git a/test/japanese-util.test.js b/test/japanese-util.test.js index 47da4ccb..a0078da0 100644 --- a/test/japanese-util.test.js +++ b/test/japanese-util.test.js @@ -23,8 +23,10 @@ import * as wanakana from '../ext/lib/wanakana.js';  const jp = new JapaneseUtil(wanakana); +/** */  function testIsCodePointKanji() {      test('isCodePointKanji', () => { +        /** @type {[characters: string, expected: boolean][]} */          const data = [              ['力方', true],              ['\u53f1\u{20b9f}', true], @@ -34,7 +36,7 @@ function testIsCodePointKanji() {          for (const [characters, expected] of data) {              for (const character of characters) { -                const codePoint = character.codePointAt(0); +                const codePoint = /** @type {number} */ (character.codePointAt(0));                  const actual = jp.isCodePointKanji(codePoint);                  expect(actual).toStrictEqual(expected); // `isCodePointKanji failed for ${character} (\\u{${codePoint.toString(16)}})`              } @@ -42,8 +44,10 @@ function testIsCodePointKanji() {      });  } +/** */  function testIsCodePointKana() {      test('isCodePointKana', () => { +        /** @type {[characters: string, expected: boolean][]} */          const data = [              ['かたカタ', true],              ['力方々kata、。?,.?', false], @@ -52,7 +56,7 @@ function testIsCodePointKana() {          for (const [characters, expected] of data) {              for (const character of characters) { -                const codePoint = character.codePointAt(0); +                const codePoint = /** @type {number} */ (character.codePointAt(0));                  const actual = jp.isCodePointKana(codePoint);                  expect(actual).toStrictEqual(expected); // `isCodePointKana failed for ${character} (\\u{${codePoint.toString(16)}})`              } @@ -60,8 +64,10 @@ function testIsCodePointKana() {      });  } +/** */  function testIsCodePointJapanese() {      test('isCodePointJapanese', () => { +        /** @type {[characters: string, expected: boolean][]} */          const data = [              ['かたカタ力方々、。?', true],              ['\u53f1\u{20b9f}', true], @@ -71,7 +77,7 @@ function testIsCodePointJapanese() {          for (const [characters, expected] of data) {              for (const character of characters) { -                const codePoint = character.codePointAt(0); +                const codePoint = /** @type {number} */ (character.codePointAt(0));                  const actual = jp.isCodePointJapanese(codePoint);                  expect(actual).toStrictEqual(expected); // `isCodePointJapanese failed for ${character} (\\u{${codePoint.toString(16)}})`              } @@ -79,8 +85,10 @@ function testIsCodePointJapanese() {      });  } +/** */  function testIsStringEntirelyKana() {      test('isStringEntirelyKana', () => { +        /** @type {[string: string, expected: boolean][]} */          const data = [              ['かたかな', true],              ['カタカナ', true], @@ -101,8 +109,10 @@ function testIsStringEntirelyKana() {      });  } +/** */  function testIsStringPartiallyJapanese() {      test('isStringPartiallyJapanese', () => { +        /** @type {[string: string, expected: boolean][]} */          const data = [              ['かたかな', true],              ['カタカナ', true], @@ -124,8 +134,10 @@ function testIsStringPartiallyJapanese() {      });  } +/** */  function testConvertKatakanaToHiragana() {      test('convertKatakanaToHiragana', () => { +        /** @type {[string: string, expected: string, keepProlongedSoundMarks?: boolean][]} */          const data = [              ['かたかな', 'かたかな'],              ['ひらがな', 'ひらがな'], @@ -146,8 +158,10 @@ function testConvertKatakanaToHiragana() {      });  } +/** */  function testConvertHiraganaToKatakana() {      test('ConvertHiraganaToKatakana', () => { +        /** @type {[string: string, expected: string][]} */          const data = [              ['かたかな', 'カタカナ'],              ['ひらがな', 'ヒラガナ'], @@ -166,8 +180,10 @@ function testConvertHiraganaToKatakana() {      });  } +/** */  function testConvertToRomaji() {      test('ConvertToRomaji', () => { +        /** @type {[string: string, expected: string][]} */          const data = [              ['かたかな', 'katakana'],              ['ひらがな', 'hiragana'], @@ -186,8 +202,10 @@ function testConvertToRomaji() {      });  } +/** */  function testConvertNumericToFullWidth() {      test('ConvertNumericToFullWidth', () => { +        /** @type {[string: string, expected: string][]} */          const data = [              ['0123456789', '0123456789'],              ['abcdefghij', 'abcdefghij'], @@ -201,8 +219,10 @@ function testConvertNumericToFullWidth() {      });  } +/** */  function testConvertHalfWidthKanaToFullWidth() {      test('ConvertHalfWidthKanaToFullWidth', () => { +        /** @type {[string: string, expected: string, expectedSourceMapping?: number[]][]} */          const data = [              ['0123456789', '0123456789'],              ['abcdefghij', 'abcdefghij'], @@ -227,8 +247,10 @@ function testConvertHalfWidthKanaToFullWidth() {      });  } +/** */  function testConvertAlphabeticToKana() {      test('ConvertAlphabeticToKana', () => { +        /** @type {[string: string, expected: string, expectedSourceMapping?: number[]][]} */          const data = [              ['0123456789', '0123456789'],              ['abcdefghij', 'あbcでfgひj', [1, 1, 1, 2, 1, 1, 2, 1]], @@ -252,8 +274,10 @@ function testConvertAlphabeticToKana() {      });  } +/** */  function testDistributeFurigana() {      test('DistributeFurigana', () => { +        /** @type {[input: [term: string, reading: string], expected: {text: string, reading: string}[]][]} */          const data = [              [                  ['有り難う', 'ありがとう'], @@ -719,8 +743,10 @@ function testDistributeFurigana() {      });  } +/** */  function testDistributeFuriganaInflected() {      test('DistributeFuriganaInflected', () => { +        /** @type {[input: [term: string, reading: string, source: string], expected: {text: string, reading: string}[]][]} */          const data = [              [                  ['美味しい', 'おいしい', '美味しかた'], @@ -770,8 +796,10 @@ function testDistributeFuriganaInflected() {      });  } +/** */  function testCollapseEmphaticSequences() {      test('CollapseEmphaticSequences', () => { +        /** @type {[input: [text: string, fullCollapse: boolean], output: [expected: string, expectedSourceMapping: number[]]][]} */          const data = [              [['かこい', false], ['かこい', [1, 1, 1]]],              [['かこい', true], ['かこい', [1, 1, 1]]], @@ -825,8 +853,10 @@ function testCollapseEmphaticSequences() {      });  } +/** */  function testIsMoraPitchHigh() {      test('IsMoraPitchHigh', () => { +        /** @type {[input: [moraIndex: number, pitchAccentDownstepPosition: number], expected: boolean][]} */          const data = [              [[0, 0], false],              [[1, 0], true], @@ -861,8 +891,10 @@ function testIsMoraPitchHigh() {      });  } +/** */  function testGetKanaMorae() {      test('GetKanaMorae', () => { +        /** @type {[text: string, expected: string[]][]} */          const data = [              ['かこ', ['か', 'こ']],              ['かっこ', ['か', 'っ', 'こ']], @@ -883,6 +915,7 @@ function testGetKanaMorae() {  } +/** */  function main() {      testIsCodePointKanji();      testIsCodePointKana(); diff --git a/test/jsconfig.json b/test/jsconfig.json new file mode 100644 index 00000000..c587abe6 --- /dev/null +++ b/test/jsconfig.json @@ -0,0 +1,40 @@ +{ +    "compilerOptions": { +        "module": "ES2022", +        "target": "ES2022", +        "checkJs": true, +        "moduleResolution": "node", +        "strict": true, +        "strictNullChecks": true, +        "noImplicitAny": true, +        "strictPropertyInitialization": true, +        "suppressImplicitAnyIndexErrors": false, +        "skipLibCheck": false, +        "baseUrl": ".", +        "paths": { +            "*": ["../types/ext/*"], +            "dev/*": ["../types/dev/*"], +            "test/*": ["../types/test/*"], +            "rollup/parseAst": ["../types/other/rollup-parse-ast"] +        }, +        "types": [ +            "chrome", +            "firefox-webext-browser", +            "handlebars", +            "jszip", +            "parse5", +            "wanakana" +        ] +    }, +    "include": [ +        "**/*.js", +        "../ext/**/*.js", +        "../types/ext/**/*.ts", +        "../types/dev/**/*.ts", +        "../types/other/globals.d.ts" +    ], +    "exclude": [ +        "../node_modules", +        "../dev/lib" +    ] +}
\ No newline at end of file diff --git a/test/jsdom.test.js b/test/jsdom.test.js index c53f374e..6c2e00ee 100644 --- a/test/jsdom.test.js +++ b/test/jsdom.test.js @@ -26,20 +26,25 @@ import {expect, test} from 'vitest';   */  function testJSDOMSelectorBug() {      test('JSDOMSelectorBug', () => { -    // nwsapi is used by JSDOM +        // nwsapi is used by JSDOM          const dom = new JSDOM();          const {document} = dom.window;          const div = document.createElement('div');          div.innerHTML = '<div class="b"><div class="c"></div></div>';          const c = div.querySelector('.c'); -        expect(() => c.matches('.a:nth-last-of-type(1) .b .c')).not.toThrow(); +        expect(() => { +            if (c === null) { throw new Error('Element not found'); } +            c.matches('.a:nth-last-of-type(1) .b .c'); +        }).not.toThrow();      });  } +/** */  export function testJSDOM() {      testJSDOMSelectorBug();  } +/** */  function main() {      testJSDOM();  } diff --git a/test/json-schema.test.js b/test/json-schema.test.js index 5370e8da..e534f538 100644 --- a/test/json-schema.test.js +++ b/test/json-schema.test.js @@ -19,25 +19,47 @@  import {expect, test} from 'vitest';  import {JsonSchema} from '../ext/js/data/json-schema.js'; +/** + * @param {import('json-schema').Schema} schema + * @param {unknown} value + * @returns {boolean} + */  function schemaValidate(schema, value) {      return new JsonSchema(schema).isValid(value);  } +/** + * @param {import('json-schema').Schema} schema + * @param {unknown} value + * @returns {import('json-schema').Value} + */  function getValidValueOrDefault(schema, value) {      return new JsonSchema(schema).getValidValueOrDefault(value);  } +/** + * @param {import('json-schema').Schema} schema + * @param {import('json-schema').Value} value + * @returns {import('json-schema').Value} + */  function createProxy(schema, value) {      return new JsonSchema(schema).createProxy(value);  } +/** + * @template T + * @param {T} value + * @returns {T} + */  function clone(value) {      return JSON.parse(JSON.stringify(value));  } +/** */  function testValidate1() {      test('Validate1', () => { +        /** @type {import('json-schema').Schema} */          const schema = {              allOf: [                  { @@ -56,28 +78,34 @@ function testValidate1() {                      ]                  },                  { -                    not: [ -                        {multipleOf: 20} -                    ] +                    not: { +                        anyOf: [ +                            {multipleOf: 20} +                        ] +                    }                  }              ]          }; +        /** +         * @param {number} value +         * @returns {boolean} +         */          const jsValidate = (value) => {              return (                  typeof value === 'number' && -            ( -                (value >= 10 && value <= 100) || -                (value >= -100 && value <= -10) -            ) && -            (                  ( -                    (value % 3) === 0 || -                    (value % 5) === 0 +                    (value >= 10 && value <= 100) || +                    (value >= -100 && value <= -10) +                ) && +                ( +                    ( +                        (value % 3) === 0 || +                        (value % 5) === 0 +                    ) && +                    (value % 15) !== 0                  ) && -                (value % 15) !== 0 -            ) && -            (value % 20) !== 0 +                (value % 20) !== 0              );          }; @@ -89,10 +117,12 @@ function testValidate1() {      });  } +/** */  function testValidate2() {      test('Validate2', () => { +        /** @type {{schema: import('json-schema').Schema, inputs: {expected: boolean, value: unknown}[]}[]} */          const data = [ -        // String tests +            // String tests              {                  schema: {                      type: 'string' @@ -494,10 +524,12 @@ function testValidate2() {  } +/** */  function testGetValidValueOrDefault1() {      test('GetValidValueOrDefault1', () => { +        /** @type {{schema: import('json-schema').Schema, inputs: [value: unknown, expected: unknown][]}[]} */          const data = [ -        // Test value defaulting on objects with additionalProperties=false +            // Test value defaulting on objects with additionalProperties=false              {                  schema: {                      type: 'object', @@ -667,10 +699,10 @@ function testGetValidValueOrDefault1() {                      type: 'object',                      required: ['toString'],                      properties: { -                        toString: { +                        toString: /** @type {import('json-schema').SchemaObject} */ ({                              type: 'string',                              default: 'default' -                        } +                        })                      }                  },                  inputs: [ @@ -850,10 +882,12 @@ function testGetValidValueOrDefault1() {  } +/** */  function testProxy1() {      test('Proxy1', () => { +        /** @type {{schema: import('json-schema').Schema, tests: {error: boolean, value?: import('json-schema').Value, action: (value: import('core').SafeAny) => void}[]}[]} */          const data = [ -        // Object tests +            // Object tests              {                  schema: {                      type: 'object', @@ -998,6 +1032,7 @@ function testProxy1() {  } +/** */  function main() {      testValidate1();      testValidate2(); diff --git a/test/object-property-accessor.test.js b/test/object-property-accessor.test.js index a8730093..4d50b1e9 100644 --- a/test/object-property-accessor.test.js +++ b/test/object-property-accessor.test.js @@ -19,6 +19,9 @@  import {expect, test} from 'vitest';  import {ObjectPropertyAccessor} from '../ext/js/general/object-property-accessor.js'; +/** + * @returns {import('core').UnknownObject} + */  function createTestObject() {      return {          0: null, @@ -36,8 +39,10 @@ function createTestObject() {  } +/** */  function testGet1() {      test('Get1', () => { +        /** @type {[pathArray: (string|number)[], getExpected: (object: import('core').SafeAny) => unknown][]} */          const data = [              [[], (object) => object],              [['0'], (object) => object['0']], @@ -61,11 +66,13 @@ function testGet1() {      });  } +/** */  function testGet2() {      test('Get2', () => {          const object = createTestObject();          const accessor = new ObjectPropertyAccessor(object); +        /** @type {[pathArray: (string|number)[], message: string][]} */          const data = [              [[0], 'Invalid path: [0]'],              [['0', 'invalid'], 'Invalid path: ["0"].invalid'], @@ -95,9 +102,11 @@ function testGet2() {  } +/** */  function testSet1() {      test('Set1', () => {          const testValue = {}; +        /** @type {(string|number)[][]} */          const data = [              ['0'],              ['value1', 'value2'], @@ -120,12 +129,14 @@ function testSet1() {      });  } +/** */  function testSet2() {      test('Set2', () => {          const object = createTestObject();          const accessor = new ObjectPropertyAccessor(object);          const testValue = {}; +        /** @type {[pathArray: (string|number)[], message: string][]} */          const data = [              [[], 'Invalid path'],              [[0], 'Invalid path: [0]'], @@ -148,10 +159,17 @@ function testSet2() {  } +/** */  function testDelete1() {      test('Delete1', () => { +        /** +         * @param {unknown} object +         * @param {string} property +         * @returns {boolean} +         */          const hasOwn = (object, property) => Object.prototype.hasOwnProperty.call(object, property); +        /** @type {[pathArray: (string|number)[], validate: (object: import('core').SafeAny) => boolean][]} */          const data = [              [['0'], (object) => !hasOwn(object, '0')],              [['value1', 'value2'], (object) => !hasOwn(object.value1, 'value2')], @@ -171,8 +189,10 @@ function testDelete1() {      });  } +/** */  function testDelete2() {      test('Delete2', () => { +        /** @type {[pathArray: (string|number)[], message: string][]} */          const data = [              [[], 'Invalid path'],              [[0], 'Invalid path: [0]'], @@ -201,8 +221,10 @@ function testDelete2() {  } +/** */  function testSwap1() {      test('Swap1', () => { +        /** @type {[pathArray: (string|number)[], compareValues: boolean][]} */          const data = [              [['0'], true],              [['value1', 'value2'], true], @@ -237,8 +259,10 @@ function testSwap1() {      });  } +/** */  function testSwap2() {      test('Swap2', () => { +        /** @type {[pathArray1: (string|number)[], pathArray2: (string|number)[], checkRevert: boolean, message: string][]} */          const data = [              [[], [], false, 'Invalid path 1'],              [['0'], [], false, 'Invalid path 2'], @@ -276,8 +300,10 @@ function testSwap2() {  } +/** */  function testGetPathString1() {      test('GetPathString1', () => { +        /** @type {[pathArray: (string|number)[], expected: string][]} */          const data = [              [[], ''],              [[0], '[0]'], @@ -298,22 +324,27 @@ function testGetPathString1() {      });  } +/** */  function testGetPathString2() {      test('GetPathString2', () => { +        /** @type {[pathArray: unknown[], message: string][]} */          const data = [              [[1.5], 'Invalid index'],              [[null], 'Invalid type: object']          ];          for (const [pathArray, message] of data) { +            // @ts-expect-error - Throwing is expected              expect(() => ObjectPropertyAccessor.getPathString(pathArray)).toThrow(message);          }      });  } +/** */  function testGetPathArray1() {      test('GetPathArray1', () => { +        /** @type {[pathString: string, pathArray: (string|number)[]][]} */          const data = [              ['', []],              ['[0]', [0]], @@ -338,8 +369,10 @@ function testGetPathArray1() {      });  } +/** */  function testGetPathArray2() {      test('GetPathArray2', () => { +        /** @type {[pathString: string, message: string][]} */          const data = [              ['?', 'Unexpected character: ?'],              ['.', 'Unexpected character: .'], @@ -372,8 +405,10 @@ function testGetPathArray2() {  } +/** */  function testHasProperty() {      test('HasProperty', () => { +        /** @type {[object: unknown, property: unknown, expected: boolean][]} */          const data = [              [{}, 'invalid', false],              [{}, 0, false], @@ -389,13 +424,16 @@ function testHasProperty() {          ];          for (const [object, property, expected] of data) { +            // @ts-expect-error - Ignore potentially property types              expect(ObjectPropertyAccessor.hasProperty(object, property)).toStrictEqual(expected);          }      });  } +/** */  function testIsValidPropertyType() {      test('IsValidPropertyType', () => { +        /** @type {[object: unknown, property: unknown, expected: boolean][]} */          const data = [              [{}, 'invalid', true],              [{}, 0, false], @@ -411,12 +449,14 @@ function testIsValidPropertyType() {          ];          for (const [object, property, expected] of data) { +            // @ts-expect-error - Ignore potentially property types              expect(ObjectPropertyAccessor.isValidPropertyType(object, property)).toStrictEqual(expected);          }      });  } +/** */  function main() {      testGet1();      testGet2(); diff --git a/test/options-util.test.js b/test/options-util.test.js index ff5b6713..7845d759 100644 --- a/test/options-util.test.js +++ b/test/options-util.test.js @@ -24,7 +24,12 @@ import {OptionsUtil} from '../ext/js/data/options-util.js';  import {TemplatePatcher} from '../ext/js/templates/template-patcher.js';  const dirname = path.dirname(fileURLToPath(import.meta.url)); -vi.stubGlobal('fetch', async function fetch(url2) { + +/** + * @param {string} url2 + * @returns {Promise<import('dev/vm').PseudoFetchResponse>} + */ +async function fetch(url2) {      const filePath = url.fileURLToPath(url2);      await Promise.resolve();      const content = fs.readFileSync(filePath, {encoding: null}); @@ -35,15 +40,22 @@ vi.stubGlobal('fetch', async function fetch(url2) {          text: async () => Promise.resolve(content.toString('utf8')),          json: async () => Promise.resolve(JSON.parse(content.toString('utf8')))      }; -}); -vi.stubGlobal('chrome', { +} +/** @type {import('dev/vm').PseudoChrome} */ +const chrome = {      runtime: { -        getURL: (path2) => { +        getURL(path2) {              return url.pathToFileURL(path.join(dirname, '..', 'ext', path2.replace(/^\//, ''))).href;          }      } -}); +}; + +vi.stubGlobal('fetch', fetch); +vi.stubGlobal('chrome', chrome); +/** + * @returns {unknown} + */  function createProfileOptionsTestData1() {      return {          version: 14, @@ -144,6 +156,9 @@ function createProfileOptionsTestData1() {      };  } +/** + * @returns {unknown} + */  function createOptionsTestData1() {      return {          profiles: [ @@ -243,6 +258,9 @@ function createOptionsTestData1() {  } +/** + * @returns {unknown} + */  function createProfileOptionsUpdatedTestData1() {      return {          general: { @@ -519,6 +537,9 @@ function createProfileOptionsUpdatedTestData1() {      };  } +/** + * @returns {unknown} + */  function createOptionsUpdatedTestData1() {      return {          profiles: [ @@ -612,6 +633,7 @@ function createOptionsUpdatedTestData1() {  } +/** */  async function testUpdate() {      test('Update', async () => {          const optionsUtil = new OptionsUtil(); @@ -624,8 +646,10 @@ async function testUpdate() {      });  } +/** */  async function testDefault() {      test('Default', async () => { +        /** @type {((options: import('options-util').IntermediateOptions) => void)[]} */          const data = [              (options) => options,              (options) => { @@ -651,12 +675,17 @@ async function testDefault() {      });  } +/** */  async function testFieldTemplatesUpdate() {      test('FieldTemplatesUpdate', async () => {          const optionsUtil = new OptionsUtil();          await optionsUtil.prepare();          const templatePatcher = new TemplatePatcher(); +        /** +         * @param {string} fileName +         * @returns {string} +         */          const loadDataFile = (fileName) => {              const content = fs.readFileSync(path.join(dirname, '..', 'ext', fileName), {encoding: 'utf8'});              return templatePatcher.parsePatch(content).addition; @@ -671,6 +700,11 @@ async function testFieldTemplatesUpdate() {              {version: 13, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v13.handlebars')},              {version: 21, changes: loadDataFile('data/templates/anki-field-templates-upgrade-v21.handlebars')}          ]; +        /** +         * @param {number} startVersion +         * @param {number} targetVersion +         * @returns {string} +         */          const getUpdateAdditions = (startVersion, targetVersion) => {              let value = '';              for (const {version, changes} of updates) { @@ -682,7 +716,7 @@ async function testFieldTemplatesUpdate() {          };          const data = [ -        // Standard format +            // Standard format              {                  oldVersion: 0,                  newVersion: 12, @@ -1564,7 +1598,7 @@ async function testFieldTemplatesUpdate() {          const updatesPattern = /<<<UPDATE-ADDITIONS>>>/g;          for (const {old, expected, oldVersion, newVersion} of data) { -            const options = createOptionsTestData1(); +            const options = /** @type {import('core').SafeAny} */ (createOptionsTestData1());              options.profiles[0].options.anki.fieldTemplates = old;              options.version = oldVersion; @@ -1578,6 +1612,7 @@ async function testFieldTemplatesUpdate() {  } +/** */  async function main() {      await testUpdate();      await testDefault(); diff --git a/test/playwright/integration.spec.js b/test/playwright/integration.spec.js index b9a86d84..c8cf2f6d 100644 --- a/test/playwright/integration.spec.js +++ b/test/playwright/integration.spec.js @@ -45,7 +45,8 @@ test('search clipboard', async ({page, extensionId}) => {  test('anki add', async ({context, page, extensionId}) => {      // mock anki routes -    let resolve; +    /** @type {?(value: unknown) => void} */ +    let resolve = null;      const addNotePromise = new Promise((res) => {          resolve = res;      }); @@ -53,7 +54,7 @@ test('anki add', async ({context, page, extensionId}) => {          mockAnkiRouteHandler(route);          const req = route.request();          if (req.url().includes('127.0.0.1:8765') && req.postDataJSON().action === 'addNote') { -            resolve(req.postDataJSON()); +            /** @type {(value: unknown) => void} */ (resolve)(req.postDataJSON());          }      }); @@ -63,7 +64,11 @@ test('anki add', async ({context, page, extensionId}) => {      // load in test dictionary      const dictionary = createDictionaryArchive(path.join(root, 'test/data/dictionaries/valid-dictionary1'), 'valid-dictionary1');      const testDictionarySource = await dictionary.generateAsync({type: 'arraybuffer'}); -    await page.locator('input[id="dictionary-import-file-input"]').setInputFiles({name: 'valid-dictionary1.zip', buffer: Buffer.from(testDictionarySource)}); +    await page.locator('input[id="dictionary-import-file-input"]').setInputFiles({ +        name: 'valid-dictionary1.zip', +        mimeType: 'application/x-zip', +        buffer: Buffer.from(testDictionarySource) +    });      await expect(page.locator('id=dictionaries')).toHaveText('Dictionaries (1 installed, 1 enabled)', {timeout: 5 * 60 * 1000});      // connect to anki @@ -75,7 +80,7 @@ test('anki add', async ({context, page, extensionId}) => {      await page.locator('select.anki-card-deck').selectOption('Mock Deck');      await page.locator('select.anki-card-model').selectOption('Mock Model');      for (const modelField of mockModelFieldNames) { -        await page.locator(`[data-setting="anki.terms.fields.${modelField}"]`).fill(mockModelFieldsToAnkiValues[modelField]); +        await page.locator(`[data-setting="anki.terms.fields.${modelField}"]`).fill(/** @type {string} */ (mockModelFieldsToAnkiValues[modelField]));      }      await page.locator('#anki-cards-modal > div > div.modal-footer > button:nth-child(2)').click();      await writeToClipboardFromPage(page, '読むの例文'); diff --git a/test/playwright/playwright-util.js b/test/playwright/playwright-util.js index 5ceb92fd..ac68db4d 100644 --- a/test/playwright/playwright-util.js +++ b/test/playwright/playwright-util.js @@ -55,6 +55,7 @@ export const mockModelFieldNames = [      'Sentence'  ]; +/** @type {{[key: string]: string|undefined}} */  export const mockModelFieldsToAnkiValues = {      'Word': '{expression}',      'Reading': '{furigana-plain}', @@ -62,6 +63,10 @@ export const mockModelFieldsToAnkiValues = {      'Audio': '{audio}'  }; +/** + * @param {import('playwright').Route} route + * @returns {Promise<void>|undefined} + */  export const mockAnkiRouteHandler = (route) => {      const reqBody = route.request().postDataJSON();      const respBody = ankiRouteResponses[reqBody.action]; @@ -71,6 +76,11 @@ export const mockAnkiRouteHandler = (route) => {      route.fulfill(respBody);  }; +/** + * @param {import('playwright').Page} page + * @param {string} text + * @returns {Promise<void>} + */  export const writeToClipboardFromPage = async (page, text) => {      await page.evaluate(`navigator.clipboard.writeText('${text}')`);  }; @@ -100,6 +110,7 @@ const baseAnkiResp = {      contentType: 'text/json'  }; +/** @type {{[key: string]: import('core').SerializableObject}} */  const ankiRouteResponses = {      'version': Object.assign({body: JSON.stringify(6)}, baseAnkiResp),      'deckNames': Object.assign({body: JSON.stringify(['Mock Deck'])}, baseAnkiResp), diff --git a/test/playwright/visual.spec.js b/test/playwright/visual.spec.js index 2f46990f..8b48b7c0 100644 --- a/test/playwright/visual.spec.js +++ b/test/playwright/visual.spec.js @@ -48,10 +48,16 @@ test('visual', async ({page, extensionId}) => {      // take a screenshot of the settings page with jmdict loaded      await expect.soft(page).toHaveScreenshot('settings-jmdict-loaded.png', {mask: [storage_locator]}); +    /** +     * @param {number} doc_number +     * @param {number} test_number +     * @param {import('@playwright/test').ElementHandle<Node>} el +     * @param {{x: number, y: number}} offset +     */      const screenshot = async (doc_number, test_number, el, offset) => {          const test_name = 'doc' + doc_number + '-test' + test_number; -        const box = await el.boundingBox(); +        const box = (await el.boundingBox()) || {x: 0, y: 0, width: 0, height: 0};          // find the popup frame if it exists          let popup_frame = page.frames().find((f) => f.url().includes('popup.html')); @@ -66,7 +72,7 @@ test('visual', async ({page, extensionId}) => {              popup_frame = await frame_attached; // wait for popup to be attached          }          try { -            await (await popup_frame.frameElement()).waitForElementState('visible', {timeout: 500});  // some tests don't have a popup, so don't fail if it's not there; TODO: check if the popup is expected to be there +            await (await /** @type {import('@playwright/test').Frame} */ (popup_frame).frameElement()).waitForElementState('visible', {timeout: 500});  // some tests don't have a popup, so don't fail if it's not there; TODO: check if the popup is expected to be there          } catch (error) {              console.log(test_name + ' has no popup');          } @@ -75,7 +81,7 @@ test('visual', async ({page, extensionId}) => {          await expect.soft(page).toHaveScreenshot(test_name + '.png');          await page.mouse.click(0, 0); // click away so popup disappears -        await (await popup_frame.frameElement()).waitForElementState('hidden'); // wait for popup to disappear +        await (await /** @type {import('@playwright/test').Frame} */ (popup_frame).frameElement()).waitForElementState('hidden'); // wait for popup to disappear      };      // Load test-document1.html diff --git a/test/profile-conditions-util.test.js b/test/profile-conditions-util.test.js index ca8b00ef..62b21555 100644 --- a/test/profile-conditions-util.test.js +++ b/test/profile-conditions-util.test.js @@ -19,31 +19,33 @@  import {expect, test} from 'vitest';  import {ProfileConditionsUtil} from '../ext/js/background/profile-conditions-util.js'; +/** */  function testNormalizeContext() {      test('NormalizeContext', () => { +        /** @type {{context: import('settings').OptionsContext, expected: import('profile-conditions-util').NormalizedOptionsContext}[]} */          const data = [ -        // Empty +            // Empty              { -                context: {}, -                expected: {flags: []} +                context: {index: 0}, +                expected: {index: 0, flags: []}              },              // Domain normalization              { -                context: {url: ''}, -                expected: {url: '', flags: []} +                context: {depth: 0, url: ''}, +                expected: {depth: 0, url: '', flags: []}              },              { -                context: {url: 'http://example.com/'}, -                expected: {url: 'http://example.com/', domain: 'example.com', flags: []} +                context: {depth: 0, url: 'http://example.com/'}, +                expected: {depth: 0, 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: {depth: 0, url: 'http://example.com:1234/'}, +                expected: {depth: 0, 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: []} +                context: {depth: 0, url: 'http://user@example.com:1234/'}, +                expected: {depth: 0, url: 'http://user@example.com:1234/', domain: 'example.com', flags: []}              }          ]; @@ -55,15 +57,17 @@ function testNormalizeContext() {      });  } +/** */  function testSchemas() {      test('Schemas', () => { +        /** @type {{conditionGroups: import('settings').ProfileConditionGroup[], expectedSchema?: import('json-schema').Schema, inputs?: {expected: boolean, context: import('settings').OptionsContext}[]}[]} */          const data = [ -        // Empty +            // Empty              {                  conditionGroups: [],                  expectedSchema: {},                  inputs: [ -                    {expected: true, context: {url: 'http://example.com/'}} +                    {expected: true, context: {depth: 0, url: 'http://example.com/'}}                  ]              },              { @@ -72,7 +76,7 @@ function testSchemas() {                  ],                  expectedSchema: {},                  inputs: [ -                    {expected: true, context: {url: 'http://example.com/'}} +                    {expected: true, context: {depth: 0, url: 'http://example.com/'}}                  ]              },              { @@ -82,7 +86,7 @@ function testSchemas() {                  ],                  expectedSchema: {},                  inputs: [ -                    {expected: true, context: {url: 'http://example.com/'}} +                    {expected: true, context: {depth: 0, url: 'http://example.com/'}}                  ]              }, @@ -124,14 +128,16 @@ function testSchemas() {                      }                  ],                  expectedSchema: { -                    not: [ -                        { -                            properties: { -                                depth: {const: 0} -                            }, -                            required: ['depth'] -                        } -                    ] +                    not: { +                        anyOf: [ +                            { +                                properties: { +                                    depth: {const: 0} +                                }, +                                required: ['depth'] +                            } +                        ] +                    }                  },                  inputs: [                      {expected: false, context: {depth: 0, url: 'http://example.com/'}}, @@ -371,9 +377,9 @@ function testSchemas() {                  },                  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']}} +                    {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']}}                  ]              },              { @@ -383,7 +389,7 @@ function testSchemas() {                              {                                  type: 'modifierKeys',                                  operator: 'are', -                                value: 'Alt, Shift' +                                value: 'alt, shift'                              }                          ]                      } @@ -395,8 +401,8 @@ function testSchemas() {                              maxItems: 2,                              minItems: 2,                              allOf: [ -                                {contains: {const: 'Alt'}}, -                                {contains: {const: 'Shift'}} +                                {contains: {const: 'alt'}}, +                                {contains: {const: 'shift'}}                              ]                          }                      }, @@ -404,9 +410,9 @@ function testSchemas() {                  },                  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']}} +                    {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']}}                  ]              },              { @@ -422,24 +428,26 @@ function testSchemas() {                      }                  ],                  expectedSchema: { -                    not: [ -                        { -                            properties: { -                                modifierKeys: { -                                    type: 'array', -                                    maxItems: 0, -                                    minItems: 0 -                                } -                            }, -                            required: ['modifierKeys'] -                        } -                    ] +                    not: { +                        anyOf: [ +                            { +                                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']}} +                    {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']}}                  ]              },              { @@ -449,34 +457,36 @@ function testSchemas() {                              {                                  type: 'modifierKeys',                                  operator: 'areNot', -                                value: 'Alt, Shift' +                                value: 'alt, shift'                              }                          ]                      }                  ],                  expectedSchema: { -                    not: [ -                        { -                            properties: { -                                modifierKeys: { -                                    type: 'array', -                                    maxItems: 2, -                                    minItems: 2, -                                    allOf: [ -                                        {contains: {const: 'Alt'}}, -                                        {contains: {const: 'Shift'}} -                                    ] -                                } -                            }, -                            required: ['modifierKeys'] -                        } -                    ] +                    not: { +                        anyOf: [ +                            { +                                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']}} +                    {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']}}                  ]              },              { @@ -502,9 +512,9 @@ function testSchemas() {                  },                  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']}} +                    {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']}}                  ]              },              { @@ -514,7 +524,7 @@ function testSchemas() {                              {                                  type: 'modifierKeys',                                  operator: 'include', -                                value: 'Alt, Shift' +                                value: 'alt, shift'                              }                          ]                      } @@ -525,8 +535,8 @@ function testSchemas() {                              type: 'array',                              minItems: 2,                              allOf: [ -                                {contains: {const: 'Alt'}}, -                                {contains: {const: 'Shift'}} +                                {contains: {const: 'alt'}}, +                                {contains: {const: 'shift'}}                              ]                          }                      }, @@ -534,9 +544,9 @@ function testSchemas() {                  },                  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']}} +                    {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']}}                  ]              },              { @@ -561,9 +571,9 @@ function testSchemas() {                  },                  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']}} +                    {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']}}                  ]              },              { @@ -573,7 +583,7 @@ function testSchemas() {                              {                                  type: 'modifierKeys',                                  operator: 'notInclude', -                                value: 'Alt, Shift' +                                value: 'alt, shift'                              }                          ]                      } @@ -582,19 +592,21 @@ function testSchemas() {                      properties: {                          modifierKeys: {                              type: 'array', -                            not: [ -                                {contains: {const: 'Alt'}}, -                                {contains: {const: 'Shift'}} -                            ] +                            not: { +                                anyOf: [ +                                    {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']}} +                    {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']}}                  ]              }, @@ -622,11 +634,13 @@ function testSchemas() {                      }                  },                  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']}} +                    {expected: true,  context: {depth: 0, url: ''}}, +                    {expected: true,  context: {depth: 0, url: '', flags: []}}, +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -636,7 +650,7 @@ function testSchemas() {                              {                                  type: 'flags',                                  operator: 'are', -                                value: 'test1, test2' +                                value: 'clipboard, test2'                              }                          ]                      } @@ -649,18 +663,20 @@ function testSchemas() {                              maxItems: 2,                              minItems: 2,                              allOf: [ -                                {contains: {const: 'test1'}}, +                                {contains: {const: 'clipboard'}},                                  {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']}} +                    {expected: false, context: {depth: 0, url: ''}}, +                    {expected: false, context: {depth: 0, url: '', flags: []}}, +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -676,25 +692,29 @@ function testSchemas() {                      }                  ],                  expectedSchema: { -                    not: [ -                        { -                            required: ['flags'], -                            properties: { -                                flags: { -                                    type: 'array', -                                    maxItems: 0, -                                    minItems: 0 +                    not: { +                        anyOf: [ +                            { +                                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']}} +                    {expected: false, context: {depth: 0, url: ''}}, +                    {expected: false, context: {depth: 0, url: '', flags: []}}, +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -704,35 +724,39 @@ function testSchemas() {                              {                                  type: 'flags',                                  operator: 'areNot', -                                value: 'test1, test2' +                                value: 'clipboard, test2'                              }                          ]                      }                  ],                  expectedSchema: { -                    not: [ -                        { -                            required: ['flags'], -                            properties: { -                                flags: { -                                    type: 'array', -                                    maxItems: 2, -                                    minItems: 2, -                                    allOf: [ -                                        {contains: {const: 'test1'}}, -                                        {contains: {const: 'test2'}} -                                    ] +                    not: { +                        anyOf: [ +                            { +                                required: ['flags'], +                                properties: { +                                    flags: { +                                        type: 'array', +                                        maxItems: 2, +                                        minItems: 2, +                                        allOf: [ +                                            {contains: {const: 'clipboard'}}, +                                            {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']}} +                    {expected: true,  context: {depth: 0, url: ''}}, +                    {expected: true,  context: {depth: 0, url: '', flags: []}}, +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -757,11 +781,13 @@ function testSchemas() {                      }                  },                  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']}} +                    {expected: true,  context: {depth: 0, url: ''}}, +                    {expected: true,  context: {depth: 0, url: '', flags: []}}, +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -771,7 +797,7 @@ function testSchemas() {                              {                                  type: 'flags',                                  operator: 'include', -                                value: 'test1, test2' +                                value: 'clipboard, test2'                              }                          ]                      } @@ -783,18 +809,20 @@ function testSchemas() {                              type: 'array',                              minItems: 2,                              allOf: [ -                                {contains: {const: 'test1'}}, +                                {contains: {const: 'clipboard'}},                                  {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']}} +                    {expected: false, context: {depth: 0, url: ''}}, +                    {expected: false, context: {depth: 0, url: '', flags: []}}, +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -818,11 +846,13 @@ function testSchemas() {                      }                  },                  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']}} +                    {expected: true,  context: {depth: 0, url: ''}}, +                    {expected: true,  context: {depth: 0, url: '', flags: []}}, +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: true,  context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              },              { @@ -832,7 +862,7 @@ function testSchemas() {                              {                                  type: 'flags',                                  operator: 'notInclude', -                                value: 'test1, test2' +                                value: 'clipboard, test2'                              }                          ]                      } @@ -842,19 +872,23 @@ function testSchemas() {                      properties: {                          flags: {                              type: 'array', -                            not: [ -                                {contains: {const: 'test1'}}, -                                {contains: {const: 'test2'}} -                            ] +                            not: { +                                anyOf: [ +                                    {contains: {const: 'clipboard'}}, +                                    {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']}} +                    {expected: true,  context: {depth: 0, url: ''}}, +                    {expected: true,  context: {depth: 0, url: '', flags: []}}, +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2']}}, +                    // @ts-expect-error - Ignore type for string flag for testing purposes +                    {expected: false, context: {depth: 0, url: '', flags: ['clipboard', 'test2', 'test3']}}                  ]              }, @@ -1082,6 +1116,7 @@ function testSchemas() {  } +/** */  function main() {      testNormalizeContext();      testSchemas(); diff --git a/test/text-source-map.test.js b/test/text-source-map.test.js index aeaba000..54b39319 100644 --- a/test/text-source-map.test.js +++ b/test/text-source-map.test.js @@ -19,6 +19,7 @@  import {expect, test} from 'vitest';  import {TextSourceMap} from '../ext/js/general/text-source-map.js'; +/** */  function testSource() {      test('Source', () => {          const data = [ @@ -34,8 +35,10 @@ function testSource() {      });  } +/** */  function testEquals() {      test('Equals', () => { +        /** @type {[args1: [source1: string, mapping1: ?(number[])], args2: [source2: string, mapping2: ?(number[])], expectedEquals: boolean][]} */          const data = [              [['source1', null], ['source1', null], true],              [['source2', null], ['source2', null], true], @@ -76,8 +79,10 @@ function testEquals() {      });  } +/** */  function testGetSourceLength() {      test('GetSourceLength', () => { +        /** @type {[args: [source: string, mapping: number[]], finalLength: number, expectedValue: number][]} */          const data = [              [['source', [1, 1, 1, 1, 1, 1]], 1, 1],              [['source', [1, 1, 1, 1, 1, 1]], 2, 2], @@ -103,10 +108,12 @@ function testGetSourceLength() {      });  } +/** */  function testCombineInsert() {      test('CombineInsert', () => { +        /** @type {[args: [source: string, mapping: ?(number[])], expectedArgs: [expectedSource: string, expectedMapping: ?(number[])], operations: [operation: string, arg1: number, arg2: number][]][]} */          const data = [ -        // No operations +            // No operations              [                  ['source', null],                  ['source', [1, 1, 1, 1, 1, 1]], @@ -226,6 +233,7 @@ function testCombineInsert() {  } +/** */  function main() {      testSource();      testEquals(); diff --git a/test/translator.test.js b/test/translator.test.js index 7a827d39..3db560a7 100644 --- a/test/translator.test.js +++ b/test/translator.test.js @@ -28,6 +28,7 @@ vi.stubGlobal('IDBKeyRange', IDBKeyRange);  const dirname = path.dirname(fileURLToPath(import.meta.url)); +/** */  async function main() {      const translatorVM = new TranslatorVM();      const dictionaryDirectory = path.join(dirname, 'data', 'dictionaries', 'valid-dictionary1'); @@ -53,6 +54,7 @@ async function main() {                  case 'findTerms':                      {                          const {name, mode, text} = t; +                        /** @type {import('translation').FindTermsOptions} */                          const options = translatorVM.buildOptions(optionsPresets, t.options);                          const {dictionaryEntries, originalTextLength} = structuredClone(await translatorVM.translator.findTerms(mode, text, options));                          const noteDataList = mode !== 'simple' ? structuredClone(dictionaryEntries.map((dictionaryEntry) => translatorVM.createTestAnkiNoteData(structuredClone(dictionaryEntry), mode))) : null; @@ -66,9 +68,10 @@ async function main() {                  case 'findKanji':                      {                          const {name, text} = t; +                        /** @type {import('translation').FindKanjiOptions} */                          const options = translatorVM.buildOptions(optionsPresets, t.options);                          const dictionaryEntries = structuredClone(await translatorVM.translator.findKanji(text, options)); -                        const noteDataList = structuredClone(dictionaryEntries.map((dictionaryEntry) => translatorVM.createTestAnkiNoteData(structuredClone(dictionaryEntry), null))); +                        const noteDataList = structuredClone(dictionaryEntries.map((dictionaryEntry) => translatorVM.createTestAnkiNoteData(structuredClone(dictionaryEntry), 'split')));                          actualResults1.push({name, dictionaryEntries});                          actualResults2.push({name, noteDataList});                          expect(dictionaryEntries).toStrictEqual(expected1.dictionaryEntries); |