Pop-up dictionary browser extension for language learning. Successor to Yomichan. (PERSONAL FORK)
1/*
2 * Copyright (C) 2023-2025 Yomitan Authors
3 * Copyright (C) 2020-2022 Yomichan Authors
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <https://www.gnu.org/licenses/>.
17 */
18
19import {IDBKeyRange, indexedDB} from 'fake-indexeddb';
20import {expect, vi} from 'vitest';
21import {createDictionaryArchiveData} from '../../dev/dictionary-archive-util.js';
22import {DictionaryDatabase} from '../../ext/js/dictionary/dictionary-database.js';
23import {DictionaryImporter} from '../../ext/js/dictionary/dictionary-importer.js';
24import {Translator} from '../../ext/js/language/translator.js';
25import {chrome, fetch} from '../mocks/common.js';
26import {DictionaryImporterMediaLoader} from '../mocks/dictionary-importer-media-loader.js';
27import {createDomTest} from './dom-test.js';
28
29vi.stubGlobal('indexedDB', indexedDB);
30vi.stubGlobal('IDBKeyRange', IDBKeyRange);
31vi.stubGlobal('fetch', fetch);
32vi.stubGlobal('chrome', chrome);
33
34/**
35 * @param {string} dictionaryDirectory
36 * @param {string} dictionaryName
37 * @returns {Promise<{translator: Translator, styles: string}>}
38 */
39export async function createTranslatorContext(dictionaryDirectory, dictionaryName) {
40 // Dictionary
41 const testDictionaryData = await createDictionaryArchiveData(dictionaryDirectory, dictionaryName);
42
43 // Setup database
44 const dictionaryImporterMediaLoader = new DictionaryImporterMediaLoader();
45 const dictionaryImporter = new DictionaryImporter(dictionaryImporterMediaLoader);
46 const dictionaryDatabase = new DictionaryDatabase();
47 await dictionaryDatabase.prepare();
48
49 const {errors, result} = await dictionaryImporter.importDictionary(
50 dictionaryDatabase,
51 testDictionaryData,
52 {prefixWildcardsSupported: true, yomitanVersion: '0.0.0.0'},
53 );
54
55 expect(errors.length).toEqual(0);
56 expect(result).not.toBeNull();
57
58 const styles = result?.styles ?? '';
59
60 // Setup translator
61 const translator = new Translator(dictionaryDatabase);
62 translator.prepare();
63
64 return {translator, styles};
65}
66
67/**
68 * @param {string|undefined} htmlFilePath
69 * @param {string} dictionaryDirectory
70 * @param {string} dictionaryName
71 * @returns {Promise<import('vitest').TestAPI<{window: import('jsdom').DOMWindow, translator: Translator, styles: string}>>}
72 */
73export async function createTranslatorTest(htmlFilePath, dictionaryDirectory, dictionaryName) {
74 const test = createDomTest(htmlFilePath);
75 const {translator, styles} = await createTranslatorContext(dictionaryDirectory, dictionaryName);
76 /** @type {import('vitest').TestAPI<{window: import('jsdom').DOMWindow, translator: Translator, styles: string}>} */
77 // eslint-disable-next-line sonarjs/prefer-immediate-return
78 const result = test.extend({
79 window: async ({window}, use) => { await use(window); },
80 // eslint-disable-next-line no-empty-pattern
81 translator: async ({}, use) => { await use(translator); },
82 // eslint-disable-next-line no-empty-pattern
83 styles: async ({}, use) => { await use(styles); },
84 });
85 return result;
86}