diff options
Diffstat (limited to 'dom/tests/mochitest/general/test_bug1012662_common.js')
-rw-r--r-- | dom/tests/mochitest/general/test_bug1012662_common.js | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/dom/tests/mochitest/general/test_bug1012662_common.js b/dom/tests/mochitest/general/test_bug1012662_common.js new file mode 100644 index 000000000..0d1ba2963 --- /dev/null +++ b/dom/tests/mochitest/general/test_bug1012662_common.js @@ -0,0 +1,341 @@ +/** Test for Bug 1012662 **/ +// This test is called from both test_bug1012662_editor.html and test_bug1012662_noeditor.html +// This is to test that the code works both in the presence of a contentEditable node, and in the absense of one +var WATCH_TIMEOUT = 300; + +// Some global variables to make the debug messages easier to track down +var gTestN0 = 0, gTestN1 = 0, gTestN2 = 0; +function testLoc() { return " " + gTestN0 + " - " + gTestN1 + " - " + gTestN2; } + +// Listen for cut & copy events +var gCopyCount = 0, gCutCount = 0; +document.addEventListener('copy', function() { + gCopyCount++; +}); +document.addEventListener('cut', function() { + gCutCount++; +}); + + +// Helper methods +function selectNode(aSelector, aCb) { + var dn = document.querySelector(aSelector); + var range = document.createRange(); + range.selectNodeContents(dn); + window.getSelection().removeAllRanges(); + window.getSelection().addRange(range); + if (aCb) { + aCb(); + } +} + +function selectInputNode(aSelector, aCb) { + var dn = document.querySelector(aSelector); + synthesizeMouse(dn, 10, 10, {}); + SimpleTest.executeSoon(function() { + synthesizeKey("A", {accelKey: true}); + SimpleTest.executeSoon(aCb); + }); +} + +// Callback functions for attaching to the button +function execCut(aShouldSucceed) { + var cb = function(e) { + e.preventDefault(); + document.removeEventListener('keydown', cb); + + is(aShouldSucceed, document.execCommand('cut'), "Keydown caused cut invocation" + testLoc()); + }; + return cb; +} +function execCopy(aShouldSucceed) { + var cb = function(e) { + e.preventDefault(); + document.removeEventListener('keydown', cb); + + is(aShouldSucceed, document.execCommand('copy'), "Keydown caused copy invocation" + testLoc()); + }; + return cb; +} + +// The basic test set. Tries to cut/copy everything +function cutCopyAll(aDoCut, aDoCopy, aDone, aNegate, aClipOverride, aJustClipboardNegate) { + var execCommandAlwaysSucceed = !!(aClipOverride || aJustClipboardNegate); + + function waitForClipboard(aCond, aSetup, aNext, aNegateOne) { + if (aClipOverride) { + aCond = aClipOverride; + aNegateOne = false; + } + if (aNegate || aNegateOne || aJustClipboardNegate) { + SimpleTest.waitForClipboard(null, aSetup, aNext, aNext, "text/unicode", WATCH_TIMEOUT, true); + } else { + SimpleTest.waitForClipboard(aCond, aSetup, aNext, aNext); + } + } + + function validateCutCopy(aExpectedCut, aExpectedCopy) { + if (aNegate) { + aExpectedCut = aExpectedCopy = 0; + } // When we are negating - we always expect callbacks not to be run + + is(aExpectedCut, gCutCount, + (aExpectedCut > 0 ? "Expect cut callback to run" : "Expect cut callback not to run") + testLoc()); + is(aExpectedCopy, gCopyCount, + (aExpectedCopy > 0 ? "Expect copy callback to run" : "Expect copy callback not to run") + testLoc()); + gCutCount = gCopyCount = 0; + } + + function step(n) { + function nextStep() { step(n + 1); } + + document.querySelector('span').textContent = 'span text'; + document.querySelector('input[type=text]').value = 'text text'; + document.querySelector('input[type=password]').value = 'password text'; + document.querySelector('textarea').value = 'textarea text'; + + var contentEditableNode = document.querySelector('div[contentEditable=true]'); + if (contentEditableNode) { + contentEditableNode.textContent = 'contenteditable text'; + } + + gTestN2 = n; + switch (n) { + case 0: + // copy on readonly selection + selectNode('span'); + waitForClipboard("span text", function() { + aDoCopy(true); + }, nextStep); + return; + + case 1: + validateCutCopy(0, 1); + + // cut on readonly selection + selectNode('span'); + + waitForClipboard("span text", function() { + aDoCut(execCommandAlwaysSucceed); + }, nextStep, true); + return; + + case 2: + validateCutCopy(1, 0); + + // copy on textbox selection + selectInputNode('input[type=text]', nextStep); + return; + + case 3: + waitForClipboard("text text", function() { + selectInputNode('input[type=text]', function() { aDoCopy(true); }); + }, nextStep); + return; + + case 4: + validateCutCopy(0, 1); + + // cut on textbox selection + selectInputNode('input[type=text]', nextStep); + return; + + case 5: + waitForClipboard("text text", function() { + aDoCut(true); + }, nextStep); + return; + + case 6: + validateCutCopy(1, 0); + + // copy on password selection + selectInputNode('input[type=password]', nextStep); + return; + + case 7: + waitForClipboard(null, function() { + aDoCopy(execCommandAlwaysSucceed); + }, nextStep, true); + return; + + case 8: + validateCutCopy(0, 1); + + // cut on password selection + selectInputNode('input[type=password]', nextStep); + return; + + case 9: + waitForClipboard(null, function() { + aDoCut(execCommandAlwaysSucceed); + }, nextStep, true); + return; + + case 10: + validateCutCopy(1, 0); + + // copy on textarea selection + selectInputNode('textarea', nextStep); + return; + + case 11: + waitForClipboard("textarea text", function() { + aDoCopy(true); + }, nextStep); + return; + + case 12: + validateCutCopy(0, 1); + + // cut on password selection + selectInputNode('textarea', nextStep); + return; + + case 13: + waitForClipboard("textarea text", function() { + aDoCut(true); + }, nextStep); + return; + + case 14: + validateCutCopy(1, 0); + + // copy on no selection + document.querySelector('textarea').blur(); + + waitForClipboard(null, function() { + aDoCopy(true); + }, nextStep, true); + return; + + case 15: + validateCutCopy(0, 1); + + // cut on no selection + waitForClipboard(null, function() { + aDoCut(execCommandAlwaysSucceed); + }, nextStep, true); + return; + + case 16: + validateCutCopy(1, 0); + + if (!document.querySelector('div[contentEditable=true]')) { + // We're done! (no contentEditable node!) + step(-1); + return; + } + break; + + case 17: + // copy on contenteditable selection + waitForClipboard("contenteditable text", function() { + selectNode('div[contentEditable=true]', function() { + aDoCopy(true); + }); + }, nextStep); + return; + + case 18: + validateCutCopy(0, 1); + break; + + case 19: + // cut on contenteditable selection + waitForClipboard("contenteditable text", function() { + selectNode('div[contentEditable=true]', function() { + aDoCut(true); + }); + }, nextStep); + return; + + case 20: + validateCutCopy(1, 0); + break; + + default: + aDone(); + return; + } + + SimpleTest.executeSoon(function() { step(n + 1); }); + } + + step(0); +} + +function allMechanisms(aCb, aClipOverride, aNegateAll) { + function testStep(n) { + gTestN1 = n; + switch (n) { + case 0: + // Keyboard issued + cutCopyAll(function docut(aSucc) { + synthesizeKey("X", {accelKey: true}); + }, function docopy(aSucc) { + synthesizeKey("C", {accelKey: true}); + }, function done() { testStep(n + 1); }, false, aClipOverride, aNegateAll); + return; + + case 1: + // Button issued + cutCopyAll(function docut(aSucc) { + document.addEventListener('keydown', execCut(aSucc)); + synthesizeKey("Q", {}); + }, function docopy(aSucc) { + document.addEventListener('keydown', execCopy(aSucc)); + synthesizeKey("Q", {}); + }, function done() { testStep(n + 1); }, false, aClipOverride, aNegateAll); + return; + + case 2: + // Button issued + cutCopyAll(function doCut(aSucc) { + is(false, document.execCommand('cut'), "Can't directly execCommand not in a user callback"); + }, function doCopy(aSucc) { + is(false, document.execCommand('copy'), "Can't directly execCommand not in a user callback"); + }, function done() { testStep(n + 1); }, true, aClipOverride, aNegateAll); + return; + + default: + aCb(); + return; + } + + SimpleTest.executeSoon(function() { testStep(n + 1); }); + } + testStep(0); +} + +// Run the tests +SimpleTest.waitForExplicitFinish(); +SimpleTest.requestLongerTimeout(5); // On the emulator - this times out occasionally +SimpleTest.waitForFocus(function() { + function justCancel(aEvent) { + aEvent.preventDefault(); + } + + function override(aEvent) { + aEvent.clipboardData.setData('text/plain', 'overridden'); + aEvent.preventDefault(); + } + + allMechanisms(function() { + gTestN0 = 1; + document.addEventListener('cut', override); + document.addEventListener('copy', override); + + allMechanisms(function() { + gTestN0 = 2; + document.removeEventListener('cut', override); + document.removeEventListener('copy', override); + document.addEventListener('cut', justCancel); + document.addEventListener('copy', justCancel); + + allMechanisms(function() { + SimpleTest.finish(); + }, null, true); + }, 'overridden'); + }); +}); |