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:
parent
0dc170e70b
commit
2910685a96
109
dev/database-vm.js
Normal file
109
dev/database-vm.js
Normal 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
|
||||||
|
};
|
@ -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'),
|
||||||
|
@ -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"]
|
||||||
]
|
]
|
BIN
test/data/dictionaries/valid-dictionary2/image.gif
Normal file
BIN
test/data/dictionaries/valid-dictionary2/image.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 B |
6
test/data/dictionaries/valid-dictionary2/index.json
Normal file
6
test/data/dictionaries/valid-dictionary2/index.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"title": "Test Dictionary 2",
|
||||||
|
"format": 3,
|
||||||
|
"revision": "test",
|
||||||
|
"sequenced": true
|
||||||
|
}
|
42
test/data/dictionaries/valid-dictionary2/kanji_bank_1.json
Normal file
42
test/data/dictionaries/valid-dictionary2/kanji_bank_1.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
["打", "freq", 1],
|
||||||
|
["込", "freq", 2]
|
||||||
|
]
|
7
test/data/dictionaries/valid-dictionary2/tag_bank_1.json
Normal file
7
test/data/dictionaries/valid-dictionary2/tag_bank_1.json
Normal 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]
|
||||||
|
]
|
9
test/data/dictionaries/valid-dictionary2/tag_bank_2.json
Normal file
9
test/data/dictionaries/valid-dictionary2/tag_bank_2.json
Normal 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]
|
||||||
|
]
|
4
test/data/dictionaries/valid-dictionary2/tag_bank_3.json
Normal file
4
test/data/dictionaries/valid-dictionary2/tag_bank_3.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[
|
||||||
|
["ptag1", "pcategory1", 0, "ptag1 notes", 0],
|
||||||
|
["ptag2", "pcategory2", 0, "ptag2 notes", 0]
|
||||||
|
]
|
13
test/data/dictionaries/valid-dictionary2/term_bank_1.json
Normal file
13
test/data/dictionaries/valid-dictionary2/term_bank_1.json
Normal 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"]
|
||||||
|
]
|
@ -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}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
16507
test/data/test-translator-data.json
Normal file
16507
test/data/test-translator-data.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -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]
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -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
175
test/test-translator.js
Normal 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); }
|
Loading…
Reference in New Issue
Block a user