Pop-up dictionary browser extension for language learning. Successor to Yomichan. (PERSONAL FORK)
at lambda-fork/main 83 lines 3.7 kB view raw
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 {describe, expect, test} from 'vitest'; 20import {LanguageTransformer} from '../../ext/js/language/language-transformer.js'; 21 22/** 23 * @param {LanguageTransformer} languageTransformer 24 * @param {string} source 25 * @param {string} expectedTerm 26 * @param {string|null} expectedConditionName 27 * @param {string[]|null} expectedReasons 28 * @returns {{has: false, reasons: null, rules: null}|{has: true, reasons: string[], rules: number}} 29 */ 30function hasTermReasons(languageTransformer, source, expectedTerm, expectedConditionName, expectedReasons) { 31 for (const {text, conditions, trace} of languageTransformer.transform(source)) { 32 if (text !== expectedTerm) { continue; } 33 if (expectedConditionName !== null) { 34 const expectedConditions = languageTransformer.getConditionFlagsFromConditionType(expectedConditionName); 35 if (!LanguageTransformer.conditionsMatch(conditions, expectedConditions)) { continue; } 36 } 37 let okay = true; 38 if (expectedReasons !== null) { 39 if (trace.length !== expectedReasons.length) { continue; } 40 for (let i = 0, ii = expectedReasons.length; i < ii; ++i) { 41 if (expectedReasons[i] !== trace[i].transform) { 42 okay = false; 43 break; 44 } 45 } 46 } 47 if (okay) { 48 return { 49 has: true, 50 reasons: trace.map((frame) => frame.transform), 51 rules: conditions, 52 }; 53 } 54 } 55 return {has: false, reasons: null, rules: null}; 56} 57 58/** 59 * @param {LanguageTransformer} languageTransformer 60 * @param {import('test/language-transformer-test').LanguageTransformerTestCategory[]} data 61 * @param {(input: string) => string} [preprocess] An optional function for if the input to the transformer needs to be preprocessed. 62 */ 63export function testLanguageTransformer(languageTransformer, data, preprocess) { 64 if (typeof preprocess === 'undefined') { preprocess = (input) => input; } 65 describe('deinflections', () => { 66 describe.each(data)('$category', ({valid, tests}) => { 67 for (const {source, term, rule, reasons} of tests) { 68 const {has} = hasTermReasons(languageTransformer, preprocess(source), preprocess(term), rule, reasons); 69 let message = `${source} ${valid ? 'has' : 'does not have'} term candidate ${JSON.stringify(term)}`; 70 if (rule !== null) { 71 message += ` with rule ${JSON.stringify(rule)}`; 72 } 73 if (reasons !== null) { 74 message += (typeof rule !== 'undefined' ? ' and' : ' with'); 75 message += ` reasons ${JSON.stringify(reasons)}`; 76 } 77 test(`${message}`, () => { 78 expect(has).toStrictEqual(valid); 79 }); 80 } 81 }); 82 }); 83}