Files
xxx/tests/js/editor-html.test.js
T
tim b7022ab486 Add JavaScript tests.
Run "npm install", then "npm test".
2026-09-26 03:48:09 +02:00

103 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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);
});