| <!doctype html> |
| <html> |
| <meta charset=utf-8> |
| <meta name="variant" content="?designMode"> |
| <meta name="variant" content="?body"> |
| <meta name="variant" content="?html"> |
| <meta name="variant" content="?div-in-body"> |
| <meta name="variant" content="?nothing"> |
| <title>Test editing outside of body element</title> |
| <script src=/resources/testharness.js></script> |
| <script src=/resources/testharnessreport.js></script> |
| <script src="/resources/testdriver.js"></script> |
| <script src="/resources/testdriver-vendor.js"></script> |
| <script src="/resources/testdriver-actions.js"></script> |
| <script src="../include/editor-test-utils.js"></script> |
| <script> |
| "use strict"; |
| |
| // This test creates an editable <div> element, append it to the <html>, |
| // i.e., after the <body>, and do something in it. |
| |
| const tests = [ |
| { |
| command: "insertText", |
| arg: "abc", |
| initial: "<div>[]<br></div>", |
| expected: ["<div>abc</div>", "<div>abc<br></div>"], |
| }, |
| { |
| command: "delete", |
| initial: "<div>abc[]</div>", |
| expected: ["<div>ab</div>", "<div>ab<br></div>"], |
| }, |
| { |
| command: "forwardDelete", |
| initial: "<div>[]abc</div>", |
| expected: ["<div>bc</div>", "<div>bc<br></div>"], |
| }, |
| { |
| command: "insertParagraph", |
| initial: "<div>ab[]c</div>", |
| expected: [ |
| "<div>ab</div><div>c</div>", |
| "<div>ab<br></div><div>c</div>", |
| "<div>ab</div><div>c<br></div>", |
| "<div>ab<br></div><div>c<br></div>", |
| ], |
| }, |
| { |
| command: "insertLineBreak", |
| initial: "<div>ab[]c</div>", |
| expected: ["<div>ab<br>c</div>", "<div>ab<br>c<br></div>"], |
| }, |
| { |
| command: "bold", |
| initial: "<div>a[b]c</div>", |
| expected: ["<div>a<b>b</b>c</div>", "<div>a<b>b</b>c<br></div>"], |
| }, |
| { |
| command: "italic", |
| initial: "<div>a[b]c</div>", |
| expected: ["<div>a<i>b</i>c</div>", "<div>a<i>b</i>c<br></div>"], |
| }, |
| { |
| command: "createLink", |
| arg: "another.html", |
| initial: "<div>a[b]c</div>", |
| expected: [ |
| "<div>a<a href=\"another.html\">b</a>c</div>", |
| "<div>a<a href=\"another.html\">b</a>c<br></div>", |
| ], |
| }, |
| { |
| command: "unlink", |
| initial: "<div>a[<a href=\"another.html\">b</a>]c</div>", |
| expected: ["<div>abc</div>", "<div>abc<br></div>"], |
| }, |
| { |
| command: "insertHTML", |
| arg: "<hr>", |
| initial: "<div>a[b]c</div>", |
| expected: [ |
| "<div>a<hr>c</div>", |
| "<div>a<br><hr>c</div>", |
| "<div>a<hr>c<br></div>", |
| "<div>a<br><hr>c<br></div>", |
| ], |
| }, |
| // TODO: Add more commands. |
| ]; |
| |
| let editingHost = () => { |
| switch (document.location.search) { |
| case "?designMode": |
| document.designMode = "on"; |
| return document.documentElement; |
| case "?body": |
| document.body.setAttribute("contenteditable", "true"); |
| return document.body; |
| case "?html": |
| document.documentElement.setAttribute("contenteditable", "true"); |
| return document.documentElement; |
| case "?div-in-body": |
| return document.querySelector("div[contenteditable]"); |
| case "?nothing": |
| return null; |
| } |
| }; |
| |
| let div; |
| |
| promise_test(async () => { |
| await new Promise(resolve => { |
| addEventListener( |
| "load", |
| () => { |
| assert_true(true, "load event is fired"); |
| resolve(); |
| }, |
| { once: true } |
| ); |
| }); |
| |
| div = document.createElement("div"); |
| if (editingHost != document.documentElement) { |
| div.setAttribute("contenteditable", "true"); |
| editingHost = div; |
| } |
| document.documentElement.appendChild(div); |
| assert_equals(document.documentElement.lastChild, div, |
| "The test target should be last child of the <html>"); |
| }, "Waiting for load event"); |
| |
| function addPromiseTest(testName, testFunc) { |
| promise_test(async () => { |
| editingHost.focus(); |
| await testFunc(new EditorTestUtils(div)); |
| }, testName); |
| } |
| |
| for (const test of tests) { |
| addPromiseTest( |
| `Test for execCommand("${test.command}", false, ${ |
| typeof test.arg == "string" ? `"${test.arg}"` : test.arg |
| }) in "${test.initial}"`, |
| async (utils) => { |
| utils.setupEditingHost(test.initial); |
| await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve))); |
| document.execCommand(test.command, false, test.arg); |
| if (Array.isArray(test.expected)) { |
| assert_in_array(div.innerHTML, test.expected, |
| "The editing result is different from expected one"); |
| } else { |
| assert_equals(div.innerHTML, test.expected, |
| "The editing result is different from expected one"); |
| } |
| } |
| ); |
| } |
| </script> |
| </head> |
| <body></body> |
| </html> |