summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/general/test_bug1012662_common.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/tests/mochitest/general/test_bug1012662_common.js')
-rw-r--r--dom/tests/mochitest/general/test_bug1012662_common.js341
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');
+ });
+});