505 lines
11 KiB
JavaScript
505 lines
11 KiB
JavaScript
// This test is called from both test_clipboard_editor.html and test_clipboard_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 });
|
|
// Clear the user activation state which is set from synthesized mouse and
|
|
// key event.
|
|
SpecialPowers.wrap(document).clearUserGestureActivation();
|
|
SimpleTest.executeSoon(aCb);
|
|
});
|
|
}
|
|
|
|
// Callback functions for attaching to the button
|
|
function execCommand(aCommand, aShouldSucceed, aAsync = false) {
|
|
var cb = function(e) {
|
|
e.preventDefault();
|
|
document.removeEventListener("keydown", cb);
|
|
|
|
if (aAsync) {
|
|
setTimeout(() => {
|
|
is(
|
|
aShouldSucceed,
|
|
document.execCommand(aCommand),
|
|
"Keydown caused " + aCommand + " invocation" + testLoc()
|
|
);
|
|
}, 0);
|
|
} else {
|
|
is(
|
|
aShouldSucceed,
|
|
document.execCommand(aCommand),
|
|
"Keydown caused " + aCommand + " 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/plain",
|
|
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);
|
|
}
|
|
|
|
// Reset the user activation state before running next test.
|
|
SpecialPowers.wrap(document).clearUserGestureActivation();
|
|
|
|
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) {
|
|
/** Test for Bug 1012662 **/
|
|
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", execCommand("cut", aSucc));
|
|
sendString("Q");
|
|
},
|
|
function docopy(aSucc) {
|
|
document.addEventListener("keydown", execCommand("copy", aSucc));
|
|
sendString("Q");
|
|
},
|
|
function done() {
|
|
testStep(n + 1);
|
|
},
|
|
false,
|
|
aClipOverride,
|
|
aNegateAll
|
|
);
|
|
return;
|
|
|
|
case 2:
|
|
// Not triggered by user gesture
|
|
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;
|
|
|
|
/** Test for Bug 1597857 **/
|
|
case 3:
|
|
// Button issued async
|
|
cutCopyAll(
|
|
function docut(aSucc) {
|
|
document.addEventListener(
|
|
"keydown",
|
|
execCommand("cut", aSucc, true)
|
|
);
|
|
sendString("Q");
|
|
},
|
|
function docopy(aSucc) {
|
|
document.addEventListener(
|
|
"keydown",
|
|
execCommand("copy", aSucc, true)
|
|
);
|
|
sendString("Q");
|
|
},
|
|
function done() {
|
|
testStep(n + 1);
|
|
},
|
|
false,
|
|
aClipOverride,
|
|
aNegateAll
|
|
);
|
|
return;
|
|
|
|
default:
|
|
aCb();
|
|
}
|
|
}
|
|
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");
|
|
});
|
|
});
|