commit f5038bfe19515c12c73c8124dec668fc2e115b36
parent 3304c4ec94ebdc341612dbc8180a12136601414d
Author: Florian Zia <fzia@mozilla.com>
Date: Wed, 31 Dec 2025 21:26:45 +0000
Bug 2003063, Bug 2007032 - Part 5: Add initial chrome tests for multiline editor r=mak
Adds chrome tests for MultilineEditor basic functionality.
Differential Revision: https://phabricator.services.mozilla.com/D277183
Diffstat:
7 files changed, 379 insertions(+), 0 deletions(-)
diff --git a/browser/components/multilineeditor/moz.build b/browser/components/multilineeditor/moz.build
@@ -6,3 +6,5 @@ with Files("**"):
BUG_COMPONENT = ("Firefox", "Address Bar")
JAR_MANIFESTS += ["jar.mn"]
+
+TEST_DIRS += ["tests"]
diff --git a/browser/components/multilineeditor/tests/chrome/chrome.toml b/browser/components/multilineeditor/tests/chrome/chrome.toml
@@ -0,0 +1,12 @@
+[DEFAULT]
+support-files = [
+ "../../../../../toolkit/content/tests/widgets/lit-test-helpers.js",
+]
+
+["test_multiline_editor_input.html"]
+
+["test_multiline_editor_rendering.html"]
+
+["test_multiline_editor_selection.html"]
+
+["test_multiline_editor_value.html"]
diff --git a/browser/components/multilineeditor/tests/chrome/test_multiline_editor_input.html b/browser/components/multilineeditor/tests/chrome/test_multiline_editor_input.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Multiline editor input test</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link
+ rel="stylesheet"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ />
+ <link rel="stylesheet" href="chrome://global/skin/global.css" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <script src="../../../../../toolkit/content/tests/widgets/lit-test-helpers.js"></script>
+ <script
+ type="module"
+ src="chrome://browser/content/multilineeditor/multiline-editor.mjs"
+ ></script>
+ <script>
+ let html;
+ let testHelpers;
+
+ add_setup(async function setup() {
+ testHelpers = new LitTestHelpers();
+ ({ html } = await testHelpers.setupLit());
+ testHelpers.setupTests({
+ templateFn: (attributes) => html`<moz-multiline-editor ${attributes}></moz-multiline-editor>`,
+ });
+ });
+
+ add_task(async function testInputEvent() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ let inputEventFired = false;
+ const inputPromise = BrowserTestUtils.waitForEvent(editor, "input");
+ editor.addEventListener("input", () => {
+ inputEventFired = true;
+ });
+
+ editor.focus();
+ sendString("a");
+ await inputPromise;
+
+ ok(inputEventFired, "Input event was fired");
+ ok(editor.value.includes("a"), "Value updated after input");
+ });
+
+ add_task(async function testFocus() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.focus();
+ const shadowRoot = editor.shadowRoot;
+ const editorElement = shadowRoot.querySelector(".multiline-editor");
+ ok(editorElement, "Editor element exists in shadow DOM");
+
+ ok(shadowRoot.activeElement, "Shadow DOM has an active element after focus");
+ is(document.activeElement, editor, "Editor element is the active element in document");
+ });
+
+ add_task(async function testReadOnlyPreventsUserInput() {
+ const result = await testHelpers.renderTemplate(html`
+ <moz-multiline-editor readonly></moz-multiline-editor>
+ `);
+ const editor = result.querySelector("moz-multiline-editor");
+
+ is(editor.readOnly, true, "Editor is read-only");
+ is(editor.value, "", "Initial value is empty");
+
+ let inputEventFired = false;
+ editor.addEventListener("input", () => {
+ inputEventFired = true;
+ });
+
+ editor.focus();
+ sendString("test");
+
+ await new Promise(resolve => requestAnimationFrame(resolve));
+
+ ok(!inputEventFired, "Input event not fired");
+ is(editor.value, "", "Value remains empty");
+ });
+ </script>
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ </body>
+</html>
diff --git a/browser/components/multilineeditor/tests/chrome/test_multiline_editor_rendering.html b/browser/components/multilineeditor/tests/chrome/test_multiline_editor_rendering.html
@@ -0,0 +1,64 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Multiline editor rendering test</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link
+ rel="stylesheet"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ />
+ <link rel="stylesheet" href="chrome://global/skin/global.css" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <script src="../../../../../toolkit/content/tests/widgets/lit-test-helpers.js"></script>
+ <script
+ type="module"
+ src="chrome://browser/content/multilineeditor/multiline-editor.mjs"
+ ></script>
+ <script>
+ let html;
+ let testHelpers;
+
+ add_setup(async function setup() {
+ testHelpers = new LitTestHelpers();
+ ({ html } = await testHelpers.setupLit());
+ testHelpers.setupTests({
+ templateFn: (attributes) => html`<moz-multiline-editor ${attributes}></moz-multiline-editor>`,
+ });
+ });
+
+ add_task(async function testBasicRendering() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ ok(editor, "Editor element is rendered");
+ is(editor.value, "", "Editor has empty value");
+ is(editor.placeholder, "", "Editor has empty placeholder");
+ is(editor.readOnly, false, "Editor is not read-only by default");
+ });
+
+ add_task(async function testPlaceholder() {
+ const result = await testHelpers.renderTemplate(html`
+ <moz-multiline-editor placeholder="Enter text here"></moz-multiline-editor>
+ `);
+ const editor = result.querySelector("moz-multiline-editor");
+
+ is(editor.placeholder, "Enter text here", "Placeholder is set correctly");
+ });
+
+ add_task(async function testReadOnly() {
+ const result = await testHelpers.renderTemplate(html`
+ <moz-multiline-editor readonly></moz-multiline-editor>
+ `);
+ const editor = result.querySelector("moz-multiline-editor");
+
+ is(editor.readOnly, true, "Editor is read-only");
+ });
+ </script>
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ </body>
+</html>
diff --git a/browser/components/multilineeditor/tests/chrome/test_multiline_editor_selection.html b/browser/components/multilineeditor/tests/chrome/test_multiline_editor_selection.html
@@ -0,0 +1,113 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Multiline editor selection test</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link
+ rel="stylesheet"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ />
+ <link rel="stylesheet" href="chrome://global/skin/global.css" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <script src="../../../../../toolkit/content/tests/widgets/lit-test-helpers.js"></script>
+ <script
+ type="module"
+ src="chrome://browser/content/multilineeditor/multiline-editor.mjs"
+ ></script>
+ <script>
+ let html;
+ let testHelpers;
+
+ add_setup(async function setup() {
+ testHelpers = new LitTestHelpers();
+ ({ html } = await testHelpers.setupLit());
+ testHelpers.setupTests({
+ templateFn: (attributes) => html`<moz-multiline-editor ${attributes}></moz-multiline-editor>`,
+ });
+ });
+
+ add_task(async function testSelectionProperties() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Hello World";
+ is(editor.selectionStart, 11, "Selection starts at end of text after setting value");
+ is(editor.selectionEnd, 11, "Selection ends at end of text after setting value");
+ });
+
+ add_task(async function testSetSelectionRange() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Hello World";
+ editor.setSelectionRange(0, 5);
+ is(editor.selectionStart, 0, "Selection start is 0");
+ is(editor.selectionEnd, 5, "Selection end is 5");
+ });
+
+ add_task(async function testSelectAll() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ const text = "Hello World";
+ editor.value = text;
+ editor.select();
+ is(editor.selectionStart, 0, "Selection starts at beginning");
+ is(editor.selectionEnd, text.length, "Selection ends at text length");
+ });
+
+ add_task(async function testSelectionWithMultiline() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Line 1\nLine 2";
+ editor.setSelectionRange(0, 6);
+ is(editor.selectionStart, 0, "Selection start is correct");
+ is(editor.selectionEnd, 6, "Selection end is correct");
+ });
+
+ add_task(async function testSelectionStartProperty() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Hello World";
+ const initialEnd = editor.selectionEnd;
+ editor.selectionStart = 6;
+ is(editor.selectionStart, 6, "Selection start is set via property");
+ is(editor.selectionEnd, initialEnd, "Selection end remains unchanged");
+ });
+
+ add_task(async function testSelectionEndProperty() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Hello World";
+ editor.setSelectionRange(0, 5);
+ editor.selectionEnd = 11;
+ is(editor.selectionStart, 0, "Selection start remains at 0");
+ is(editor.selectionEnd, 11, "Selection end is set via property");
+ });
+
+ add_task(async function testSelectionchangeEvent() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ let selectionChangeEventFired = false;
+ editor.addEventListener("selectionchange", () => {
+ selectionChangeEventFired = true;
+ });
+
+ editor.value = "Hello World";
+ editor.setSelectionRange(0, 5);
+
+ ok(selectionChangeEventFired, "Selectionchange event was fired");
+ });
+ </script>
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ </body>
+</html>
diff --git a/browser/components/multilineeditor/tests/chrome/test_multiline_editor_value.html b/browser/components/multilineeditor/tests/chrome/test_multiline_editor_value.html
@@ -0,0 +1,90 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Multiline editor value test</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link
+ rel="stylesheet"
+ href="chrome://mochikit/content/tests/SimpleTest/test.css"
+ />
+ <link rel="stylesheet" href="chrome://global/skin/global.css" />
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <script src="../../../../../toolkit/content/tests/widgets/lit-test-helpers.js"></script>
+ <script
+ type="module"
+ src="chrome://browser/content/multilineeditor/multiline-editor.mjs"
+ ></script>
+ <script>
+ let html;
+ let testHelpers;
+
+ add_setup(async function setup() {
+ testHelpers = new LitTestHelpers();
+ ({ html } = await testHelpers.setupLit());
+ testHelpers.setupTests({
+ templateFn: (attributes) => html`<moz-multiline-editor ${attributes}></moz-multiline-editor>`,
+ });
+ });
+
+ add_task(async function testSingleWordValue() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Hello";
+ is(editor.value, "Hello", "Value with single word is set correctly");
+ });
+
+ add_task(async function testMultiWordValue() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Hello and goodbye world";
+ is(editor.value, "Hello and goodbye world", "Value with multiple words is set correctly");
+ });
+
+ add_task(async function testMultilineValue() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ const text = "Line 1\nLine 2\nLine 3";
+ editor.value = text;
+ is(editor.value, text, "Multiline text is set correctly");
+ });
+
+ add_task(async function testClearValue() {
+ const result = await testHelpers.renderTemplate();
+ const editor = result.querySelector("moz-multiline-editor");
+
+ editor.value = "Some text";
+ is(editor.value, "Some text", "Value is set");
+
+ editor.value = "";
+ is(editor.value, "", "Value is cleared");
+ });
+
+ add_task(async function testPendingValue() {
+ const editor = document.createElement("moz-multiline-editor");
+
+ // Set value before rendering completed
+ editor.value = "Pending text";
+ is(editor.value, "Pending text", "Value getter returns pending value before view creation");
+ ok(!editor.shadowRoot, "Shadow root doesn’t exist before connection");
+
+ const result = await testHelpers.renderTemplate();
+ result.appendChild(editor);
+
+ // Wait for editor to complete rendering
+ await editor.updateComplete;
+
+ ok(editor.shadowRoot, "Shadow root exists");
+ is(editor.value, "Pending text", "Pending value is applied");
+ });
+ </script>
+ </head>
+ <body>
+ <p id="display"></p>
+ <div id="content" style="display: none"></div>
+ <pre id="test"></pre>
+ </body>
+</html>
diff --git a/browser/components/multilineeditor/tests/moz.build b/browser/components/multilineeditor/tests/moz.build
@@ -0,0 +1,8 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+with Files("**"):
+ BUG_COMPONENT = ("Firefox", "Address Bar")
+
+MOCHITEST_CHROME_MANIFESTS += ["chrome/chrome.toml"]