tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 1eaf3a5aecce35d1cf9f519c4302a34f892241ba
parent 315371a4b053a73704bda05c728402c960f7285f
Author: Edgar Chen <echen@mozilla.com>
Date:   Mon, 10 Nov 2025 20:21:45 +0000

Bug 1650720 - Part 1: Add plaintext serializer tests for linebreak; r=masayuki

Differential Revision: https://phabricator.services.mozilla.com/D270276

Diffstat:
Mdom/serializers/tests/mochitest/mochitest.toml | 4++++
Adom/serializers/tests/mochitest/test_plaintext_linebreak.html | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Adom/serializers/tests/mochitest/test_plaintext_linebreak_compress.html | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 231 insertions(+), 0 deletions(-)

diff --git a/dom/serializers/tests/mochitest/mochitest.toml b/dom/serializers/tests/mochitest/mochitest.toml @@ -123,3 +123,7 @@ skip-if = [ ["test_htmlcopyencoder.html"] ["test_htmlcopyencoder.xhtml"] + +["test_plaintext_linebreak.html"] + +["test_plaintext_linebreak_compress.html"] diff --git a/dom/serializers/tests/mochitest/test_plaintext_linebreak.html b/dom/serializers/tests/mochitest/test_plaintext_linebreak.html @@ -0,0 +1,130 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>Test line breaks for plaintext serializer</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="/tests/SimpleTest/EventUtils.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=1650720">Mozilla Bug 1650720</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="preformatted"></pre> +<div id="container"></div> +<script> + +const de = SpecialPowers.Ci.nsIDocumentEncoder; +const platformLineBreak = navigator.platform.indexOf("Win") == 0 ? "\r\n" : "\n"; +const CASES = [ + "\r", + "\n", + "\r\r", + "\r\n", + "\n\r", + "\n\n", + "\r\r\r", + "\r\r\n", + "\r\n\r", + "\r\n\n", + "\n\r\r", + "\n\r\n", + "\n\n\r", + "\n\n\n", + "\r \n", + "\n \r", +]; + +function convertLineBreaksForTestResult(aText) { + return aText.replace(/\r?\n|\r(?!\n)/g, platformLineBreak); +} + +function selectAndEncode(aElement) { + // Select the element. + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.selectAllChildren(aElement); + + const encoder = SpecialPowers.Cu.createHTMLCopyEncoder(); + encoder.init(document, "text/plain", de.OutputSelectionOnly); + encoder.setSelection(selection); + return encoder.encodeToString(); +} + +CASES.forEach((lineBreaks) => { + const text = `${lineBreaks}First${lineBreaks}Second${lineBreaks}`; + + add_task(async function test_pre_text() { + info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); + + const pre = document.getElementById("preformatted"); + pre.textContent = text; + + is(selectAndEncode(pre), text.replace(/\r|\n/g, platformLineBreak), + `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); + }); + + add_task(async function test_pre_img_alt() { + info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); + + const pre = document.getElementById("preformatted"); + const img = document.createElement("img"); + img.alt = text; + pre.replaceChildren(img); + + is(selectAndEncode(pre), convertLineBreaksForTestResult(text), + `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); + }); + + add_task(async function test_pre_img_title() { + info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); + + const pre = document.getElementById("preformatted"); + const img = document.createElement("img"); + img.title = text; + pre.replaceChildren(img); + + is(selectAndEncode(pre), ` [${convertLineBreaksForTestResult(text)}] `, + `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); + }); + + add_task(async function test_div_text() { + info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); + + const div = document.getElementById("container"); + div.textContent = text; + + is(selectAndEncode(div), ` First Second `, + `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); + }); + + add_task(async function test_div_img_alt() { + info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); + + const div = document.getElementById("container"); + const img = document.createElement("img"); + img.alt = text; + div.replaceChildren(img); + + // Our plain text serializer keep the first CR/LF. + is(selectAndEncode(div), `${lineBreaks[0]}First Second `, + `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); + }); + + add_task(async function test_div_img_title() { + info(`Testing line breaks: ${JSON.stringify(lineBreaks)}`); + + const div = document.getElementById("container"); + const img = document.createElement("img"); + img.title = text; + div.replaceChildren(img); + + is(selectAndEncode(div), ` [ First Second ] `, + `Encoded data for line breaks: ${JSON.stringify(lineBreaks)}`); + }); +}); + +</script> +</body> +</html> diff --git a/dom/serializers/tests/mochitest/test_plaintext_linebreak_compress.html b/dom/serializers/tests/mochitest/test_plaintext_linebreak_compress.html @@ -0,0 +1,97 @@ +<!DOCTYPE HTML> +<html> +<head> +<title>Test line breaks for plaintext serializer</title> +<script src="/tests/SimpleTest/SimpleTest.js"></script> +<script src="/tests/SimpleTest/EventUtils.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=1650720">Mozilla Bug 1650720</a> +<p id="display"></p> +<div id="content" style="display: none"> +</div> +<pre id="preformatted"></pre> +<div id="container"></div> +<script> + +const de = SpecialPowers.Ci.nsIDocumentEncoder; +const platformLineBreak = navigator.platform.indexOf("Win") == 0 ? "\r\n" : "\n"; +// XXX: I'm not sure if the line break compression behavior entirely makes sense, +// but this is what we have for now. +const TESTS = [ + {innerHTMLs: [`<pre>First <div>Second </div></pre><h3>Third</h3>`, + `<pre>First <div>Second </div></pre>\n<h3>Third</h3>`, + `<pre>First <div>Second </div></pre>\n\n<h3>Third</h3>`, + `<pre>First <div>Second </div></pre>\n\n\n<h3>Third</h3>`, + `<pre>First <div>Second </div></pre>\n\n\n\n<h3>Third</h3>`, + `<pre>First <div>Second </div>\n</pre><h3>Third</h3>`, + `<pre>First <div>Second </div>\n</pre>\n<h3>Third</h3>`, + `<pre>First <div>Second </div>\n</pre>\n\n<h3>Third</h3>`, + `<pre>First <div>Second </div>\n</pre>\n\n\n<h3>Third</h3>`, + `<pre>First <div>Second </div>\n</pre>\n\n\n\n<h3>Third</h3>`, + `<pre>First \n<div>Second </div></pre><h3>Third</h3>`], + expectedResult: `First ${platformLineBreak}Second ${platformLineBreak}${platformLineBreak}Third`}, + {innerHTMLs: [`<pre>First <pre>Second </pre></pre>Third`, + `<pre>First <pre>Second </pre></pre>\nThird`, + `<pre>First <pre>Second </pre></pre>\n\nThird`, + `<pre>First <pre>Second </pre></pre>\n\n\nThird`, + `<pre>First <pre>Second </pre></pre>\n\n\n\nThird`, + `<pre>First \n<pre>Second </pre></pre>Third`, + `<pre>First \n<pre>Second </pre></pre>\nThird`, + // XXX: Not sure below two cases should have another line break + // before the "Second". However, <pre> might have some special + // rules against normal elements with white-space:pre. + `<pre>First \n\n<pre>Second </pre></pre>Third`, + `<pre>First \n\n<pre>Second </pre></pre>\nThird`], + expectedResult: `First ${platformLineBreak}${platformLineBreak}Second ${platformLineBreak}${platformLineBreak}Third`}, + {innerHTMLs: [`<pre>First </pre><pre>Second</pre>`, + `<pre>First </pre>\n<pre>Second</pre>`, + `<pre>First </pre>\n\n<pre>Second</pre>`, + `<pre>First </pre>\n\n\n<pre>Second</pre>`, + `<pre>First </pre>\n\n\n\n<pre>Second</pre>`, + `<pre>First \n</pre><pre>Second</pre>`, + `<pre>First \n</pre>\n<pre>Second</pre>`, + `<pre>First \n</pre>\n\n<pre>Second</pre>`, + `<pre>First \n</pre>\n\n\n<pre>Second</pre>`, + `<pre>First \n</pre>\n\n\n\n<pre>Second</pre>`, + // XXX: Not sure below five cases should have another line break + // before the "Second". However, <pre> might have some special + // rules against normal elements with white-space:pre. + `<pre>First \n\n</pre><pre>Second</pre>`, + `<pre>First \n\n</pre>\n<pre>Second</pre>`, + `<pre>First \n\n</pre>\n\n<pre>Second</pre>`, + `<pre>First \n\n</pre>\n\n\n<pre>Second</pre>`, + `<pre>First \n\n</pre>\n\n\n\n<pre>Second</pre>`], + expectedResult: `First ${platformLineBreak}${platformLineBreak}Second`}, +]; + +function selectAndEncode(aElement) { + // Select the element. + const selection = window.getSelection(); + selection.removeAllRanges(); + selection.selectAllChildren(aElement); + + const encoder = SpecialPowers.Cu.createHTMLCopyEncoder(); + encoder.init(document, "text/plain", de.OutputSelectionOnly); + encoder.setSelection(selection); + return encoder.encodeToString(); +} + +TESTS.forEach((test) => { + test.innerHTMLs.forEach((innerHTML) => { + add_task(async function test_line_break_compress() { + info(`Testing ${JSON.stringify(innerHTML)}`); + + const div = document.getElementById("container"); + div.innerHTML = innerHTML; + + is(selectAndEncode(div), test.expectedResult, + `Encoded data for ${JSON.stringify(innerHTML)}`); + }); + }); +}); + +</script> +</body> +</html>