commit 942ef4cb8ece456c791c9757b5d762ed6495bced
parent ae635f4b7a9a57b14bd7d6c00f80f27534359426
Author: Edgar Chen <echen@mozilla.com>
Date: Wed, 7 Jan 2026 13:21:31 +0000
Bug 1953174 - Part 1: Add more mochitest tests for HTMLCopyEncoder; r=masayuki DONTBUILD
Differential Revision: https://phabricator.services.mozilla.com/D277505
Diffstat:
4 files changed, 379 insertions(+), 0 deletions(-)
diff --git a/dom/serializers/tests/mochitest/mochitest.toml b/dom/serializers/tests/mochitest/mochitest.toml
@@ -130,6 +130,12 @@ skip-if = [
["test_htmlcopyencoder.xhtml"]
+["test_htmlcopyencoder_common_ancestor.html"]
+
+["test_htmlcopyencoder_list.html"]
+
+["test_htmlcopyencoder_table.html"]
+
["test_plaintext_linebreak.html"]
["test_plaintext_linebreak_compress.html"]
diff --git a/dom/serializers/tests/mochitest/test_htmlcopyencoder_common_ancestor.html b/dom/serializers/tests/mochitest/test_htmlcopyencoder_common_ancestor.html
@@ -0,0 +1,155 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+-->
+<head>
+<title>Test on the html copy encoder for common ancestor</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1953174">Mozilla Bug 1953174</a>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<div id="container"></div>
+<script>
+
+/* global describe, it, beforeEach */
+
+const ELEMENTS = [
+ "address", "article", "aside", "bdi", "bdo", "blockquote", "data", "dd",
+ "del", "div", "dl", "dt", "figcaption", "figure", "footer", "header",
+ "hgroup", "ins", "kdb", "main", "mark", "nav", "p", "q", "rp", "rt", "ruby",
+ "samp", "section", "sub", "sup", "time"
+];
+
+const ALWAYS_INCLUDE_ELEMENTS = [
+ "a", "abbr", "b", "big", "cite", "code", "dfn", "em", "font", "h1", "h2",
+ "h3", "h4", "h5", "h6", "i", "pre", "s", "script", "small", "span", "strike",
+ "strong", "tt", "u", "var"
+];
+
+const de = SpecialPowers.Ci.nsIDocumentEncoder;
+const encoder = SpecialPowers.Cu.createHTMLCopyEncoder();
+function testSelectAndCopy(aNode, aInclude) {
+ const innerHTML = `<${aNode} id="target">First Second</${aNode}>`;
+ describe(innerHTML, () => {
+ beforeEach(() => {
+ info("Construct nodes");
+ const container = document.getElementById("container");
+ container.innerHTML = innerHTML;
+ });
+
+ it(`Select node`, async () => {
+ info("Select nodes");
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+
+ const target = document.getElementById("target");
+ const range = document.createRange();
+ range.selectNode(target);
+ selection.addRange(range);
+
+ info("Initialize encoder");
+ encoder.init(document, "text/html", 0);
+ encoder.setSelection(selection);
+
+ let htmlContext = { value: '' };
+ let htmlInfo = { value: '' };
+ is(encoder.encodeToStringWithContext(htmlContext, htmlInfo),
+ `<div id="container">${innerHTML}</div>`,
+ `Check serialized output`);
+ is(htmlContext.value, `<html><body></body></html>`,
+ `Check serialized context`);
+ is(htmlInfo.value, `0,0`, `Check serialized info`);
+ });
+
+ it(`Select node contents`, async () => {
+ info("Select nodes");
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+
+ const target = document.getElementById("target");
+ const range = document.createRange();
+ range.selectNodeContents(target);
+ selection.addRange(range);
+
+ info("Initialize encoder");
+ encoder.init(document, "text/html", 0);
+ encoder.setSelection(selection);
+
+ let htmlContext = { value: '' };
+ let htmlInfo = { value: '' };
+ is(encoder.encodeToStringWithContext(htmlContext, htmlInfo),
+ `<div id="container">${innerHTML}</div>`,
+ `Check serialized output`);
+ is(htmlContext.value, `<html><body></body></html>`,
+ `Check serialized context`);
+ is(htmlInfo.value, `0,0`, `Check serialized info`);
+ });
+
+ it(`Select whole text`, async () => {
+ info("Select text");
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+
+ const target = document.getElementById("target").firstChild;
+ const range = document.createRange();
+ range.setStart(target, 0);
+ range.setEnd(target, target.length);
+ selection.addRange(range);
+
+ info("Initialize encoder");
+ encoder.init(document, "text/html", 0);
+ encoder.setSelection(selection);
+
+ let htmlContext = { value: '' };
+ let htmlInfo = { value: '' };
+ is(encoder.encodeToStringWithContext(htmlContext, htmlInfo),
+ aInclude ? innerHTML : `First Second`,
+ `Check serialized output`);
+ is(htmlContext.value,
+ `<html><body><div id="container"><${aNode} id="target"></${aNode}></div></body></html>`,
+ `Check serialized context`);
+ is(htmlInfo.value, `0,0`, `Check serialized info`);
+ });
+
+ it(`Select partial text`, async () => {
+ info("Select text");
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+
+ const target = document.getElementById("target").firstChild;
+ const range = document.createRange();
+ range.setStart(target, 0);
+ range.setEnd(target, 5);
+ selection.addRange(range);
+
+ info("Initialize encoder");
+ encoder.init(document, "text/html", 0);
+ encoder.setSelection(selection);
+
+ let htmlContext = { value: '' };
+ let htmlInfo = { value: '' };
+ is(encoder.encodeToStringWithContext(htmlContext, htmlInfo),
+ aInclude ? `<${aNode} id="target">First</${aNode}>` : `First`,
+ `Check serialized output`);
+ is(htmlContext.value,
+ `<html><body><div id="container"><${aNode} id="target"></${aNode}></div></body></html>`,
+ `Check serialized context`);
+ is(htmlInfo.value, `0,0`, `Check serialized info`);
+ });
+ });
+}
+
+ELEMENTS.forEach(aNode => {
+ testSelectAndCopy(aNode, false);
+});
+
+ALWAYS_INCLUDE_ELEMENTS.forEach(aNode => {
+ testSelectAndCopy(aNode, true);
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/serializers/tests/mochitest/test_htmlcopyencoder_list.html b/dom/serializers/tests/mochitest/test_htmlcopyencoder_list.html
@@ -0,0 +1,97 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+-->
+<head>
+<title>Test on the html copy encoder for table selection</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1953174">Mozilla Bug 1953174</a>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<div id="container">
+ <ul>
+ <li>Item1</li>
+ <li><span>Item2</span></li>
+ <li><div>Item3</div></li>
+ <li><ol><li>SubItem1</li></ol></li>
+ <li><ol><li><span>SubItem2</span></li><li><div>SubItem3</div></li></ol></li>
+ <div><li>ItemInDiv1</li></div>
+ <span><li>ItemInSpan1</li></span>
+ <div><li><span>ItemInDiv1</span></li></div>
+ </ul>
+</div>
+<script>
+
+/* global describe, it, beforeEach */
+
+const TESTS = [
+ {
+ selector: `ul li`,
+ expectedResult: `<li>Item1</li>`,
+ expectedContext: `<html><body><div id="container"><ul></ul></div></body></html>`,
+ }, {
+ selector: `ul li span`,
+ expectedResult: `<li><span>Item2</span></li>`,
+ expectedContext: `<html><body><div id="container"><ul></ul></div></body></html>`,
+ }, {
+ selector: `ul li div`,
+ expectedResult: `<li><div>Item3</div></li>`,
+ expectedContext: `<html><body><div id="container"><ul></ul></div></body></html>`,
+ }, {
+ selector: `ul ol li`,
+ expectedResult: `<li><ol><li>SubItem1</li></ol></li>`,
+ expectedContext: `<html><body><div id="container"><ul></ul></div></body></html>`,
+ }, {
+ selector: `ul ol li span`,
+ expectedResult: `<li><span>SubItem2</span></li>`,
+ expectedContext: `<html><body><div id="container"><ul><li><ol></ol></li></ul></div></body></html>`,
+ }, {
+ selector: `ul ol li div`,
+ expectedResult: `<li><div>SubItem3</div></li>`,
+ expectedContext: `<html><body><div id="container"><ul><li><ol></ol></li></ul></div></body></html>`,
+ }, {
+ selector: `ul span li`,
+ expectedResult: `<span><li>ItemInSpan1</li></span>`,
+ expectedContext: `<html><body><div id="container"><ul></ul></div></body></html>`,
+ }, {
+ selector: `ul div span`,
+ expectedResult: `<div><li><span>ItemInDiv1</span></li></div>`,
+ expectedContext: `<html><body><div id="container"><ul></ul></div></body></html>`,
+ },
+];
+
+const de = SpecialPowers.Ci.nsIDocumentEncoder;
+const encoder = SpecialPowers.Cu.createHTMLCopyEncoder();
+
+TESTS.forEach(testCase => {
+ it(`Selector: ${testCase.selector}`, () => {
+ info("Select nodes");
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+
+ const range = document.createRange();
+ selection.addRange(range);
+
+ const target = document.querySelector(testCase.selector);
+ range.selectNode(target);
+
+ info("Initialize encoder");
+ encoder.init(document, "text/html", 0);
+ encoder.setSelection(selection);
+
+ info("Check result");
+ let htmlContext = { value: '' };
+ let htmlInfo = { value: '' };
+ is(encoder.encodeToStringWithContext(htmlContext, htmlInfo), testCase.expectedResult,
+ `Check serialized output`);
+ is(htmlContext.value, testCase.expectedContext, `Check serialized context`);
+ is(htmlInfo.value, `0,0`, `Check serialized info`);
+ });
+});
+
+</script>
+</body>
+</html>
diff --git a/dom/serializers/tests/mochitest/test_htmlcopyencoder_table.html b/dom/serializers/tests/mochitest/test_htmlcopyencoder_table.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+-->
+<head>
+<title>Test on the html copy encoder for table selection</title>
+<script src="/tests/SimpleTest/SimpleTest.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1953174">Mozilla Bug 1953174</a>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<div id="container">
+ <table>
+ <caption><span>Title1</span></caption>
+ <thead>
+ <tr><th>First</th><th><span>Second</span></th><th><div>Third</div></th></tr>
+ </thead>
+ <tbody>
+ <tr><th>Colume1</th><td>Data11</td><td><span>Data12</span></td></tr>
+ <tr><th><span>Colume2</span></th><td><div>Data21</div></td></tr>
+ <tr><th><div>Colume3</div></th></tr>
+ </tbody>
+ <tfoot>
+ <tr><th>Footer</th><td>DataFooter</td></tr>
+ </tfoot>
+ </table>
+</div>
+<script>
+
+/* global describe, it, beforeEach */
+
+const TESTS = [
+ {
+ selector: `caption`,
+ expectedResult: `<table><caption><span>Title1</span></caption></table>`,
+ expectedContext: `<html><body><div id="container"><table></table></div></body></html>`,
+ }, {
+ selector: `caption span`,
+ expectedResult: `<table><caption><span>Title1</span></caption></table>`,
+ expectedContext: `<html><body><div id="container"><table></table></div></body></html>`,
+ }, {
+ selector: `thead th`,
+ expectedResult: `<table><thead><tr><th>First</th></tr></thead></table>`,
+ expectedContext: `<html><body><div id="container"><table><thead></thead></table></div></body></html>`,
+ }, {
+ selector: `thead th span`,
+ expectedResult: `<span>Second</span>`,
+ expectedContext: `<html><body><div id="container"><table><thead><tr><th></th></tr></thead></table></div></body></html>`,
+ }, {
+ selector: `thead th div`,
+ expectedResult: `<div>Third</div>`,
+ expectedContext: `<html><body><div id="container"><table><thead><tr><th></th></tr></thead></table></div></body></html>`,
+ }, {
+ selector: `tbody th`,
+ expectedResult: `<table><tbody><tr><th>Colume1</th></tr></tbody></table>`,
+ expectedContext: `<html><body><div id="container"><table><tbody></tbody></table></div></body></html>`,
+ }, {
+ selector: `tbody th span`,
+ expectedResult: `<span>Colume2</span>`,
+ expectedContext: `<html><body><div id="container"><table><tbody><tr><th></th></tr></tbody></table></div></body></html>`,
+ }, {
+ selector: `tbody th div`,
+ expectedResult: `<div>Colume3</div>`,
+ expectedContext: `<html><body><div id="container"><table><tbody><tr><th></th></tr></tbody></table></div></body></html>`,
+ }, {
+ selector: `tbody td`,
+ expectedResult: `<table><tbody><tr><td>Data11</td></tr></tbody></table>`,
+ expectedContext: `<html><body><div id="container"><table><tbody></tbody></table></div></body></html>`,
+ }, {
+ selector: `tbody td span`,
+ expectedResult: `<span>Data12</span>`,
+ expectedContext: `<html><body><div id="container"><table><tbody><tr><td></td></tr></tbody></table></div></body></html>`,
+ }, {
+ selector: `tbody td div`,
+ expectedResult: `<div>Data21</div>`,
+ expectedContext: `<html><body><div id="container"><table><tbody><tr><td></td></tr></tbody></table></div></body></html>`,
+ }, {
+ selector: `tfoot th`,
+ expectedResult: `<table><tfoot><tr><th>Footer</th></tr></tfoot></table>`,
+ expectedContext: `<html><body><div id="container"><table><tfoot></tfoot></table></div></body></html>`,
+ }, {
+ selector: `tfoot td`,
+ expectedResult: `<table><tfoot><tr><td>DataFooter</td></tr></tfoot></table>`,
+ expectedContext: `<html><body><div id="container"><table><tfoot></tfoot></table></div></body></html>`,
+ }
+];
+
+const de = SpecialPowers.Ci.nsIDocumentEncoder;
+const encoder = SpecialPowers.Cu.createHTMLCopyEncoder();
+
+TESTS.forEach(testCase => {
+ it(`Selector: ${testCase.selector}`, () => {
+ info("Select nodes");
+ const selection = window.getSelection();
+ selection.removeAllRanges();
+
+ const range = document.createRange();
+ selection.addRange(range);
+
+ const target = document.querySelector(testCase.selector);
+ range.selectNode(target);
+
+ info("Initialize encoder");
+ encoder.init(document, "text/html", 0);
+ encoder.setSelection(selection);
+
+ info("Check result");
+ let htmlContext = { value: '' };
+ let htmlInfo = { value: '' };
+ is(encoder.encodeToStringWithContext(htmlContext, htmlInfo), testCase.expectedResult,
+ `Check serialized output`);
+ is(htmlContext.value, testCase.expectedContext, `Check serialized context`);
+ is(htmlInfo.value, `0,0`, `Check serialized info`);
+ });
+});
+
+</script>
+</body>
+</html>