exec-command-without-editable-element.tentative.html (25459B)
1 <!doctype html> 2 <meta charset=utf-8> 3 <title>Test that execCommand without editable element</title> 4 <script src=../include/implementation.js></script> 5 <script>var testsJsLibraryOnly = true</script> 6 <script src=../include/tests.js></script> 7 <script src=/resources/testharness.js></script> 8 <script src=/resources/testharnessreport.js></script> 9 <script> 10 "use strict"; 11 12 setup({explicit_done: true}); 13 14 // This test calls execCommand() without editable element in the document, 15 // but its parent or child document has editable element and it has focus. 16 // In most cases, execCommand() should do nothing and return false. However, 17 // "cut", "copy", "paste" and "selectall" commands should work without DOM tree 18 // modification for making web apps can implement their own editor without 19 // editable element. 20 async function runTests() { 21 let parentWindow = window; 22 let parentDocument = document; 23 let parentSelection = parentDocument.getSelection(); 24 let parentEditor = parentDocument.getElementById("editor"); 25 parentEditor.focus(); 26 let iframe = document.getElementsByTagName("iframe")[0]; 27 let childWindow = iframe.contentWindow; 28 let childDocument = iframe.contentDocument; 29 let childSelection = childDocument.getSelection(); 30 let childEditor = childDocument.getElementById("editor"); 31 childEditor.focus(); 32 33 // execCommand() in child document shouldn't affect to focused parent 34 // document. 35 await doTest(parentWindow, parentDocument, parentSelection, parentEditor, 36 childWindow, childDocument, childSelection, childEditor, false); 37 // execCommand() in parent document shouldn't affect to focused child 38 // document but "cut" and "copy" may affect the focused child document. 39 await doTest(childWindow, childDocument, childSelection, childEditor, 40 parentWindow, parentDocument, parentSelection, parentEditor, true); 41 42 done(); 43 } 44 45 async function doTest(aFocusWindow, aFocusDocument, aFocusSelection, aFocusEditor, 46 aExecWindow, aExecDocument, aExecSelection, aExecEditor, 47 aExecInParent) { 48 const kTests = [ 49 /** 50 * command: The command which you test. 51 * focusContent: Will be set to innerHTML of div#editor element in focused 52 * document. 53 * execContent: Will be set to innerHTML of div#editor element in the 54 * document whose execCommand() will be called. 55 * initFunc: [optional] If you need to do something before running the 56 * test, you can do it with a function. 57 * expectedFocusContent: Expected content and selection in div#editor in 58 * focused document after calling execCommand(). 59 * expectedExecContent: Expected content and selection in div#editor in 60 * the document whose execCommand() is called. 61 * event: The event which you need to check whether it's fired or not. 62 * expectedFiredInFocus: true if the event should be fired on the focused 63 * document node. 64 * expectedFiredInExec: true if the event should be fired on the document 65 * node whose execCommand() is called. 66 * expectedResult: Expected result of execCommand(). 67 */ 68 {command: "bold", value: "bold", 69 focusContent: "a[b]c", execContent: "a[b]c", 70 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 71 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 72 expectedResult: false, 73 }, 74 {command: "italic", value: null, 75 focusContent: "a[b]c", execContent: "a[b]c", 76 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 77 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 78 expectedResult: false, 79 }, 80 {command: "underline", value: null, 81 focusContent: "a[b]c", execContent: "a[b]c", 82 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 83 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 84 expectedResult: false, 85 }, 86 {command: "strikethrough", value: null, 87 focusContent: "a[b]c", execContent: "a[b]c", 88 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 89 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 90 expectedResult: false, 91 }, 92 {command: "subscript", value: null, 93 focusContent: "a[b]c", execContent: "a[b]c", 94 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 95 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 96 expectedResult: false, 97 }, 98 {command: "superscript", value: null, 99 focusContent: "a[b]c", execContent: "a[b]c", 100 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 101 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 102 expectedResult: false, 103 }, 104 // "cut", "copy" and "paste" command should cause firing corresponding 105 // events to make web apps be able to implement their own editor even 106 // if there is no editor and selection is collapsed. 107 {command: "cut", value: null, 108 focusContent: "a[b]c", execContent: "ab[]c", 109 expectedFocusContent: "a[b]c", expectedExecContent: "ab[]c", 110 event: "cut", expectedFiredInFocus: false, expectedFiredInExec: true, 111 expectedResult: false, 112 }, 113 {command: "cut", value: null, 114 focusContent: "a[b]c", execContent: "a[b]c", 115 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 116 event: "cut", expectedFiredInFocus: false, expectedFiredInExec: true, 117 expectedResult: false, 118 }, 119 {command: "copy", value: null, 120 focusContent: "a[b]c", execContent: "ab[]c", 121 expectedFocusContent: "a[b]c", expectedExecContent: "ab[]c", 122 event: "copy", expectedFiredInFocus: false, expectedFiredInExec: true, 123 expectedResult: false, 124 }, 125 {command: "copy", value: null, 126 focusContent: "a[b]c", execContent: "a[b]c", 127 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 128 event: "copy", expectedFiredInFocus: false, expectedFiredInExec: true, 129 expectedResult: false, 130 }, 131 {command: "paste", value: null, 132 focusContent: "a[b]c", execContent: "a[b]c", 133 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 134 initFunc: () => { aFocusDocument.execCommand("copy", false, "b"); }, 135 event: "paste", expectedFiredInFocus: false, expectedFiredInExec: true, 136 expectedResult: false, 137 }, 138 {command: "delete", value: null, 139 focusContent: "a[b]c", execContent: "a[b]c", 140 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 141 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 142 expectedResult: false, 143 }, 144 {command: "forwarddelete", value: null, 145 focusContent: "a[b]c", execContent: "a[b]c", 146 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 147 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 148 expectedResult: false, 149 }, 150 // "selectall" command should be available without editable content. 151 {command: "selectall", value: null, 152 focusContent: "a[b]c", execContent: "a[b]c", 153 expectedFocusContent: "a[b]c", expectedExecContent: undefined, 154 event: "selectionchange", expectedFiredInFocus: false, expectedFiredInExec: true, 155 expectedResult: true, 156 }, 157 {command: "undo", value: null, 158 focusContent: "a[]c", execContent: "a[b]c", 159 initFunc: () => { aFocusDocument.execCommand("insertText", false, "b"); }, 160 expectedFocusContent: "ab[]c", expectedExecContent: "a[b]c", 161 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 162 expectedResult: false, 163 }, 164 {command: "redo", value: null, 165 focusContent: "a[]c", execContent: "a[b]c", 166 initFunc: () => { 167 aFocusDocument.execCommand("insertText", false, "b"); 168 aFocusDocument.execCommand("undo", false, null); 169 }, 170 expectedFocusContent: "a[]c", expectedExecContent: "a[b]c", 171 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 172 expectedResult: false, 173 }, 174 {command: "indent", value: null, 175 focusContent: "a[b]c", execContent: "a[b]c", 176 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 177 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 178 expectedResult: false, 179 }, 180 {command: "outdent", value: null, 181 focusContent: "a[b]c", execContent: "a[b]c", 182 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 183 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 184 expectedResult: false, 185 }, 186 {command: "backcolor", value: "#000000", 187 focusContent: "a[b]c", execContent: "a[b]c", 188 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 189 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 190 expectedResult: false, 191 }, 192 {command: "forecolor", value: "#F0F0F0", 193 focusContent: "a[b]c", execContent: "a[b]c", 194 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 195 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 196 expectedResult: false, 197 }, 198 {command: "hilitecolor", value: "#FFFF00", 199 focusContent: "a[b]c", execContent: "a[b]c", 200 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 201 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 202 expectedResult: false, 203 }, 204 {command: "fontname", value: "DummyFont", 205 focusContent: "a[b]c", execContent: "a[b]c", 206 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 207 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 208 expectedResult: false, 209 }, 210 {command: "fontsize", value: "5", 211 focusContent: "a[b]c", execContent: "a[b]c", 212 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 213 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 214 expectedResult: false, 215 }, 216 {command: "increasefontsize", value: null, 217 focusContent: "a[b]c", execContent: "a[b]c", 218 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 219 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 220 expectedResult: false, 221 }, 222 {command: "decreasefontsize", value: null, 223 focusContent: "a[b]c", execContent: "a[b]c", 224 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 225 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 226 expectedResult: false, 227 }, 228 {command: "inserthorizontalrule", value: null, 229 focusContent: "a[]bc", execContent: "a[]bc", 230 expectedFocusContent: "a[]bc", expectedExecContent: "a[]bc", 231 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 232 expectedResult: false, 233 }, 234 {command: "createlink", value: "foo.html", 235 focusContent: "a[b]c", execContent: "a[b]c", 236 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 237 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 238 expectedResult: false, 239 }, 240 {command: "insertimage", value: "no-image.png", 241 focusContent: "a[b]c", execContent: "a[b]c", 242 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 243 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 244 expectedResult: false, 245 }, 246 {command: "inserthtml", value: "<b>inserted</b>", 247 focusContent: "a[b]c", execContent: "a[b]c", 248 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 249 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 250 expectedResult: false, 251 }, 252 {command: "inserttext", value: "**inserted**", 253 focusContent: "a[b]c", execContent: "a[b]c", 254 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 255 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 256 expectedResult: false, 257 }, 258 {command: "justifyleft", value: null, 259 focusContent: "a[b]c", execContent: "a[b]c", 260 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 261 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 262 expectedResult: false, 263 }, 264 {command: "justifyright", value: null, 265 focusContent: "a[b]c", execContent: "a[b]c", 266 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 267 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 268 expectedResult: false, 269 }, 270 {command: "justifycenter", value: null, 271 focusContent: "a[b]c", execContent: "a[b]c", 272 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 273 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 274 expectedResult: false, 275 }, 276 {command: "justifyfull", value: null, 277 focusContent: "a[b]c", execContent: "a[b]c", 278 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 279 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 280 expectedResult: false, 281 }, 282 {command: "removeformat", value: null, 283 focusContent: "<b>a[b]c</b>", execContent: "<b>a[b]c</b>", 284 expectedFocusContent: "<b>a[b]c</b>", expectedExecContent: "<b>a[b]c</b>", 285 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 286 expectedResult: false, 287 }, 288 {command: "unlink", value: null, 289 focusContent: "<a href=\"foo.html\">a[b]c</a>", execContent: "<a href=\"foo.html\">a[b]c</a>", 290 expectedFocusContent: "<a href=\"foo.html\">a[b]c</a>", expectedExecContent: "<a href=\"foo.html\">a[b]c</a>", 291 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 292 expectedResult: false, 293 }, 294 {command: "insertorderedlist", value: null, 295 focusContent: "a[b]c", execContent: "a[b]c", 296 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 297 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 298 expectedResult: false, 299 }, 300 {command: "insertunorderedlist", value: null, 301 focusContent: "a[b]c", execContent: "a[b]c", 302 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 303 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 304 expectedResult: false, 305 }, 306 {command: "insertparagraph", value: null, 307 focusContent: "a[b]c", execContent: "a[b]c", 308 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 309 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 310 expectedResult: false, 311 }, 312 {command: "insertlinebreak", value: null, 313 focusContent: "a[b]c", execContent: "a[b]c", 314 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 315 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 316 expectedResult: false, 317 }, 318 {command: "formatblock", value: "div", 319 focusContent: "a[b]c", execContent: "a[b]c", 320 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 321 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 322 expectedResult: false, 323 }, 324 {command: "heading", value: "h1", 325 focusContent: "a[b]c", execContent: "a[b]c", 326 expectedFocusContent: "a[b]c", expectedExecContent: "a[b]c", 327 event: "input", expectedFiredInFocus: false, expectedFiredInExec: false, 328 expectedResult: false, 329 }, 330 /** 331 * command: The command which you test. 332 * state: The state which is used with execCommand(). 333 * initState: The state which should be set with execCommand() first. 334 * focusContent: Will be set to innerHTML of div#editor element in focused 335 * document. 336 * execContent: Will be set to innerHTML of div#editor element in the 337 * document whose execCommand() will be called. 338 * initFunc: [optional] If you need to do something before running the 339 * test, you can do it with a function. 340 * expectedSetStateInFocus: Expected queryCommandState() result in focused 341 * document. 342 * expectedSetStateInExec: Expected queryCommandState() result in document 343 * whose execCommand() is called. 344 * expectedResult: Expected result of execCommand(). 345 */ 346 {command: "styleWithCSS", state: "true", initState: "false", 347 focusContent: "a[b]c", execContent: "a[b]c", 348 expectedSetStateInFocus: false, expectedSetStateInExec: false, 349 expectedResult: false, 350 }, 351 {command: "contentReadOnly", state: "true", initState: "false", 352 focusContent: "a[b]c", execContent: "a[b]c", 353 expectedSetStateInFocus: false, expectedSetStateInExec: false, 354 expectedResult: false, 355 }, 356 {command: "insertBrOnReturn", state: "true", initState: "false", 357 focusContent: "a[b]c", execContent: "a[b]c", 358 expectedSetStateInFocus: false, expectedSetStateInExec: false, 359 expectedResult: false, 360 }, 361 {command: "defaultParagraphSeparator", state: "div", initState: "p", 362 focusContent: "a[b]c", execContent: "a[b]c", 363 expectedSetStateInFocus: false, expectedSetStateInExec: false, 364 expectedResult: false, 365 }, 366 {command: "defaultParagraphSeparator", state: "p", initState: "div", 367 focusContent: "a[b]c", execContent: "a[b]c", 368 expectedSetStateInFocus: false, expectedSetStateInExec: false, 369 expectedResult: false, 370 }, 371 {command: "enableObjectResizing", state: "true", initState: "false", 372 focusContent: "a[b]c", execContent: "a[b]c", 373 expectedSetStateInFocus: false, expectedSetStateInExec: false, 374 expectedResult: false, 375 }, 376 {command: "enableInlineTableEditing", state: "true", initState: "false", 377 focusContent: "a[b]c", execContent: "a[b]c", 378 expectedSetStateInFocus: false, expectedSetStateInExec: false, 379 expectedResult: false, 380 }, 381 {command: "enableAbsolutePositionEditing", state: "true", initState: "false", 382 focusContent: "a[b]c", execContent: "a[b]c", 383 expectedSetStateInFocus: false, expectedSetStateInExec: false, 384 expectedResult: false, 385 }, 386 ]; 387 388 async function waitForCondition(aCheckFunc) { 389 let retry = 60; 390 while (retry--) { 391 if (aCheckFunc()) { 392 return; 393 } 394 await new Promise(resolve => requestAnimationFrame(resolve)); 395 } 396 } 397 398 for (const kTest of kTests) { 399 // Skip unsupported command since it's not purpose of this tests whether 400 // each command is supported on the browser. 401 if (!aExecDocument.queryCommandSupported(kTest.command)) { 402 continue; 403 } 404 aExecEditor.removeAttribute("contenteditable"); // Disable commands in the exec document. 405 let points = setupDiv(aFocusEditor, kTest.focusContent); 406 aFocusSelection.setBaseAndExtent(points[0], points[1], points[2], points[3]); 407 points = setupDiv(aExecEditor, kTest.execContent); 408 aExecSelection.setBaseAndExtent(points[0], points[1], points[2], points[3]); 409 aFocusWindow.focus(); 410 aFocusEditor.focus(); 411 if (kTest.initFunc) { 412 kTest.initFunc(); 413 } 414 if (kTest.state === undefined) { 415 let eventFiredOnFocusDocument = false; 416 function handlerOnFocusDocument() { 417 eventFiredOnFocusDocument = true; 418 } 419 aFocusDocument.addEventListener(kTest.event, handlerOnFocusDocument, {capture: true}); 420 let eventFiredOnExecDocument = false; 421 function handlerOnExecDocument() { 422 eventFiredOnExecDocument = true; 423 } 424 aExecDocument.addEventListener(kTest.event, handlerOnExecDocument, {capture: true}); 425 const kDescription = `${aExecInParent ? "Parent" : "Child"}Document.execCommand(${kTest.command}, false, ${kTest.value}) with ${kTest.execContent}`; 426 test(function () { 427 let ret = aExecDocument.execCommand(kTest.command, false, kTest.value); 428 assert_equals(ret, kTest.expectedResult, `execCommand should return ${kTest.expectedResult}`); 429 }, `${kDescription}: calling execCommand`); 430 if (kTest.event === "selectionchange") { 431 test(function () { 432 assert_false(eventFiredOnFocusDocument, 433 `"${kTest.event}" event should not be fired synchronously on focused document`); 434 assert_false(eventFiredOnExecDocument, 435 `"${kTest.event}" event should not be fired synchronously on executed document`); 436 }, `${kDescription}: checking unexpected synchronous event`); 437 await waitForCondition(() => eventFiredOnFocusDocument && eventFiredOnExecDocument); 438 // TODO: Whether select all changes selection in the focused document depends on the 439 // implementation of "Select All". 440 } else { 441 test(function () { 442 assert_equals(eventFiredOnFocusDocument, kTest.expectedFiredInFocus, 443 `"${kTest.event}" event should${kTest.expectedFiredInFocus ? "" : " not"} be fired`); 444 }, `${kDescription}: checking event on focused document`); 445 } 446 test(function () { 447 assert_equals(eventFiredOnExecDocument, kTest.expectedFiredInExec, 448 `"${kTest.event}" event should${kTest.expectedFiredInExec ? "" : " not"} be fired`); 449 }, `${kDescription}: checking event on executed document`); 450 test(function () { 451 if (aFocusSelection.rangeCount) { 452 addBrackets(aFocusSelection.getRangeAt(0)); 453 } 454 assert_equals(aFocusEditor.innerHTML, kTest.expectedFocusContent); 455 }, `${kDescription}: checking result content in focused document`); 456 test(function () { 457 if (kTest.command === "selectall") { 458 assert_true(aExecSelection.rangeCount > 0); 459 assert_equals( 460 aExecSelection.toString().replace(/[\r\n]/g, ""), 461 aExecDocument.body.textContent.replace(/[\r\n]/g, "") 462 ); 463 } else { 464 if (aExecSelection.rangeCount) { 465 addBrackets(aExecSelection.getRangeAt(0)); 466 } 467 assert_equals(aExecEditor.innerHTML, kTest.expectedExecContent); 468 } 469 }, `${kDescription}: checking result content in executed document`); 470 aFocusDocument.removeEventListener(kTest.event, handlerOnFocusDocument, {capture: true}); 471 aExecDocument.removeEventListener(kTest.event, handlerOnExecDocument, {capture: true}); 472 aExecEditor.setAttribute("contenteditable", ""); 473 } else { 474 const kDescription = `${aExecInParent ? "Parent" : "Child"}Document.execCommand(${kTest.command}, false, ${kTest.state})`; 475 test(function () { 476 let ret = aExecDocument.execCommand(kTest.command, false, kTest.initState); 477 assert_equals(ret, kTest.expectedResult, `execCommand should return ${kTest.expectedResult}`); 478 }, `${kDescription}: calling execCommand to initialize`); 479 let hasSetState = false; 480 test(function () { 481 hasSetState = aExecDocument.queryCommandState(kTest.command); 482 assert_equals(hasSetState, kTest.expectedSetStateInExec, `queryCommandState on executed document should return ${kTest.expectedSetState}`); 483 }, `${kDescription}: calling queryCommandState on executed document after initializing`); 484 test(function () { 485 let ret = aFocusDocument.queryCommandState(kTest.command); 486 assert_equals(ret, kTest.expectedSetStateInFocus, `queryCommandState on focus document should return ${kTest.expectedSetState}`); 487 }, `${kDescription}: calling queryCommandState on focus document after initializing`); 488 if (hasSetState) { 489 test(function () { 490 let ret = aExecDocument.queryCommandValue(kTest.command); 491 assert_equals(ret, kTest.initState, `queryCommandValue on executed document should return ${kTest.initState}`); 492 }, `${kDescription}: calling queryCommandValue on executed document after initializing`); 493 } 494 test(function () { 495 let ret = aExecDocument.execCommand(kTest.command, false, kTest.state); 496 assert_equals(ret, kTest.expectedResult, `execCommand should return ${kTest.expectedResult}`); 497 }, `${kDescription}: calling execCommand to set state`); 498 test(function () { 499 hasSetState = aExecDocument.queryCommandState(kTest.command); 500 assert_equals(hasSetState, kTest.expectedSetStateInExec, `queryCommandState should return ${kTest.expectedSetState}`); 501 }, `${kDescription}: calling queryCommandState on executed document`); 502 test(function () { 503 let ret = aFocusDocument.queryCommandState(kTest.command); 504 assert_equals(ret, kTest.expectedSetStateInFocus, `queryCommandState should return ${kTest.expectedSetState}`); 505 }, `${kDescription}: calling queryCommandState on focused document`); 506 if (hasSetState) { 507 test(function () { 508 let ret = aExecDocument.queryCommandValue(kTest.command); 509 assert_equals(ret, kTest.state, `queryCommandValue should return ${kTest.initState}`); 510 }, `${kDescription}: calling queryCommandValue on executed document`); 511 } 512 aExecEditor.setAttribute("contenteditable", ""); 513 test(function () { 514 let ret = aExecDocument.queryCommandState(kTest.command); 515 assert_equals(ret, kTest.expectedSetStateInExec, `queryCommandState should return ${kTest.expectedSetState}`); 516 }, `${kDescription}: calling queryCommandState on executed document after making executed document editable`); 517 } 518 } 519 } 520 521 window.addEventListener("load", runTests, {once: true}); 522 </script> 523 <body> 524 <div contenteditable id="editor">abc</div> 525 <iframe srcdoc="<div contenteditable id='editor'>def</div><span>ghi</span>"></iframe> 526 </body>