این پاسخ هوش مصنوعی است
"use strict"; const assert = require("node:assert/strict"); const fs = require("node:fs"); const path = require("node:path"); const { JSDOM } = require("jsdom"); const source = fs.readFileSync(path.join(__dirname, "../src/content.js"), "utf8"); function createExtensionDom(body, overrides = {}) { const settings = { enabled: true, fixDirection: true, useFont: true, fixInputs: true, disabledSites: [], ...overrides }; let onChanged; const dom = new JSDOM(`
${body}`, { url: "https://chat.example/", runScripts: "dangerously", pretendToBeVisual: true }); dom.window.requestIdleCallback = (callback) => callback({ didTimeout: false, timeRemaining: () => 50 }); dom.window.chrome = { runtime: { getURL: (file) => `chrome-extension://test/${file}`, lastError: null }, storage: { local: { get: (_defaults, callback) => callback(settings) }, onChanged: { addListener: (callback) => { onChanged = callback; } } } }; const script = dom.window.document.createElement("script"); script.textContent = source; dom.window.document.head.appendChild(script); return { dom, changeSettings(patch) { for (const [key, value] of Object.entries(patch)) settings[key] = value; const changes = Object.fromEntries(Object.entries(patch).map(([key, value]) => [key, { newValue: value }])); onChanged(changes, "local"); } }; } function element(body, id = "target", overrides) { const fixture = createExtensionDom(body, overrides); return { fixture, target: fixture.dom.window.document.getElementById(id) }; } const tests = []; function test(name, fn) { tests.push({ name, fn }); } function nextTurn() { return new Promise((resolve) => setTimeout(resolve, 0)); } test("real Persian text is corrected to RTL", () => { const { target } = element('این یک متن فارسی است
'); assert.equal(target.getAttribute("dir"), "rtl"); }); test("Arabic-only text is not treated as Persian", () => { const { target } = element('هذا نص عربي للاختبار
'); assert.equal(target.hasAttribute("dir"), false); assert.equal(target.hasAttribute("data-rtlx-font"), false); }); test("English-leading Persian text uses auto direction", () => { const { target } = element('The answer is متن فارسی برای آزمایش.
'); assert.equal(target.getAttribute("dir"), "auto"); assert.equal(target.hasAttribute("data-rtlx-rtl"), false); }); test("Latin digits inside Persian text remain byte-identical", () => { const text = "نسخه 1234567890 برای آزمایش"; const { target } = element(`${text}
`); assert.equal(target.textContent, text); }); test("a sensible explicit RTL direction is preserved without ownership markers", () => { const { target } = element('این متن از قبل راستچین است
'); assert.equal(target.getAttribute("dir"), "rtl"); assert.equal(target.hasAttribute("data-rtlx-setdir"), false); }); test("a sensible explicit auto direction is preserved without ownership markers", () => { const { target } = element('این متن جهت خودکار دارد
'); assert.equal(target.getAttribute("dir"), "auto"); assert.equal(target.hasAttribute("data-rtlx-setdir"), false); }); test("a clearly wrong explicit LTR direction is corrected reversibly", () => { const { target } = element('این متن فارسی راستبهچپ است
'); assert.equal(target.getAttribute("dir"), "rtl"); assert.equal(target.getAttribute("data-rtlx-dir"), "ltr"); }); test("an inline author font is never replaced", () => { const { target } = element('این متن فونت دارد
'); assert.equal(target.style.fontFamily, "Arial"); assert.equal(target.hasAttribute("data-rtlx-font"), false); }); test("an inherited author font is never replaced", () => { const { target } = element('این متن فونت ارثبری دارد
این متن فونت دارد
'); assert.equal(target.style.fontFamily, ""); assert.equal(target.hasAttribute("data-rtlx-font"), false); }); test("an inherited stylesheet font is never replaced", () => { const { target } = element('این پاسخ هوش مصنوعی است
این متن بدون فونت است
'); assert.match(target.style.fontFamily, /Vazirmatn/i); }); test("streamed Persian text is corrected and Latin digits are untouched", async () => { const { fixture, target } = element('Waiting
'); target.textContent = "پاسخ زنده 1234567890"; await nextTurn(); assert.equal(target.getAttribute("dir"), "rtl"); assert.equal(target.textContent, "پاسخ زنده 1234567890"); fixture.dom.window.close(); }); test("a streamed block that becomes English is restored", async () => { const { fixture, target } = element('پاسخ فارسی
'); assert.equal(target.getAttribute("dir"), "rtl"); target.textContent = "The final answer is English."; await nextTurn(); assert.equal(target.hasAttribute("dir"), false); assert.equal(target.hasAttribute("data-rtlx-rtl"), false); assert.equal(target.style.fontFamily, ""); fixture.dom.window.close(); }); test("disabling the extension restores owned direction and font", () => { const { fixture, target } = element('پاسخ فارسی
'); fixture.changeSettings({ enabled: false }); assert.equal(target.hasAttribute("dir"), false); assert.equal(target.style.fontFamily, ""); }); test("unstyled inputs receive Vazirmatn only after Persian is present", () => { const { fixture, target } = element(''); assert.equal(target.style.fontFamily, ""); target.value = "متن فارسی"; target.dispatchEvent(new fixture.dom.window.Event("input", { bubbles: true })); assert.match(target.style.fontFamily, /Vazirmatn/i); }); test("author-styled Persian inputs preserve their font", () => { const { target } = element(''); assert.equal(target.style.fontFamily, "Arial"); assert.equal(target.hasAttribute("data-rtlx-font"), false); }); test("input listeners do not reapply styling while the extension is disabled", () => { const { fixture, target } = element(''); fixture.changeSettings({ enabled: false }); target.value = "متن فارسی"; target.dispatchEvent(new fixture.dom.window.Event("input", { bubbles: true })); assert.equal(target.style.fontFamily, ""); assert.equal(target.hasAttribute("data-rtlx-font"), false); }); (async () => { let passed = 0; for (const { name, fn } of tests) { try { await fn(); passed += 1; console.log(`PASS ${name}`); } catch (error) { console.error(`FAIL ${name}`); console.error(error.message); } } console.log(`\n${passed}/${tests.length} passed`); process.exitCode = passed === tests.length ? 0 : 1; })();