| <!DOCTYPE html> |
| <html> |
| <body> |
| <p>This test ensures WebKit does not fire DOM mutation events while execCommand is in progress.</p> |
| <div id="test" contenteditable></div> |
| <pre> |
| <script> |
| |
| if (window.testRunner) |
| testRunner.dumpAsText(); |
| |
| var commands = [ |
| {name: 'BackColor', value: 'blue'}, |
| {name: 'CreateLink', value: 'about:blank'}, |
| {name: 'Delete', value: null}, |
| {name: 'FontName', value: 'Arial'}, |
| {name: 'FontSize', value: '5'}, |
| {name: 'FontSizeDelta', value: '5'}, |
| {name: 'ForeColor', value: 'blue'}, |
| {name: 'FormatBlock', value: 'pre'}, |
| {name: 'ForwardDelete', value: null}, |
| {name: 'HiliteColor', value: 'red'}, |
| {name: 'Indent', value: null}, |
| {name: 'InsertHTML', value: "<i>hello</i>"}, |
| {name: 'InsertHorizontalRule', value: null}, |
| {name: 'InsertImage', value: '../resources/abe.png'}, |
| {name: 'InsertLineBreak', value: null}, |
| {name: 'InsertNewlineInQuotedContent', value: null}, |
| {name: 'InsertOrderedList', value: null}, |
| {name: 'InsertParagraph', value: null}, |
| {name: 'InsertText', value: 'webkit'}, |
| {name: 'InsertUnorderedList', value: null}, |
| {name: 'Italic', value: null}, |
| {name: 'JustifyCenter', value: null}, |
| {name: 'JustifyFull', value: null}, |
| {name: 'JustifyLeft', value: null}, |
| {name: 'JustifyNone', value: null}, |
| {name: 'JustifyRight', value: null}, |
| {name: 'Outdent', value: null}, |
| {name: 'RemoveFormat', value: null}, |
| {name: 'Strikethrough', value: null}, |
| {name: 'Subscript', value: null}, |
| {name: 'Superscript', value: null}, |
| {name: 'Transpose', value: null, selector: function (test) { window.getSelection().setPosition(test.firstChild, 1); }}, |
| {name: 'Underline', value: null}, |
| {name: 'Unlink', value: null}, |
| ]; |
| |
| var events = { |
| 'DOMCharacterDataModified': false, |
| 'DOMSubtreeModified': false, |
| 'DOMNodeInserted': false, |
| 'DOMNodeRemoved': false, |
| 'DOMNodeRemovedFromDocument': false, |
| 'DOMNodeInsertedIntoDocument': true, // this event can never be observed. |
| 'focusin': false, |
| 'focusout': false, |
| }; |
| |
| var log = []; |
| var test = document.getElementById('test'); |
| |
| function addEventListeners(node) { |
| for (var e in events) { |
| node.addEventListener(e, function (event) { |
| log.push(test.innerHTML); |
| events[event.type] = true; |
| }, false); |
| } |
| } |
| |
| function isLogConsistent() { |
| for (var i= 1; i < log.length; i++) { |
| if (log[0] != log[i]) { |
| console.log(log); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| addEventListeners(test); |
| |
| var initial = 'hello, <input type="text"><blockquote align="right"><u><a href="about:blank">world</a></u></blockquote>'; |
| for (var i = 0; i < commands.length; i++) { |
| test.innerHTML = initial; |
| if (i) |
| document.write("\n"); |
| |
| if (test.innerHTML != initial) { |
| document.write("FAIL: initial innerHTML didn't match"); |
| continue; |
| } |
| |
| if (commands[i].selector) |
| commands[i].selector(test); |
| else { |
| document.getElementsByTagName('input')[0].focus(); |
| window.getSelection().selectAllChildren(test); |
| } |
| addEventListeners(test.childNodes[2]); |
| log = []; // clear log |
| document.execCommand(commands[i].name, false, commands[i].value); |
| |
| var quotedValue = commands[i].value ? "'" + commands[i].value.replace('<', '<') + "'" : null; |
| var action = "execCommand('" + commands[i].name + "', false, " + quotedValue + ")"; |
| |
| if (test.innerHTML == initial || log.length <= 0) |
| document.write('FAIL: ' + action + ' made no change to the DOM.'); |
| else if (!isLogConsistent()) |
| document.write('FAIL: ' + action + ' dispatched events before finalizing the DOM tree.'); |
| else |
| document.write('PASS: ' + action); |
| } |
| test.style.display = 'none'; |
| |
| document.write('\n'); |
| for (var e in events) { |
| if (!events[e]) |
| document.write('\nWARNING: ' + e + ' was never observed.'); |
| } |
| |
| document.write('\n\nDONE'); |
| |
| </script> |
| </pre> |
| </body> |
| </html> |