diff options
Diffstat (limited to 'test')
21 files changed, 240 insertions, 38 deletions
| diff --git a/test/data/dictionaries/invalid-dictionary1/index.json b/test/data/dictionaries/invalid-dictionary1/index.json new file mode 100644 index 00000000..1be3b360 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary1/index.json @@ -0,0 +1,7 @@ +{ +    "title": "Invalid Dictionary 1", +    "format": 0, +    "revision": "test", +    "sequenced": true, +    "description": "Invalid format number" +}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary2/index.json b/test/data/dictionaries/invalid-dictionary2/index.json new file mode 100644 index 00000000..ba2cc669 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary2/index.json @@ -0,0 +1,7 @@ +{ +    "title": "Invalid Dictionary 2", +    "format": 3, +    "revision": "test", +    "sequenced": true, +    "description": "Empty entry in kanji bank" +}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary2/kanji_bank_1.json b/test/data/dictionaries/invalid-dictionary2/kanji_bank_1.json new file mode 100644 index 00000000..5825bcac --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary2/kanji_bank_1.json @@ -0,0 +1,3 @@ +[ +    [] +]
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary3/index.json b/test/data/dictionaries/invalid-dictionary3/index.json new file mode 100644 index 00000000..f23fa3f0 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary3/index.json @@ -0,0 +1,7 @@ +{ +    "title": "Invalid Dictionary 3", +    "format": 3, +    "revision": "test", +    "sequenced": true, +    "description": "Invalid type entry in kanji meta bank" +}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary3/kanji_meta_bank_1.json b/test/data/dictionaries/invalid-dictionary3/kanji_meta_bank_1.json new file mode 100644 index 00000000..9e26dfee --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary3/kanji_meta_bank_1.json @@ -0,0 +1 @@ +{}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary4/index.json b/test/data/dictionaries/invalid-dictionary4/index.json new file mode 100644 index 00000000..542791d7 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary4/index.json @@ -0,0 +1,7 @@ +{ +    "title": "Invalid Dictionary 4", +    "format": 3, +    "revision": "test", +    "sequenced": true, +    "description": "Invalid value as part of a tag bank entry" +}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary4/tag_bank_1.json b/test/data/dictionaries/invalid-dictionary4/tag_bank_1.json new file mode 100644 index 00000000..4f19b476 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary4/tag_bank_1.json @@ -0,0 +1,3 @@ +[ +    [{"invalid": true}, "category1", 0, "tag1 notes", 0] +]
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary5/index.json b/test/data/dictionaries/invalid-dictionary5/index.json new file mode 100644 index 00000000..e0d0f00e --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary5/index.json @@ -0,0 +1,7 @@ +{ +    "title": "Invalid Dictionary 5", +    "format": 3, +    "revision": "test", +    "sequenced": true, +    "description": "Invalid type as part of a term bank entry" +}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary5/term_bank_1.json b/test/data/dictionaries/invalid-dictionary5/term_bank_1.json new file mode 100644 index 00000000..7288a996 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary5/term_bank_1.json @@ -0,0 +1,3 @@ +[ +    ["打", "だ", "tag1 tag2", "", 2, false, 1, "tag3 tag4 tag5"] +]
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary6/index.json b/test/data/dictionaries/invalid-dictionary6/index.json new file mode 100644 index 00000000..b91acca3 --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary6/index.json @@ -0,0 +1,7 @@ +{ +    "title": "Invalid Dictionary 6", +    "format": 3, +    "revision": "test", +    "sequenced": true, +    "description": "Invalid root type for term meta bank" +}
\ No newline at end of file diff --git a/test/data/dictionaries/invalid-dictionary6/term_meta_bank_1.json b/test/data/dictionaries/invalid-dictionary6/term_meta_bank_1.json new file mode 100644 index 00000000..02e4a84d --- /dev/null +++ b/test/data/dictionaries/invalid-dictionary6/term_meta_bank_1.json @@ -0,0 +1 @@ +false
\ No newline at end of file diff --git a/test/test-dictionary-data/index.json b/test/data/dictionaries/valid-dictionary1/index.json index 3034bf38..3034bf38 100644 --- a/test/test-dictionary-data/index.json +++ b/test/data/dictionaries/valid-dictionary1/index.json diff --git a/test/test-dictionary-data/kanji_bank_1.json b/test/data/dictionaries/valid-dictionary1/kanji_bank_1.json index 264f94c1..264f94c1 100644 --- a/test/test-dictionary-data/kanji_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/kanji_bank_1.json diff --git a/test/test-dictionary-data/kanji_meta_bank_1.json b/test/data/dictionaries/valid-dictionary1/kanji_meta_bank_1.json index 73e75b8a..73e75b8a 100644 --- a/test/test-dictionary-data/kanji_meta_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/kanji_meta_bank_1.json diff --git a/test/test-dictionary-data/tag_bank_1.json b/test/data/dictionaries/valid-dictionary1/tag_bank_1.json index 109ad395..109ad395 100644 --- a/test/test-dictionary-data/tag_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/tag_bank_1.json diff --git a/test/test-dictionary-data/tag_bank_2.json b/test/data/dictionaries/valid-dictionary1/tag_bank_2.json index 5e7936b3..5e7936b3 100644 --- a/test/test-dictionary-data/tag_bank_2.json +++ b/test/data/dictionaries/valid-dictionary1/tag_bank_2.json diff --git a/test/test-dictionary-data/term_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_bank_1.json index 755d9f6a..755d9f6a 100644 --- a/test/test-dictionary-data/term_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/term_bank_1.json diff --git a/test/test-dictionary-data/term_meta_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json index 78096502..78096502 100644 --- a/test/test-dictionary-data/term_meta_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json diff --git a/test/test-database.js b/test/test-database.js index fcf519d7..4fb3805d 100644 --- a/test/test-database.js +++ b/test/test-database.js @@ -1,3 +1,6 @@ +const fs = require('fs'); +const url = require('url'); +const path = require('path');  const assert = require('assert');  const yomichanTest = require('./yomichan-test');  require('fake-indexeddb/auto'); @@ -5,21 +8,86 @@ require('fake-indexeddb/auto');  const chrome = {      runtime: {          onMessage: { -            addListener: () => { /* NOP */ } +            addListener() { /* NOP */ } +        }, +        getURL(path2) { +            return url.pathToFileURL(path.join(__dirname, '..', 'ext', path2.replace(/^\//, '')));          }      }  }; -const {Database} = yomichanTest.requireScript('ext/bg/js/database.js', ['Database']); +class XMLHttpRequest { +    constructor() { +        this._eventCallbacks = new Map(); +        this._url = ''; +        this._responseText = null; +    } + +    overrideMimeType() { +        // NOP +    } + +    addEventListener(eventName, callback) { +        let callbacks = this._eventCallbacks.get(eventName); +        if (typeof callbacks === 'undefined') { +            callbacks = []; +            this._eventCallbacks.set(eventName, callbacks); +        } +        callbacks.push(callback); +    } + +    open(action, url) { +        this._url = url; +    } + +    send() { +        const filePath = url.fileURLToPath(this._url); +        Promise.resolve() +            .then(() => { +                let source; +                try { +                    source = fs.readFileSync(filePath, {encoding: 'utf8'}); +                } catch (e) { +                    this._trigger('error'); +                    return; +                } +                this._responseText = source; +                this._trigger('load'); +            }); +    } + +    get responseText() { +        return this._responseText; +    } + +    _trigger(eventName, ...args) { +        const callbacks = this._eventCallbacks.get(eventName); +        if (typeof callbacks === 'undefined') { return; } + +        for (let i = 0, ii = callbacks.length; i < ii; ++i) { +            callbacks[i](...args); +        } +    } +} + +const {JsonSchema} = yomichanTest.requireScript('ext/bg/js/json-schema.js', ['JsonSchema']);  const {dictFieldSplit, dictTagSanitize} = yomichanTest.requireScript('ext/bg/js/dictionary.js', ['dictFieldSplit', 'dictTagSanitize']);  const {stringReverse, hasOwn} = yomichanTest.requireScript('ext/mixed/js/core.js', ['stringReverse', 'hasOwn'], {chrome}); - -global.window = global; -global.JSZip = yomichanTest.JSZip; -global.dictFieldSplit = dictFieldSplit; -global.dictTagSanitize = dictTagSanitize; -global.stringReverse = stringReverse; -global.hasOwn = hasOwn; +const {requestJson} = yomichanTest.requireScript('ext/bg/js/request.js', ['requestJson'], {XMLHttpRequest}); + +const databaseGlobals = { +    chrome, +    JsonSchema, +    requestJson, +    stringReverse, +    hasOwn, +    dictFieldSplit, +    dictTagSanitize, +    indexedDB: global.indexedDB, +    JSZip: yomichanTest.JSZip +}; +databaseGlobals.window = databaseGlobals; +const {Database} = yomichanTest.requireScript('ext/bg/js/database.js', ['Database'], databaseGlobals);  function countTermsWithExpression(terms, expression) { @@ -39,21 +107,31 @@ function countKanjiWithCharacter(kanji, character) {  } -async function clearDatabase() { -    const indexedDB = global.indexedDB; -    for (const {name} of await indexedDB.databases()) { -        await new Promise((resolve, reject) => { -            const request = indexedDB.deleteDatabase(name); -            request.onerror = (e) => reject(e); -            request.onsuccess = () => resolve(); -        }); -    } +function clearDatabase(timeout) { +    return new Promise((resolve, reject) => { +        const timer = setTimeout(() => { +            reject(new Error(`clearDatabase failed to resolve after ${timeout}ms`)); +        }, timeout); + +        (async () => { +            const indexedDB = global.indexedDB; +            for (const {name} of await indexedDB.databases()) { +                await new Promise((resolve, reject) => { +                    const request = indexedDB.deleteDatabase(name); +                    request.onerror = (e) => reject(e); +                    request.onsuccess = () => resolve(); +                }); +            } +            clearTimeout(timer); +            resolve(); +        })(); +    });  }  async function testDatabase1() {      // Load dictionary data -    const testDictionary = yomichanTest.createTestDictionaryArchive(); +    const testDictionary = yomichanTest.createTestDictionaryArchive('valid-dictionary1');      const testDictionarySource = await testDictionary.generateAsync({type: 'string'});      const testDictionaryIndex = JSON.parse(await testDictionary.files['index.json'].async('string')); @@ -732,7 +810,7 @@ async function testFindTagForTitle1(database, title) {  async function testDatabase2() {      // Load dictionary data -    const testDictionary = yomichanTest.createTestDictionaryArchive(); +    const testDictionary = yomichanTest.createTestDictionaryArchive('valid-dictionary1');      const testDictionarySource = await testDictionary.generateAsync({type: 'string'});      const testDictionaryIndex = JSON.parse(await testDictionary.files['index.json'].async('string')); @@ -771,12 +849,61 @@ async function testDatabase2() {  } -async function main() { -    await testDatabase1(); -    await clearDatabase(); +async function testDatabase3() { +    const invalidDictionaries = [ +        'invalid-dictionary1', +        'invalid-dictionary2', +        'invalid-dictionary3', +        'invalid-dictionary4', +        'invalid-dictionary5', +        'invalid-dictionary6' +    ]; -    await testDatabase2(); -    await clearDatabase(); +    // Setup database +    const database = new Database(); +    await database.prepare(); + +    for (const invalidDictionary of invalidDictionaries) { +        const testDictionary = yomichanTest.createTestDictionaryArchive(invalidDictionary); +        const testDictionarySource = await testDictionary.generateAsync({type: 'string'}); + +        let error = null; +        try { +            await database.importDictionary(testDictionarySource, () => {}, {}); +        } catch (e) { +            error = e; +        } + +        if (error === null) { +            assert.ok(false, `Expected an error while importing ${invalidDictionary}`); +        } else { +            const prefix = 'Dictionary has invalid data'; +            const message = error.message; +            assert.ok(typeof message, 'string'); +            assert.ok(message.startsWith(prefix), `Expected error message to start with '${prefix}': ${message}`); +        } +    } + +    await database.close(); +} + + +async function main() { +    const clearTimeout = 5000; +    try { +        await testDatabase1(); +        await clearDatabase(clearTimeout); + +        await testDatabase2(); +        await clearDatabase(clearTimeout); + +        await testDatabase3(); +        await clearDatabase(clearTimeout); +    } catch (e) { +        console.log(e); +        process.exit(-1); +        throw e; +    }  } diff --git a/test/test-dictionary.js b/test/test-dictionary.js index 84014540..b157dd5d 100644 --- a/test/test-dictionary.js +++ b/test/test-dictionary.js @@ -3,9 +3,38 @@ const dictionaryValidate = require('./dictionary-validate');  async function main() { -    const archive = yomichanTest.createTestDictionaryArchive(); +    const dictionaries = [ +        {name: 'valid-dictionary1', valid: true}, +        {name: 'invalid-dictionary1', valid: false}, +        {name: 'invalid-dictionary2', valid: false}, +        {name: 'invalid-dictionary3', valid: false}, +        {name: 'invalid-dictionary4', valid: false}, +        {name: 'invalid-dictionary5', valid: false}, +        {name: 'invalid-dictionary6', valid: false} +    ]; +      const schemas = dictionaryValidate.getSchemas(); -    await dictionaryValidate.validateDictionary(archive, schemas); + +    for (const {name, valid} of dictionaries) { +        const archive = yomichanTest.createTestDictionaryArchive(name); + +        let error = null; +        try { +            await dictionaryValidate.validateDictionary(archive, schemas); +        } catch (e) { +            error = e; +        } + +        if (valid) { +            if (error !== null) { +                throw error; +            } +        } else { +            if (error === null) { +                throw new Error(`Expected dictionary ${name} to be invalid`); +            } +        } +    }  } diff --git a/test/yomichan-test.js b/test/yomichan-test.js index dd4da919..939e0ad2 100644 --- a/test/yomichan-test.js +++ b/test/yomichan-test.js @@ -26,21 +26,14 @@ function getJSZip() {      return JSZip;  } -function createTestDictionaryArchive(dictionaryName) { -    const fileNames = [ -        'index.json', -        'tag_bank_1.json', -        'tag_bank_2.json', -        'term_bank_1.json', -        'kanji_bank_1.json', -        'term_meta_bank_1.json', -        'kanji_meta_bank_1.json' -    ]; +function createTestDictionaryArchive(dictionary, dictionaryName) { +    const dictionaryDirectory = path.join(__dirname, 'data', 'dictionaries', dictionary); +    const fileNames = fs.readdirSync(dictionaryDirectory);      const archive = new (getJSZip())();      for (const fileName of fileNames) { -        const source = fs.readFileSync(path.join(__dirname, 'test-dictionary-data', fileName), {encoding: 'utf8'}); +        const source = fs.readFileSync(path.join(dictionaryDirectory, fileName), {encoding: 'utf8'});          const json = JSON.parse(source);          if (fileName === 'index.json' && typeof dictionaryName === 'string') {              json.title = dictionaryName; |