summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/anki-note-builder.test.js2
-rw-r--r--test/document-test.js58
-rw-r--r--test/document-util.test.js86
-rw-r--r--test/dom-text-scanner.test.js49
4 files changed, 86 insertions, 109 deletions
diff --git a/test/anki-note-builder.test.js b/test/anki-note-builder.test.js
index 96dacab6..50b66f18 100644
--- a/test/anki-note-builder.test.js
+++ b/test/anki-note-builder.test.js
@@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+// @vitest-environment jsdom
+
import 'fake-indexeddb/auto';
import fs from 'fs';
import {fileURLToPath} from 'node:url';
diff --git a/test/document-test.js b/test/document-test.js
new file mode 100644
index 00000000..9d763816
--- /dev/null
+++ b/test/document-test.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2023 Yomitan Authors
+ * Copyright (C) 2020-2022 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/>.
+ */
+
+import fs from 'fs';
+import {test} from 'vitest';
+import {builtinEnvironments} from 'vitest/environments';
+
+/**
+ * @param {import('jsdom').DOMWindow} window
+ */
+function prepareWindow(window) {
+ const {document} = window;
+
+ // Define innerText setter as an alias for textContent setter
+ Object.defineProperty(window.HTMLDivElement.prototype, 'innerText', {
+ set(value) { this.textContent = value; }
+ });
+
+ // Placeholder for feature detection
+ document.caretRangeFromPoint = () => null;
+}
+
+/**
+ * @param {string} [htmlFilePath]
+ * @returns {import('vitest').TestAPI<{window: import('jsdom').DOMWindow}>}
+ */
+export function domTest(htmlFilePath) {
+ return test.extend({
+ // eslint-disable-next-line no-empty-pattern
+ window: async ({}, use) => {
+ const html = typeof htmlFilePath === 'string' ? fs.readFileSync(htmlFilePath, {encoding: 'utf8'}) : '<!DOCTYPE html>';
+ const env = builtinEnvironments.jsdom;
+ const {teardown} = await env.setup(global, {jsdom: {html}});
+ const window = /** @type {import('jsdom').DOMWindow} */ (/** @type {unknown} */ (global.window));
+ prepareWindow(window);
+ try {
+ await use(window);
+ } finally {
+ teardown(global);
+ }
+ }
+ });
+}
diff --git a/test/document-util.test.js b/test/document-util.test.js
index 8c6ab69b..10857df9 100644
--- a/test/document-util.test.js
+++ b/test/document-util.test.js
@@ -16,15 +16,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import fs from 'fs';
-import {JSDOM} from 'jsdom';
import {fileURLToPath} from 'node:url';
import path from 'path';
-import {expect, test} from 'vitest';
+import {describe, expect} from 'vitest';
import {DocumentUtil} from '../ext/js/dom/document-util.js';
import {DOMTextScanner} from '../ext/js/dom/dom-text-scanner.js';
import {TextSourceElement} from '../ext/js/dom/text-source-element.js';
import {TextSourceRange} from '../ext/js/dom/text-source-range.js';
+import {domTest} from './document-test.js';
const dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -69,27 +68,6 @@ class DOMRect {
/**
- * @param {string} fileName
- * @returns {JSDOM}
- */
-function createJSDOM(fileName) {
- const domSource = fs.readFileSync(fileName, {encoding: 'utf8'});
- const dom = new JSDOM(domSource);
- const document = dom.window.document;
- const window = dom.window;
-
- // Define innerText setter as an alias for textContent setter
- Object.defineProperty(window.HTMLDivElement.prototype, 'innerText', {
- set(value) { this.textContent = value; }
- });
-
- // Placeholder for feature detection
- document.caretRangeFromPoint = () => null;
-
- return dom;
-}
-
-/**
* @param {Element} element
* @param {string|undefined} selector
* @returns {?Element}
@@ -99,13 +77,13 @@ function querySelectorChildOrSelf(element, selector) {
}
/**
- * @param {JSDOM} dom
+ * @param {import('jsdom').DOMWindow} window
* @param {?Node} node
* @returns {?Text|Node}
*/
-function getChildTextNodeOrSelf(dom, node) {
+function getChildTextNodeOrSelf(window, node) {
if (node === null) { return null; }
- const Node = dom.window.Node;
+ const Node = window.Node;
const childNode = node.firstChild;
return (childNode !== null && childNode.nodeType === Node.TEXT_NODE ? childNode : node);
}
@@ -131,27 +109,10 @@ function findImposterElement(document) {
return document.querySelector('div[style*="2147483646"]>*');
}
-
-/** */
-async function testDocument1() {
- const dom = createJSDOM(path.join(dirname, 'data', 'html', 'test-document1.html'));
- const window = dom.window;
-
- try {
- await testDocumentTextScanningFunctions(dom);
- await testTextSourceRangeSeekFunctions(dom);
- } finally {
- window.close();
- }
-}
-
-/**
- * @param {JSDOM} dom
- */
-async function testDocumentTextScanningFunctions(dom) {
- const document = dom.window.document;
-
- test('DocumentTextScanningFunctions', () => {
+describe('DocumentUtil', () => {
+ const testDoc = domTest(path.join(dirname, 'data/html/test-document1.html'));
+ testDoc('Text scanning functions', ({window}) => {
+ const {document} = window;
for (const testElement of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('.test[data-test-type=scan]'))) {
// Get test parameters
const {
@@ -170,8 +131,8 @@ async function testDocumentTextScanningFunctions(dom) {
const elementFromPointValue = querySelectorChildOrSelf(testElement, elementFromPointSelector);
const caretRangeFromPointValue = querySelectorChildOrSelf(testElement, caretRangeFromPointSelector);
- const startNode = getChildTextNodeOrSelf(dom, querySelectorChildOrSelf(testElement, startNodeSelector));
- const endNode = getChildTextNodeOrSelf(dom, querySelectorChildOrSelf(testElement, endNodeSelector));
+ const startNode = getChildTextNodeOrSelf(window, querySelectorChildOrSelf(testElement, startNodeSelector));
+ const endNode = getChildTextNodeOrSelf(window, querySelectorChildOrSelf(testElement, endNodeSelector));
const startOffset2 = parseInt(/** @type {string} */ (startOffset), 10);
const endOffset2 = parseInt(/** @type {string} */ (endOffset), 10);
@@ -187,7 +148,7 @@ async function testDocumentTextScanningFunctions(dom) {
document.elementFromPoint = () => elementFromPointValue;
document.caretRangeFromPoint = (x, y) => {
- const imposter = getChildTextNodeOrSelf(dom, findImposterElement(document));
+ const imposter = getChildTextNodeOrSelf(window, findImposterElement(document));
expect(!!imposter).toStrictEqual(hasImposter === 'true');
const range = document.createRange();
@@ -264,15 +225,12 @@ async function testDocumentTextScanningFunctions(dom) {
source.cleanup();
}
});
-}
+});
-/**
- * @param {JSDOM} dom
- */
-async function testTextSourceRangeSeekFunctions(dom) {
- const document = dom.window.document;
-
- test('TextSourceRangeSeekFunctions', async () => {
+describe('DOMTextScanner', () => {
+ const testDoc = domTest(path.join(dirname, 'data/html/test-document1.html'));
+ testDoc('Seek functions', async ({window}) => {
+ const {document} = window;
for (const testElement of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('.test[data-test-type=text-source-range-seek]'))) {
// Get test parameters
const {
@@ -314,12 +272,4 @@ async function testTextSourceRangeSeekFunctions(dom) {
expect(content).toStrictEqual(expectedResultContent);
}
});
-}
-
-
-/** */
-async function main() {
- await testDocument1();
-}
-
-await main();
+});
diff --git a/test/dom-text-scanner.test.js b/test/dom-text-scanner.test.js
index f6a7410a..76e95a09 100644
--- a/test/dom-text-scanner.test.js
+++ b/test/dom-text-scanner.test.js
@@ -16,25 +16,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import fs from 'fs';
-import {JSDOM} from 'jsdom';
import {fileURLToPath} from 'node:url';
import path from 'path';
-import {expect, test} from 'vitest';
+import {describe, expect} from 'vitest';
import {DOMTextScanner} from '../ext/js/dom/dom-text-scanner.js';
+import {domTest} from './document-test.js';
const dirname = path.dirname(fileURLToPath(import.meta.url));
/**
- * @param {string} fileName
- * @returns {JSDOM}
- */
-function createJSDOM(fileName) {
- const domSource = fs.readFileSync(fileName, {encoding: 'utf8'});
- return new JSDOM(domSource);
-}
-
-/**
* @param {Element} element
* @param {string} selector
* @returns {?Node}
@@ -111,13 +101,12 @@ function createAbsoluteGetComputedStyle(window) {
}
-/**
- * @param {JSDOM} dom
- */
-async function testDomTextScanner(dom) {
- const document = dom.window.document;
+describe('DOMTextScanner', () => {
+ const testDoc = domTest(path.join(dirname, 'data/html/test-dom-text-scanner.html'));
+ testDoc('Seek tests', ({window}) => {
+ const {document} = window;
+ window.getComputedStyle = createAbsoluteGetComputedStyle(window);
- test('DomTextScanner', () => {
for (const testElement of /** @type {NodeListOf<HTMLElement>} */ (document.querySelectorAll('y-test'))) {
let testData = JSON.parse(/** @type {string} */ (testElement.dataset.testData));
if (!Array.isArray(testData)) {
@@ -185,26 +174,4 @@ async function testDomTextScanner(dom) {
}
}
});
-}
-
-
-/** */
-async function testDocument1() {
- const dom = createJSDOM(path.join(dirname, 'data', 'html', 'test-dom-text-scanner.html'));
- const window = dom.window;
- try {
- window.getComputedStyle = createAbsoluteGetComputedStyle(window);
-
- await testDomTextScanner(dom);
- } finally {
- window.close();
- }
-}
-
-
-/** */
-async function main() {
- await testDocument1();
-}
-
-await main();
+});