diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/data/dictionaries/valid-dictionary1/tag_bank_3.json | 4 | ||||
-rw-r--r-- | test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json | 36 | ||||
-rw-r--r-- | test/data/html/test-document2-frame1.html | 42 | ||||
-rw-r--r-- | test/data/html/test-document2-script.js | 41 | ||||
-rw-r--r-- | test/data/html/test-document2.html | 81 | ||||
-rw-r--r-- | test/data/html/test-stylesheet.css | 19 | ||||
-rw-r--r-- | test/test-database.js | 9 | ||||
-rw-r--r-- | test/test-japanese.js | 73 | ||||
-rw-r--r-- | test/test-text-source-map.js | 234 |
9 files changed, 526 insertions, 13 deletions
diff --git a/test/data/dictionaries/valid-dictionary1/tag_bank_3.json b/test/data/dictionaries/valid-dictionary1/tag_bank_3.json new file mode 100644 index 00000000..572221fe --- /dev/null +++ b/test/data/dictionaries/valid-dictionary1/tag_bank_3.json @@ -0,0 +1,4 @@ +[ + ["ptag1", "pcategory1", 0, "ptag1 notes", 0], + ["ptag2", "pcategory2", 0, "ptag2 notes", 0] +]
\ No newline at end of file diff --git a/test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json b/test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json index 78096502..26922394 100644 --- a/test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json +++ b/test/data/dictionaries/valid-dictionary1/term_meta_bank_1.json @@ -1,5 +1,39 @@ [ ["打", "freq", 1], ["打つ", "freq", 2], - ["打ち込む", "freq", 3] + ["打ち込む", "freq", 3], + [ + "打ち込む", + "pitch", + { + "reading": "うちこむ", + "pitches": [ + {"position": 0}, + {"position": 3} + ] + } + ], + [ + "打ち込む", + "pitch", + { + "reading": "ぶちこむ", + "pitches": [ + {"position": 0}, + {"position": 3} + ] + } + ], + [ + "お手前", + "pitch", + { + "reading": "おてまえ", + "pitches": [ + {"position": 2, "tags": ["ptag1"]}, + {"position": 2, "tags": ["ptag2"]}, + {"position": 0, "tags": ["ptag2"]} + ] + } + ] ]
\ No newline at end of file diff --git a/test/data/html/test-document2-frame1.html b/test/data/html/test-document2-frame1.html new file mode 100644 index 00000000..3b85cdc5 --- /dev/null +++ b/test/data/html/test-document2-frame1.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>Yomichan Tests</title> + <script src="test-document2-script.js"></script> + <style> +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + padding: 0; + margin: 0; + background-color: #f8f8f8; +} +a, a:visited { + color: #1080c0; + text-decoration: underline; +} +.content { + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + padding: 0.5em; + background-color: #f8f8f8; +} + </style> + </head> +<body><div class="content"> +<div> + ありがとう +</div> +<div> + <a href="#" id="fullscreen-link">Toggle fullscreen</a> + <script> +document.querySelector('#fullscreen-link').addEventListener('click', () => toggleFullscreen(document.body), false); + </script> +</div> +</div></body> +</html>
\ No newline at end of file diff --git a/test/data/html/test-document2-script.js b/test/data/html/test-document2-script.js new file mode 100644 index 00000000..bd5a570d --- /dev/null +++ b/test/data/html/test-document2-script.js @@ -0,0 +1,41 @@ +function requestFullscreen(element) { + if (element.requestFullscreen) { + element.requestFullscreen(); + } else if (element.mozRequestFullScreen) { + element.mozRequestFullScreen(); + } else if (element.webkitRequestFullscreen) { + element.webkitRequestFullscreen(); + } else if (element.msRequestFullscreen) { + element.msRequestFullscreen(); + } +} + +function exitFullscreen() { + if (document.exitFullscreen) { + document.exitFullscreen(); + } else if (document.mozCancelFullScreen) { + document.mozCancelFullScreen(); + } else if (document.webkitExitFullscreen) { + document.webkitExitFullscreen(); + } else if (document.msExitFullscreen) { + document.msExitFullscreen(); + } +} + +function getFullscreenElement() { + return ( + document.fullscreenElement || + document.msFullscreenElement || + document.mozFullScreenElement || + document.webkitFullscreenElement || + null + ); +} + +function toggleFullscreen(element) { + if (getFullscreenElement()) { + exitFullscreen(); + } else { + requestFullscreen(element); + } +} diff --git a/test/data/html/test-document2.html b/test/data/html/test-document2.html new file mode 100644 index 00000000..3a22a5bf --- /dev/null +++ b/test/data/html/test-document2.html @@ -0,0 +1,81 @@ +<!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width,initial-scale=1" /> + <title>Yomichan Manual Tests</title> + <link rel="icon" type="image/gif" href="data:image/gif;base64,R0lGODlhEAAQAKEBAAAAAP///////////yH5BAEKAAIALAAAAAAQABAAAAImFI6Zpt0B4YkS0TCpq07xbmEgcGVRUpLaI46ZG7ppalY0jDCwUAAAOw==" /> + <link rel="stylesheet" href="test-stylesheet.css" /> + <script src="test-document2-script.js"></script> + </head> +<body> + + <h1>Yomichan Manual Tests</h1> + <p class="description">Manual tests involving fullscreen elements, <iframe>s, and shadow DOMs.</p> + + <div class="test"> + <div class="description">Standard content.</div> + <div id="fullscreen-element1" style="width: 100%; height: 200px; border: 1px solid #d8d8d8; position: relative;"><div style="background-color: #f8f8f8; padding: 0.5em; position: absolute; left: 0; top: 0; bottom: 0; right: 0;"> + <div> + ありがとう + </div> + <div> + <a href="#" id="fullscreen-link1">Toggle fullscreen</a> + </div> + </div></div> + <script> +document.querySelector('#fullscreen-link1').addEventListener('click', () => toggleFullscreen(document.querySelector('#fullscreen-element1')), false); + </script> + </div> + + <div class="test"> + <div class="description">Content inside of a shadow DOM.</div> + <div id="shadow-content-container"></div> + <template id="shadow-content-container-content-template"> + <link rel="stylesheet" href="test-stylesheet.css" /> + <div id="fullscreen-element2" style="width: 100%; height: 200px; border: 1px solid #d8d8d8; position: relative;"><div style="background-color: #f8f8f8; padding: 0.5em; position: absolute; left: 0; top: 0; bottom: 0; right: 0;"> + <div> + ありがとう + </div> + <div> + <a href="#" id="fullscreen-link2">Toggle fullscreen</a> + </div> + </div></div> + </template> + <script> +(() => { + const shadowIframeContainer = document.querySelector('#shadow-content-container'); + const shadow = shadowIframeContainer.attachShadow({mode: 'closed'}); + const template = document.querySelector('#shadow-content-container-content-template').content; + const content = document.importNode(template, true); + const fullscreenElement = content.querySelector('#fullscreen-element2'); + content.querySelector('#fullscreen-link2').addEventListener('click', () => toggleFullscreen(fullscreenElement), false); + shadow.appendChild(content); +})(); + </script> + </div> + + <div class="test"> + <div class="description"><iframe> element.</div> + <iframe src="test-document2-frame1.html" allowfullscreen="true" style="width: 100%; height: 200px; border: 1px solid #d8d8d8;"></iframe> + </div> + + <div class="test"> + <div class="description"><iframe> element inside of a shadow DOM.</div> + <div id="shadow-iframe-container"></div> + <template id="shadow-iframe-container-content-template"> + <iframe src="test-document2-frame1.html" allowfullscreen="true" style="width: 100%; height: 200px; border: 1px solid #d8d8d8;"></iframe> + </template> + <script> +(() => { + const shadowIframeContainer = document.querySelector('#shadow-iframe-container'); + const shadow = shadowIframeContainer.attachShadow({mode: 'closed'}); + const template = document.querySelector('#shadow-iframe-container-content-template').content; + const content = document.importNode(template, true); + shadow.appendChild(content); +})(); + </script> + </div> + +</body> +</html>
\ No newline at end of file diff --git a/test/data/html/test-stylesheet.css b/test/data/html/test-stylesheet.css index ab25732e..f63d2481 100644 --- a/test/data/html/test-stylesheet.css +++ b/test/data/html/test-stylesheet.css @@ -7,6 +7,7 @@ body { margin: 0 auto; background-color: #f8f8f8; counter-reset: test-id; + overflow-y: scroll; } h1 { @@ -14,6 +15,19 @@ h1 { margin: 0.67em 0; } +p { + margin: 0.33em 0; +} + +h1+p { + margin-top: -0.67em; +} + +a, a:visited { + color: #1080c0; + text-decoration: underline; +} + .test { background-color: #ffffff; margin: 1em 0; @@ -30,3 +44,8 @@ h1 { border-bottom: 1px solid #d8d8d8; font-weight: bold; } + +.description { + color: #444444; + font-style: italic; +} diff --git a/test/test-database.js b/test/test-database.js index c3402b73..c4bfb793 100644 --- a/test/test-database.js +++ b/test/test-database.js @@ -235,8 +235,8 @@ async function testDatabase1() { true ); vm.assert.deepStrictEqual(counts, { - counts: [{kanji: 2, kanjiMeta: 2, terms: 32, termMeta: 3, tagMeta: 12}], - total: {kanji: 2, kanjiMeta: 2, terms: 32, termMeta: 3, tagMeta: 12} + counts: [{kanji: 2, kanjiMeta: 2, terms: 32, termMeta: 6, tagMeta: 14}], + total: {kanji: 2, kanjiMeta: 2, terms: 32, termMeta: 6, tagMeta: 14} }); // Test find* functions @@ -652,9 +652,10 @@ async function testFindTermMetaBulk1(database, titles) { } ], expectedResults: { - total: 1, + total: 3, modes: [ - ['freq', 1] + ['freq', 1], + ['pitch', 2] ] } }, diff --git a/test/test-japanese.js b/test/test-japanese.js index c5d220e7..ca65dde2 100644 --- a/test/test-japanese.js +++ b/test/test-japanese.js @@ -23,9 +23,11 @@ const vm = new VM(); vm.execute([ 'mixed/lib/wanakana.min.js', 'mixed/js/japanese.js', + 'bg/js/text-source-map.js', 'bg/js/japanese.js' ]); const jp = vm.get('jp'); +const TextSourceMap = vm.get('TextSourceMap'); function testIsCodePointKanji() { @@ -262,13 +264,13 @@ function testConvertHalfWidthKanaToFullWidth() { ]; for (const [string, expected, expectedSourceMapping] of data) { - const sourceMapping = new Array(string.length).fill(1); + const sourceMap = new TextSourceMap(string); const actual1 = jp.convertHalfWidthKanaToFullWidth(string, null); - const actual2 = jp.convertHalfWidthKanaToFullWidth(string, sourceMapping); + const actual2 = jp.convertHalfWidthKanaToFullWidth(string, sourceMap); assert.strictEqual(actual1, expected); assert.strictEqual(actual2, expected); - if (Array.isArray(expectedSourceMapping)) { - vm.assert.deepStrictEqual(sourceMapping, expectedSourceMapping); + if (typeof expectedSourceMapping !== 'undefined') { + assert.ok(sourceMap.equals(new TextSourceMap(string, expectedSourceMapping))); } } } @@ -285,13 +287,13 @@ function testConvertAlphabeticToKana() { ]; for (const [string, expected, expectedSourceMapping] of data) { - const sourceMapping = new Array(string.length).fill(1); + const sourceMap = new TextSourceMap(string); const actual1 = jp.convertAlphabeticToKana(string, null); - const actual2 = jp.convertAlphabeticToKana(string, sourceMapping); + const actual2 = jp.convertAlphabeticToKana(string, sourceMap); assert.strictEqual(actual1, expected); assert.strictEqual(actual2, expected); - if (Array.isArray(expectedSourceMapping)) { - vm.assert.deepStrictEqual(sourceMapping, expectedSourceMapping); + if (typeof expectedSourceMapping !== 'undefined') { + assert.ok(sourceMap.equals(new TextSourceMap(string, expectedSourceMapping))); } } } @@ -392,6 +394,59 @@ function testDistributeFuriganaInflected() { } } +function testIsMoraPitchHigh() { + const data = [ + [[0, 0], false], + [[1, 0], true], + [[2, 0], true], + [[3, 0], true], + + [[0, 1], true], + [[1, 1], false], + [[2, 1], false], + [[3, 1], false], + + [[0, 2], true], + [[1, 2], true], + [[2, 2], false], + [[3, 2], false], + + [[0, 3], true], + [[1, 3], true], + [[2, 3], true], + [[3, 3], false], + + [[0, 4], true], + [[1, 4], true], + [[2, 4], true], + [[3, 4], true] + ]; + + for (const [[moraIndex, pitchAccentPosition], expected] of data) { + const actual = jp.isMoraPitchHigh(moraIndex, pitchAccentPosition); + assert.strictEqual(actual, expected); + } +} + +function testGetKanaMorae() { + const data = [ + ['かこ', ['か', 'こ']], + ['かっこ', ['か', 'っ', 'こ']], + ['カコ', ['カ', 'コ']], + ['カッコ', ['カ', 'ッ', 'コ']], + ['コート', ['コ', 'ー', 'ト']], + ['ちゃんと', ['ちゃ', 'ん', 'と']], + ['とうきょう', ['と', 'う', 'きょ', 'う']], + ['ぎゅう', ['ぎゅ', 'う']], + ['ディスコ', ['ディ', 'ス', 'コ']] + ]; + + for (const [text, expected] of data) { + const actual = jp.getKanaMorae(text); + vm.assert.deepStrictEqual(actual, expected); + } +} + function main() { testIsCodePointKanji(); @@ -408,6 +463,8 @@ function main() { testConvertAlphabeticToKana(); testDistributeFurigana(); testDistributeFuriganaInflected(); + testIsMoraPitchHigh(); + testGetKanaMorae(); } diff --git a/test/test-text-source-map.js b/test/test-text-source-map.js new file mode 100644 index 00000000..25bd8fc2 --- /dev/null +++ b/test/test-text-source-map.js @@ -0,0 +1,234 @@ +/* + * Copyright (C) 2020 Alex Yatskov <alex@foosoft.net> + * Author: Alex Yatskov <alex@foosoft.net> + * + * 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 assert = require('assert'); +const {VM} = require('./yomichan-vm'); + +const vm = new VM(); +vm.execute(['bg/js/text-source-map.js']); +const TextSourceMap = vm.get('TextSourceMap'); + + +function testSource() { + const data = [ + ['source1'], + ['source2'], + ['source3'] + ]; + + for (const [source] of data) { + const sourceMap = new TextSourceMap(source); + assert.strictEqual(source, sourceMap.source); + } +} + +function testEquals() { + const data = [ + [['source1', null], ['source1', null], true], + [['source2', null], ['source2', null], true], + [['source3', null], ['source3', null], true], + + [['source1', [1, 1, 1, 1, 1, 1, 1]], ['source1', null], true], + [['source2', [1, 1, 1, 1, 1, 1, 1]], ['source2', null], true], + [['source3', [1, 1, 1, 1, 1, 1, 1]], ['source3', null], true], + + [['source1', null], ['source1', [1, 1, 1, 1, 1, 1, 1]], true], + [['source2', null], ['source2', [1, 1, 1, 1, 1, 1, 1]], true], + [['source3', null], ['source3', [1, 1, 1, 1, 1, 1, 1]], true], + + [['source1', [1, 1, 1, 1, 1, 1, 1]], ['source1', [1, 1, 1, 1, 1, 1, 1]], true], + [['source2', [1, 1, 1, 1, 1, 1, 1]], ['source2', [1, 1, 1, 1, 1, 1, 1]], true], + [['source3', [1, 1, 1, 1, 1, 1, 1]], ['source3', [1, 1, 1, 1, 1, 1, 1]], true], + + [['source1', [1, 2, 1, 3]], ['source1', [1, 2, 1, 3]], true], + [['source2', [1, 2, 1, 3]], ['source2', [1, 2, 1, 3]], true], + [['source3', [1, 2, 1, 3]], ['source3', [1, 2, 1, 3]], true], + + [['source1', [1, 3, 1, 2]], ['source1', [1, 2, 1, 3]], false], + [['source2', [1, 3, 1, 2]], ['source2', [1, 2, 1, 3]], false], + [['source3', [1, 3, 1, 2]], ['source3', [1, 2, 1, 3]], false], + + [['source1', [1, 1, 1, 1, 1, 1, 1]], ['source4', [1, 1, 1, 1, 1, 1, 1]], false], + [['source2', [1, 1, 1, 1, 1, 1, 1]], ['source5', [1, 1, 1, 1, 1, 1, 1]], false], + [['source3', [1, 1, 1, 1, 1, 1, 1]], ['source6', [1, 1, 1, 1, 1, 1, 1]], false] + ]; + + for (const [[source1, mapping1], [source2, mapping2], expectedEquals] of data) { + const sourceMap1 = new TextSourceMap(source1, mapping1); + const sourceMap2 = new TextSourceMap(source2, mapping2); + assert.ok(sourceMap1.equals(sourceMap1)); + assert.ok(sourceMap2.equals(sourceMap2)); + assert.strictEqual(sourceMap1.equals(sourceMap2), expectedEquals); + } +} + +function testGetSourceLength() { + const data = [ + [['source', [1, 1, 1, 1, 1, 1]], 1, 1], + [['source', [1, 1, 1, 1, 1, 1]], 2, 2], + [['source', [1, 1, 1, 1, 1, 1]], 3, 3], + [['source', [1, 1, 1, 1, 1, 1]], 4, 4], + [['source', [1, 1, 1, 1, 1, 1]], 5, 5], + [['source', [1, 1, 1, 1, 1, 1]], 6, 6], + + [['source', [2, 2, 2]], 1, 2], + [['source', [2, 2, 2]], 2, 4], + [['source', [2, 2, 2]], 3, 6], + + [['source', [3, 3]], 1, 3], + [['source', [3, 3]], 2, 6], + + [['source', [6, 6]], 1, 6] + ]; + + for (const [[source, mapping], finalLength, expectedValue] of data) { + const sourceMap = new TextSourceMap(source, mapping); + assert.strictEqual(sourceMap.getSourceLength(finalLength), expectedValue); + } +} + +function testCombineInsert() { + const data = [ + // No operations + [ + ['source', null], + ['source', [1, 1, 1, 1, 1, 1]], + [] + ], + + // Combine + [ + ['source', null], + ['source', [3, 1, 1, 1]], + [ + ['combine', 0, 2] + ] + ], + [ + ['source', null], + ['source', [1, 1, 1, 3]], + [ + ['combine', 3, 2] + ] + ], + [ + ['source', null], + ['source', [3, 3]], + [ + ['combine', 0, 2], + ['combine', 1, 2] + ] + ], + [ + ['source', null], + ['source', [3, 3]], + [ + ['combine', 3, 2], + ['combine', 0, 2] + ] + ], + + // Insert + [ + ['source', null], + ['source', [0, 1, 1, 1, 1, 1, 1]], + [ + ['insert', 0, 0] + ] + ], + [ + ['source', null], + ['source', [1, 1, 1, 1, 1, 1, 0]], + [ + ['insert', 6, 0] + ] + ], + [ + ['source', null], + ['source', [0, 1, 1, 1, 1, 1, 1, 0]], + [ + ['insert', 0, 0], + ['insert', 7, 0] + ] + ], + [ + ['source', null], + ['source', [0, 1, 1, 1, 1, 1, 1, 0]], + [ + ['insert', 6, 0], + ['insert', 0, 0] + ] + ], + + // Mixed + [ + ['source', null], + ['source', [3, 0, 3]], + [ + ['combine', 0, 2], + ['insert', 1, 0], + ['combine', 2, 2] + ] + ], + [ + ['source', null], + ['source', [3, 0, 3]], + [ + ['combine', 0, 2], + ['combine', 1, 2], + ['insert', 1, 0] + ] + ], + [ + ['source', null], + ['source', [3, 0, 3]], + [ + ['insert', 3, 0], + ['combine', 0, 2], + ['combine', 2, 2] + ] + ] + ]; + + for (const [[source, mapping], [expectedSource, expectedMapping], operations] of data) { + const sourceMap = new TextSourceMap(source, mapping); + const expectedSourceMap = new TextSourceMap(expectedSource, expectedMapping); + for (const [operation, ...args] of operations) { + switch (operation) { + case 'combine': + sourceMap.combine(...args); + break; + case 'insert': + sourceMap.insert(...args); + break; + } + } + assert.ok(sourceMap.equals(expectedSourceMap)); + } +} + + +function main() { + testSource(); + testEquals(); + testGetSourceLength(); + testCombineInsert(); +} + + +if (require.main === module) { main(); } |