Add JavaScript tests.

Run "npm install", then "npm test".
This commit is contained in:
tim
2026-09-26 03:48:09 +02:00
parent ed959888b4
commit b7022ab486
6 changed files with 1304 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
// XxxEditor.parse() and XxxEditor.serialize(): the HTML that the editor keeps and writes
"use strict";
const test = require("node:test");
const assert = require("node:assert/strict");
const { load } = require("./helpers");
const window = load(["publish/editor.js"], "");
const { parse, serialize } = window.XxxEditor;
// The HTML that the editor writes for *html*
function clean(html) {
const holder = window.document.createElement("div");
holder.appendChild(parse(html));
return serialize(holder);
}
test("simple paragraphs stay the same", () => {
assert.equal(clean("<p>One</p>\n<p>Two <strong>bold</strong> <em>it</em> <u>u</u> x<sup>2</sup> H<sub>2</sub>O</p>"),
"<p>One</p>\n<p>Two <strong>bold</strong> <em>it</em> <u>u</u> x<sup>2</sup> H<sub>2</sub>O</p>");
});
test("b and i become strong and em", () => {
assert.equal(clean("<p><b>b</b> <i>i</i></p>"), "<p><strong>b</strong> <em>i</em></p>");
});
test("scripts, styles and frames are dropped with their contents", () => {
assert.equal(clean("<p>a<script>alert(1)</script>b</p><style>p{}</style><iframe src='x'></iframe>"), "<p>ab</p>");
});
test("event handlers and unknown attributes are dropped", () => {
assert.equal(clean('<p onclick="x()" class="c" id="i">a</p><img src="x" onerror="alert(1)">'), "<p>a</p>");
});
test("unknown tags keep their contents", () => {
assert.equal(clean("<p><font color='red'>red</font> <span>plain</span></p>"), "<p>red plain</p>");
});
test("headings become paragraphs", () => {
assert.equal(clean("<h2>Title</h2>"), "<p>Title</p>");
});
test("only safe links are kept", () => {
assert.equal(clean('<p><a href="https://example.org/?a=1&amp;b=2" title="T &quot;q&quot;">x</a></p>'),
'<p><a href="https://example.org/?a=1&amp;b=2" title="T &quot;q&quot;">x</a></p>');
assert.equal(clean('<p><a href="mailto:a@example.org">m</a> <a href="/about">r</a> <a href="#top">h</a></p>'),
'<p><a href="mailto:a@example.org">m</a> <a href="/about">r</a> <a href="#top">h</a></p>');
assert.equal(clean('<p><a href="javascript:alert(1)">x</a></p>'), "<p><a>x</a></p>");
assert.equal(clean('<p><a href=" JaVaScRiPt:alert(1)">x</a></p>'), "<p><a>x</a></p>");
assert.equal(clean('<p><a href="data:text/html,x">x</a></p>'), "<p><a>x</a></p>");
});
test("only alignment and indent styles are kept", () => {
assert.equal(clean('<p style="text-align: center; color: red">c</p>'), '<p style="text-align: center;">c</p>');
assert.equal(clean('<p style="padding-left: 30px">i</p>'), '<p style="padding-left: 30px;">i</p>');
assert.equal(clean('<p style="margin-left: expression(alert(1))">x</p>'), "<p>x</p>");
assert.equal(clean('<p><span style="color: red">x</span></p>'), "<p>x</p>");
assert.equal(clean('<p><span style="text-align: right">x</span></p>'), '<p><span style="text-align: right;">x</span></p>');
});
test("the align attribute is kept only with a real alignment", () => {
assert.equal(clean('<p align="center">c</p>'), '<p align="center">c</p>');
assert.equal(clean('<p align="evil">c</p>'), "<p>c</p>");
});
test("text is escaped", () => {
assert.equal(clean("<p>a &lt; b &amp; c &gt; d \"q\"</p>"), "<p>a &lt; b &amp; c &gt; d \"q\"</p>");
});
test("line breaks, rules and no-break spaces are written as TinyMCE wrote them", () => {
assert.equal(clean("<p>one<br>two</p><hr><p>a b</p>"), "<p>one<br />two</p>\n<hr />\n<p>a&nbsp;b</p>");
});
test("an empty paragraph is written as &nbsp;", () => {
assert.equal(clean("<p>a</p><p></p><p><br></p><p>b</p>"), "<p>a</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>\n<p>b</p>");
});
test("a trailing line break in a block is dropped", () => {
assert.equal(clean("<p>a<br></p>"), "<p>a</p>");
});
test("an editor with no words gives an empty story", () => {
assert.equal(clean(""), "");
assert.equal(clean("<p><br></p>"), "");
assert.equal(clean("<p>  </p><p>​</p>"), "");
assert.equal(clean("<hr>"), "<hr />");
});
test("blockquotes and lists put their blocks on new lines", () => {
assert.equal(clean("<blockquote><p>q</p></blockquote>"), "<blockquote>\n<p>q</p>\n</blockquote>");
assert.equal(clean("<ul><li>a</li><li>b</li></ul><ol><li>c</li></ol>"), "<ul>\n<li>a</li>\n<li>b</li>\n</ul>\n<ol>\n<li>c</li>\n</ol>");
});
test("whitespace between blocks is dropped", () => {
assert.equal(clean("<p>a</p>\n\n <p>b</p>"), "<p>a</p>\n<p>b</p>");
});
test("parse does not run anything", () => {
window.hacked = false;
parse('<img src="x" onerror="window.hacked = true"><script>window.hacked = true</script>');
assert.equal(window.hacked, false);
});