/* * Copyright (C) 2023 Yomitan Authors * Copyright (C) 2020-2022 Yomichan Authors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ import {IDBKeyRange, indexedDB} from 'fake-indexeddb'; import {readFileSync} from 'fs'; import {fileURLToPath, pathToFileURL} from 'node:url'; import {dirname, join, resolve} from 'path'; import {expect, vi} from 'vitest'; import {parseJson} from '../../dev/json.js'; import {createDictionaryArchive} from '../../dev/util.js'; import {AnkiNoteDataCreator} from '../../ext/js/data/sandbox/anki-note-data-creator.js'; import {DictionaryDatabase} from '../../ext/js/language/dictionary-database.js'; import {DictionaryImporter} from '../../ext/js/language/dictionary-importer.js'; import {JapaneseUtil} from '../../ext/js/language/sandbox/japanese-util.js'; import {Translator} from '../../ext/js/language/translator.js'; import {DictionaryImporterMediaLoader} from '../mocks/dictionary-importer-media-loader.js'; import {createDomTest} from './dom-test.js'; const extDir = join(dirname(fileURLToPath(import.meta.url)), '../../ext'); const deinflectionReasonsPath = join(extDir, 'data/deinflect.json'); /** @type {import('dev/vm').PseudoChrome} */ const chrome = { runtime: { getURL: (path) => { return pathToFileURL(join(extDir, path.replace(/^\//, ''))).href; } } }; /** * @param {string} url * @returns {Promise} */ async function fetch(url) { let filePath; try { filePath = fileURLToPath(url); } catch (e) { filePath = resolve(extDir, url.replace(/^[/\\]/, '')); } await Promise.resolve(); const content = readFileSync(filePath, {encoding: null}); return { ok: true, status: 200, statusText: 'OK', text: async () => content.toString('utf8'), json: async () => parseJson(content.toString('utf8')) }; } vi.stubGlobal('indexedDB', indexedDB); vi.stubGlobal('IDBKeyRange', IDBKeyRange); vi.stubGlobal('fetch', fetch); vi.stubGlobal('chrome', chrome); /** * @param {string} dictionaryDirectory * @param {string} dictionaryName * @returns {Promise<{translator: Translator, ankiNoteDataCreator: AnkiNoteDataCreator}>} */ async function createTranslatorContext(dictionaryDirectory, dictionaryName) { // Dictionary const testDictionary = createDictionaryArchive(dictionaryDirectory, dictionaryName); const testDictionaryContent = await testDictionary.generateAsync({type: 'arraybuffer'}); // Setup database const dictionaryImporterMediaLoader = new DictionaryImporterMediaLoader(); const dictionaryImporter = new DictionaryImporter(dictionaryImporterMediaLoader); const dictionaryDatabase = new DictionaryDatabase(); await dictionaryDatabase.prepare(); const {errors} = await dictionaryImporter.importDictionary( dictionaryDatabase, testDictionaryContent, {prefixWildcardsSupported: true} ); expect(errors.length).toEqual(0); // Setup translator const japaneseUtil = new JapaneseUtil(null); const translator = new Translator({japaneseUtil, database: dictionaryDatabase}); /** @type {import('deinflector').ReasonsRaw} */ const deinflectionReasons = parseJson(readFileSync(deinflectionReasonsPath, {encoding: 'utf8'})); translator.prepare(deinflectionReasons); // Assign properties const ankiNoteDataCreator = new AnkiNoteDataCreator(japaneseUtil); return {translator, ankiNoteDataCreator}; } /** * @param {string|undefined} htmlFilePath * @param {string} dictionaryDirectory * @param {string} dictionaryName * @returns {Promise>} */ export async function createTranslatorTest(htmlFilePath, dictionaryDirectory, dictionaryName) { const test = createDomTest(htmlFilePath); const {translator, ankiNoteDataCreator} = await createTranslatorContext(dictionaryDirectory, dictionaryName); /** @type {import('vitest').TestAPI<{window: import('jsdom').DOMWindow, translator: Translator, ankiNoteDataCreator: AnkiNoteDataCreator}>} */ const result = test.extend({ window: async ({window}, use) => { await use(window); }, // eslint-disable-next-line no-empty-pattern translator: async ({}, use) => { await use(translator); }, // eslint-disable-next-line no-empty-pattern ankiNoteDataCreator: async ({}, use) => { await use(ankiNoteDataCreator); } }); return result; }