Database test updates (#1086)

* Remove unused

* Create DatabaseVM

* Update sequences in test dictionary

* Update documentation

* Add second valid testing dictionary

* Set up translator tests

* Write expected data
This commit is contained in:
toasted-nutbread 2020-12-08 20:27:36 -05:00 committed by GitHub
parent 0dc170e70b
commit 2910685a96
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 16949 additions and 139 deletions

109
dev/database-vm.js Normal file
View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2020 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 <https://www.gnu.org/licenses/>.
*/
const fs = require('fs');
const url = require('url');
const path = require('path');
const {JSZip} = require('./util');
const {VM} = require('./vm');
require('fake-indexeddb/auto');
const chrome = {
runtime: {
getURL: (path2) => {
return url.pathToFileURL(path.join(__dirname, '..', 'ext', path2.replace(/^\//, ''))).href;
}
}
};
class Image {
constructor() {
this._src = '';
this._loadCallbacks = [];
}
get src() {
return this._src;
}
set src(value) {
this._src = value;
this._delayTriggerLoad();
}
get naturalWidth() {
return 100;
}
get naturalHeight() {
return 100;
}
addEventListener(eventName, callback) {
if (eventName === 'load') {
this._loadCallbacks.push(callback);
}
}
removeEventListener(eventName, callback) {
if (eventName === 'load') {
const index = this._loadCallbacks.indexOf(callback);
if (index >= 0) {
this._loadCallbacks.splice(index, 1);
}
}
}
async _delayTriggerLoad() {
await Promise.resolve();
for (const callback of this._loadCallbacks) {
callback();
}
}
}
async function fetch(url2) {
const filePath = url.fileURLToPath(url2);
await Promise.resolve();
const content = fs.readFileSync(filePath, {encoding: null});
return {
ok: true,
status: 200,
statusText: 'OK',
text: async () => Promise.resolve(content.toString('utf8')),
json: async () => Promise.resolve(JSON.parse(content.toString('utf8')))
};
}
class DatabaseVM extends VM {
constructor() {
super({
chrome,
Image,
fetch,
indexedDB: global.indexedDB,
IDBKeyRange: global.IDBKeyRange,
JSZip
});
this.context.window = this.context;
this.indexedDB = global.indexedDB;
}
}
module.exports = {
DatabaseVM
};

View File

@ -55,10 +55,11 @@ class Translator {
/** /**
* Finds term definitions for the given text. * Finds term definitions for the given text.
* @param mode The mode to use for finding terms, which determines the format of the resulting array. * @param mode The mode to use for finding terms, which determines the format of the resulting array.
* One of: 'group', 'merge', 'split', 'simple'
* @param text The text to find terms for. * @param text The text to find terms for.
* @param options An object using the following structure: * @param options An object using the following structure:
* { * {
* wildcard: (null or string), * wildcard: (enum: null, 'prefix', 'suffix'),
* mainDictionary: (string), * mainDictionary: (string),
* alphanumeric: (boolean), * alphanumeric: (boolean),
* convertHalfWidthCharacters: (enum: 'false', 'true', 'variant'), * convertHalfWidthCharacters: (enum: 'false', 'true', 'variant'),

View File

@ -16,20 +16,20 @@
["打つ", "うつ", "tag1 tag2", "v5", 15, ["definition13a (打つ, うつ)", "definition13b (打つ, うつ)"], 3, "tag3 tag4 tag5"], ["打つ", "うつ", "tag1 tag2", "v5", 15, ["definition13a (打つ, うつ)", "definition13b (打つ, うつ)"], 3, "tag3 tag4 tag5"],
["打つ", "うつ", "tag1 tag2", "v5", 16, ["definition14a (打つ, うつ)", "definition14b (打つ, うつ)"], 3, "tag3 tag4 tag5"], ["打つ", "うつ", "tag1 tag2", "v5", 16, ["definition14a (打つ, うつ)", "definition14b (打つ, うつ)"], 3, "tag3 tag4 tag5"],
["打つ", "うつ", "tag1 tag2", "v5", 17, ["definition15a (打つ, うつ)", "definition15b (打つ, うつ)"], 3, "tag3 tag4 tag5"], ["打つ", "うつ", "tag1 tag2", "v5", 17, ["definition15a (打つ, うつ)", "definition15b (打つ, うつ)"], 3, "tag3 tag4 tag5"],
["打つ", "ぶつ", "tag1 tag2", "v5", 18, ["definition1a (打つ, ぶつ)", "definition1b (打つ, ぶつ)"], 4, "tag3 tag4 tag5"], ["打つ", "ぶつ", "tag1 tag2", "v5", 18, ["definition1a (打つ, ぶつ)", "definition1b (打つ, ぶつ)"], 3, "tag3 tag4 tag5"],
["打つ", "ぶつ", "tag1 tag2", "v5", 19, ["definition2a (打つ, ぶつ)", "definition2b (打つ, ぶつ)"], 4, "tag3 tag4 tag5"], ["打つ", "ぶつ", "tag1 tag2", "v5", 19, ["definition2a (打つ, ぶつ)", "definition2b (打つ, ぶつ)"], 3, "tag3 tag4 tag5"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 20, ["definition1a (打ち込む, うちこむ)", "definition1b (打ち込む, うちこむ)"], 5, "tag3 tag4 tag5"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 20, ["definition1a (打ち込む, うちこむ)", "definition1b (打ち込む, うちこむ)"], 4, "tag3 tag4 tag5"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 21, ["definition2a (打ち込む, うちこむ)", "definition2b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 21, ["definition2a (打ち込む, うちこむ)", "definition2b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 22, ["definition3a (打ち込む, うちこむ)", "definition3b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 22, ["definition3a (打ち込む, うちこむ)", "definition3b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 23, ["definition4a (打ち込む, うちこむ)", "definition4b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 23, ["definition4a (打ち込む, うちこむ)", "definition4b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 24, ["definition5a (打ち込む, うちこむ)", "definition5b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 24, ["definition5a (打ち込む, うちこむ)", "definition5b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 25, ["definition6a (打ち込む, うちこむ)", "definition6b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 25, ["definition6a (打ち込む, うちこむ)", "definition6b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 26, ["definition7a (打ち込む, うちこむ)", "definition7b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 26, ["definition7a (打ち込む, うちこむ)", "definition7b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 27, ["definition8a (打ち込む, うちこむ)", "definition8b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 27, ["definition8a (打ち込む, うちこむ)", "definition8b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 28, ["definition9a (打ち込む, うちこむ)", "definition9b (打ち込む, うちこむ)"], 5, "tag5 tag6 tag7"], ["打ち込む", "うちこむ", "tag1 tag2", "v5", 28, ["definition9a (打ち込む, うちこむ)", "definition9b (打ち込む, うちこむ)"], 4, "tag5 tag6 tag7"],
["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 29, ["definition1a (打ち込む, ぶちこむ)", "definition1b (打ち込む, ぶちこむ)"], 6, "tag3 tag4 tag5"], ["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 29, ["definition1a (打ち込む, ぶちこむ)", "definition1b (打ち込む, ぶちこむ)"], 4, "tag3 tag4 tag5"],
["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 30, ["definition2a (打ち込む, ぶちこむ)", "definition2b (打ち込む, ぶちこむ)"], 6, "tag3 tag4 tag5"], ["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 30, ["definition2a (打ち込む, ぶちこむ)", "definition2b (打ち込む, ぶちこむ)"], 4, "tag3 tag4 tag5"],
["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 31, ["definition3a (打ち込む, ぶちこむ)", "definition3b (打ち込む, ぶちこむ)"], 6, "tag3 tag4 tag5"], ["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 31, ["definition3a (打ち込む, ぶちこむ)", "definition3b (打ち込む, ぶちこむ)"], 4, "tag3 tag4 tag5"],
["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 32, ["definition4a (打ち込む, ぶちこむ)", "definition4b (打ち込む, ぶちこむ)"], 6, "tag3 tag4 tag5"], ["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 32, ["definition4a (打ち込む, ぶちこむ)", "definition4b (打ち込む, ぶちこむ)"], 4, "tag3 tag4 tag5"],
["画像", "がぞう", "tag1 tag2", "", 33, ["definition1a (画像, がぞう)", {"type": "image", "path": "image.gif", "width": 350, "height": 350, "description": "An image", "pixelated": true}], 7, "tag3 tag4 tag5"] ["画像", "がぞう", "tag1 tag2", "", 33, ["definition1a (画像, がぞう)", {"type": "image", "path": "image.gif", "width": 350, "height": 350, "description": "An image", "pixelated": true}], 5, "tag3 tag4 tag5"]
] ]

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 B

View File

@ -0,0 +1,6 @@
{
"title": "Test Dictionary 2",
"format": 3,
"revision": "test",
"sequenced": true
}

View File

@ -0,0 +1,42 @@
[
[
"打",
"ダ ダアス",
"う.つ う.ち- ぶ.つ",
"ktag1 ktag2",
[
"meaning1",
"meaning2",
"meaning3",
"meaning4",
"meaning5"
],
{
"kstat1": "1",
"kstat2": "2",
"kstat3": "3",
"kstat4": "4",
"kstat5": "5"
}
],
[
"込",
"",
"-こ.む こ.む こ.み -こ.み こ.める",
"ktag1 ktag2",
[
"meaning1",
"meaning2",
"meaning3",
"meaning4",
"meaning5"
],
{
"kstat1": "1",
"kstat2": "2",
"kstat3": "3",
"kstat4": "4",
"kstat5": "5"
}
]
]

View File

@ -0,0 +1,4 @@
[
["打", "freq", 1],
["込", "freq", 2]
]

View File

@ -0,0 +1,7 @@
[
["tag1", "category1", 0, "tag1 notes", 0],
["tag2", "category2", 0, "tag2 notes", 0],
["tag3", "category3", 0, "tag3 notes", 0],
["tag4", "category4", 0, "tag4 notes", 0],
["tag5", "category5", 0, "tag5 notes", 0]
]

View File

@ -0,0 +1,9 @@
[
["ktag1", "kcategory1", 0, "ktag1 notes", 0],
["ktag2", "kcategory2", 0, "ktag2 notes", 0],
["kstat1", "kcategory3", 0, "kstat1 notes", 0],
["kstat2", "kcategory4", 0, "kstat2 notes", 0],
["kstat3", "kcategory5", 0, "kstat3 notes", 0],
["kstat4", "kcategory6", 0, "kstat4 notes", 0],
["kstat5", "kcategory7", 0, "kstat5 notes", 0]
]

View File

@ -0,0 +1,4 @@
[
["ptag1", "pcategory1", 0, "ptag1 notes", 0],
["ptag2", "pcategory2", 0, "ptag2 notes", 0]
]

View File

@ -0,0 +1,13 @@
[
["打", "だ", "tag1 tag2", "", 1, ["definition1", "definition2"], 1, "tag3 tag4 tag5"],
["打", "ダース", "tag1 tag2", "", 1, ["definition3", "definition4"], 2, "tag3 tag4 tag5"],
["打つ", "うつ", "tag1 tag2", "v5", 10, ["definition5", "definition6"], 3, "tag3 tag4 tag5"],
["打つ", "うつ", "tag1 tag2", "v5", 1, ["definition7", "definition8"], 3, "tag3 tag4 tag5"],
["打つ", "ぶつ", "tag1 tag2", "v5", 10, ["definition9", "definition10"], 3, "tag3 tag4 tag5"],
["打つ", "ぶつ", "tag1 tag2", "v5", 1, ["definition11", "definition12"], 3, "tag3 tag4 tag5"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 10, ["definition13", "definition14"], 4, "tag3 tag4 tag5"],
["打ち込む", "うちこむ", "tag1 tag2", "v5", 1, ["definition15", "definition16"], 4, "tag5 tag6 tag7"],
["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 10, ["definition17", "definition18"], 4, "tag3 tag4 tag5"],
["打ち込む", "ぶちこむ", "tag1 tag2", "v5", 1, ["definition19", "definition20"], 4, "tag3 tag4 tag5"],
["画像", "がぞう", "tag1 tag2", "", 1, ["definition21", {"type": "image", "path": "image.gif", "width": 350, "height": 350, "description": "An image", "pixelated": true}], 5, "tag3 tag4 tag5"]
]

View File

@ -0,0 +1,33 @@
[
["打", "freq", 1],
["打つ", "freq", 2],
["打ち込む", "freq", 3],
["打", "freq", {"reading": "だ", "frequency": 4}],
["打", "freq", {"reading": "ダース", "frequency": 5}],
["打つ", "freq", {"reading": "うつ", "frequency": 6}],
["打つ", "freq", {"reading": "ぶつ", "frequency": 7}],
["打ち込む", "freq", {"reading": "うちこむ", "frequency": 8}],
["打ち込む", "freq", {"reading": "ぶちこむ", "frequency": 9}],
[
"打ち込む",
"pitch",
{
"reading": "うちこむ",
"pitches": [
{"position": 0},
{"position": 3}
]
}
],
[
"打ち込む",
"pitch",
{
"reading": "ぶちこむ",
"pitches": [
{"position": 0},
{"position": 3}
]
}
]
]

File diff suppressed because it is too large Load Diff

View File

@ -15,102 +15,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
const fs = require('fs');
const url = require('url');
const path = require('path'); const path = require('path');
const assert = require('assert'); const assert = require('assert');
const {JSZip, createDictionaryArchive, testMain} = require('../dev/util'); const {createDictionaryArchive, testMain} = require('../dev/util');
const {VM} = require('../dev/vm'); const {DatabaseVM} = require('../dev/database-vm');
require('fake-indexeddb/auto');
const chrome = {
runtime: {
onMessage: {
addListener() { /* NOP */ },
removeListener() { /* NOP */ }
},
getURL(path2) {
return url.pathToFileURL(path.join(__dirname, '..', 'ext', path2.replace(/^\//, ''))).href;
},
sendMessage() {
// NOP
}
}
};
class Image {
constructor() {
this._src = '';
this._loadCallbacks = [];
}
get src() {
return this._src;
}
set src(value) {
this._src = value;
this._delayTriggerLoad();
}
get naturalWidth() {
return 100;
}
get naturalHeight() {
return 100;
}
addEventListener(eventName, callback) {
if (eventName === 'load') {
this._loadCallbacks.push(callback);
}
}
removeEventListener(eventName, callback) {
if (eventName === 'load') {
const index = this._loadCallbacks.indexOf(callback);
if (index >= 0) {
this._loadCallbacks.splice(index, 1);
}
}
}
async _delayTriggerLoad() {
await Promise.resolve();
for (const callback of this._loadCallbacks) {
callback();
}
}
}
async function fetch(url2) {
const filePath = url.fileURLToPath(url2);
await Promise.resolve();
const content = fs.readFileSync(filePath, {encoding: null});
return {
ok: true,
status: 200,
statusText: 'OK',
text: async () => Promise.resolve(content.toString('utf8')),
json: async () => Promise.resolve(JSON.parse(content.toString('utf8')))
};
}
const vm = new VM({ const vm = new DatabaseVM();
chrome,
Image,
fetch,
indexedDB: global.indexedDB,
IDBKeyRange: global.IDBKeyRange,
JSZip,
addEventListener() {
// NOP
}
});
vm.context.window = vm.context;
vm.execute([ vm.execute([
'mixed/js/core.js', 'mixed/js/core.js',
'mixed/js/cache-map.js', 'mixed/js/cache-map.js',
@ -155,7 +66,7 @@ function clearDatabase(timeout) {
}, timeout); }, timeout);
(async () => { (async () => {
const indexedDB = global.indexedDB; const indexedDB = vm.indexedDB;
for (const {name} of await indexedDB.databases()) { for (const {name} of await indexedDB.databases()) {
await new Promise((resolve2, reject2) => { await new Promise((resolve2, reject2) => {
const request = indexedDB.deleteDatabase(name); const request = indexedDB.deleteDatabase(name);
@ -477,15 +388,16 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
{ {
inputs: [ inputs: [
{ {
sequenceList: [1, 2, 3, 4, 5, 6] sequenceList: [1, 2, 3, 4, 5]
} }
], ],
expectedResults: { expectedResults: {
total: 32, total: 33,
expressions: [ expressions: [
['打', 2], ['打', 2],
['打つ', 17], ['打つ', 17],
['打ち込む', 13] ['打ち込む', 13],
['画像', 1]
], ],
readings: [ readings: [
['だ', 1], ['だ', 1],
@ -493,7 +405,8 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
['うつ', 15], ['うつ', 15],
['ぶつ', 2], ['ぶつ', 2],
['うちこむ', 9], ['うちこむ', 9],
['ぶちこむ', 4] ['ぶちこむ', 4],
['がぞう', 1]
] ]
} }
}, },
@ -536,12 +449,13 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
} }
], ],
expectedResults: { expectedResults: {
total: 15, total: 17,
expressions: [ expressions: [
['打つ', 15] ['打つ', 17]
], ],
readings: [ readings: [
['うつ', 15] ['うつ', 15],
['ぶつ', 2]
] ]
} }
}, },
@ -552,12 +466,13 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
} }
], ],
expectedResults: { expectedResults: {
total: 2, total: 13,
expressions: [ expressions: [
['打つ', 2] ['打ち込む', 13]
], ],
readings: [ readings: [
['ぶつ', 2] ['うちこむ', 9],
['ぶちこむ', 4]
] ]
} }
}, },
@ -568,28 +483,12 @@ async function testFindTermsBySequenceBulk1(database, mainDictionary) {
} }
], ],
expectedResults: { expectedResults: {
total: 9, total: 1,
expressions: [ expressions: [
['打ち込む', 9] ['画像', 1]
], ],
readings: [ readings: [
['うちこむ', 9] ['がぞう', 1]
]
}
},
{
inputs: [
{
sequenceList: [6]
}
],
expectedResults: {
total: 4,
expressions: [
['打ち込む', 4]
],
readings: [
['ぶちこむ', 4]
] ]
} }
}, },

View File

@ -29,6 +29,7 @@ function createTestDictionaryArchive(dictionary, dictionaryName) {
async function main() { async function main() {
const dictionaries = [ const dictionaries = [
{name: 'valid-dictionary1', valid: true}, {name: 'valid-dictionary1', valid: true},
{name: 'valid-dictionary2', valid: true},
{name: 'invalid-dictionary1', valid: false}, {name: 'invalid-dictionary1', valid: false},
{name: 'invalid-dictionary2', valid: false}, {name: 'invalid-dictionary2', valid: false},
{name: 'invalid-dictionary3', valid: false}, {name: 'invalid-dictionary3', valid: false},

175
test/test-translator.js Normal file
View File

@ -0,0 +1,175 @@
/*
* Copyright (C) 2020 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 <https://www.gnu.org/licenses/>.
*/
const fs = require('fs');
const path = require('path');
const assert = require('assert');
const {createDictionaryArchive, testMain} = require('../dev/util');
const {DatabaseVM} = require('../dev/database-vm');
function createTestDictionaryArchive(dictionary, dictionaryName) {
const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary);
return createDictionaryArchive(dictionaryDirectory, dictionaryName);
}
function clone(value) {
return JSON.parse(JSON.stringify(value));
}
async function createVM() {
// Set up VM
const vm = new DatabaseVM();
vm.execute([
'mixed/js/core.js',
'mixed/js/cache-map.js',
'mixed/js/japanese.js',
'bg/js/json-schema.js',
'bg/js/media-utility.js',
'bg/js/dictionary-importer.js',
'bg/js/database.js',
'bg/js/dictionary-database.js',
'bg/js/text-source-map.js',
'bg/js/deinflector.js',
'bg/js/translator.js'
]);
const [
DictionaryImporter,
DictionaryDatabase,
JapaneseUtil,
Translator
] = vm.get([
'DictionaryImporter',
'DictionaryDatabase',
'JapaneseUtil',
'Translator'
]);
// Dictionary
const testDictionary = createTestDictionaryArchive('valid-dictionary2');
const testDictionaryContent = await testDictionary.generateAsync({type: 'string'});
// Setup database
const dictionaryImporter = new DictionaryImporter();
const dictionaryDatabase = new DictionaryDatabase();
await dictionaryDatabase.prepare();
const {result, errors} = await dictionaryImporter.importDictionary(
dictionaryDatabase,
testDictionaryContent,
{prefixWildcardsSupported: true},
() => {}
);
assert.deepStrictEqual(errors.length, 0);
// Setup translator
const japaneseUtil = new JapaneseUtil(null);
const translator = new Translator({japaneseUtil, database: dictionaryDatabase});
const deinflectionReasions = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'ext', 'bg/lang/deinflect.json')));
translator.prepare(deinflectionReasions);
// Done
return {vm, translator, dictionary: result};
}
function buildOptions(optionsPresets, optionsArray, dictionaryTitle) {
const options = {};
if (!Array.isArray(optionsArray)) { optionsArray = [optionsArray]; }
for (const entry of optionsArray) {
switch (typeof entry) {
case 'string':
if (!Object.prototype.hasOwnProperty.call(optionsPresets, entry)) {
throw new Error('Invalid options preset');
}
Object.assign(options, clone(optionsPresets[entry]));
break;
case 'object':
Object.assign(options, clone(entry));
break;
default:
throw new Error('Invalid options type');
}
}
// Update structure
const placeholder = '${title}';
if (options.mainDictionary === placeholder) {
options.mainDictionary = dictionaryTitle;
}
let {enabledDictionaryMap} = options;
if (Array.isArray(enabledDictionaryMap)) {
for (const entry of enabledDictionaryMap) {
if (entry[0] === placeholder) {
entry[0] = dictionaryTitle;
}
}
enabledDictionaryMap = new Map(enabledDictionaryMap);
options.enabledDictionaryMap = enabledDictionaryMap;
}
return options;
}
async function main() {
const write = (process.argv[2] === '--write');
const {translator, dictionary: {title}} = await createVM();
const dataFilePath = path.join(__dirname, 'data', 'test-translator-data.json');
const data = JSON.parse(fs.readFileSync(dataFilePath, {encoding: 'utf8'}));
const {optionsPresets, tests} = data;
for (const test of tests) {
switch (test.func) {
case 'findTerms':
{
const {mode, text} = test;
const options = buildOptions(optionsPresets, test.options, title);
const [definitions, length] = clone(await translator.findTerms(mode, text, options));
if (write) {
test.expected = {length, definitions};
} else {
const {expected} = test;
assert.deepStrictEqual(length, expected.length);
assert.deepStrictEqual(definitions, expected.definitions);
}
}
break;
case 'findKanji':
{
const {text} = test;
const options = buildOptions(optionsPresets, test.options, title);
const definitions = clone(await translator.findKanji(text, options));
if (write) {
test.expected = {definitions};
} else {
const {expected} = test;
assert.deepStrictEqual(definitions, expected.definitions);
}
}
break;
}
}
if (write) {
fs.writeFileSync(dataFilePath, JSON.stringify(data, null, 4), {encoding: 'utf8'});
}
}
if (require.main === module) { testMain(main); }