| products/Sources/formale Sprachen/C/Firefox/editor/libeditor/tests/test_middle_click_paste.html |
 |
<!DOCTYPE html>
<html>
<head>
<title>Test for paste with middle button click</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none;">
</div>
<div id="container"></div>
<textarea id="toCopyPlaintext" style="display: none;"></textarea>
<iframe id="toCopyHTMLContent" srcdoc="" style="display: none;"></iframe>
<pre id="test">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
// TODO: This file should test complicated cases too.
// E.g., pasting into existing content, e.g., pasting invalid child
// element for the parent elements at insertion point.
async function copyPlaintext(aText) {
return new Promise(resolve => {
SimpleTest.waitForClipboard(aText,
() => {
let element = document.getElementById("toCopyPlaintext");
element.style.display = "block";
element.focus();
element.value = aText;
synthesizeKey("a", {accelKey: true});
synthesizeKey("c", {accelKey: true});
},
() => {
ok(true, `Succeeded to copy "${aText}" to clipboard`);
let element = document.getElementById("toCopyPlaintext");
element.style.display = "none";
resolve();
},
() => {
ok(false, `Failed to copy "${aText}" to clipboard`);
SimpleTest.finish();
});
});
}
async function copyHTMLContent(aInnerHTML) {
let iframe = document.getElementById("toCopyHTMLContent");
iframe.style.display = "block";
iframe.contentDocument.body.scrollTop;
iframe.contentDocument.body.innerHTML = aInnerHTML;
iframe.contentWindow.focus();
iframe.contentWindow.getSelection().selectAllChildren(iframe.contentDocument.body);
return new Promise(resolve => {
SimpleTest.waitForClipboard(
() => { return true; },
() => {
synthesizeKey("c", {accelKey: true}, iframe.contentWindow);
},
() => {
ok(true, `Succeeded to copy "${aInnerHTML}" to clipboard as HTML`);
iframe.style.display = "none";
resolve();
},
() => {
ok(false, `Failed to copy "${aInnerHTML}" to clipboard`);
SimpleTest.finish();
},
"text/html");
});
}
function checkInputEvent(aEvent, aInputType, aData, aDataTransfer, aTargetRanges, aDescription) {
ok(aEvent instanceof InputEvent,
`"${aEvent.type}" event should be dispatched with InputEvent interface ${aDescription}`);
is(aEvent.cancelable, aEvent.type === "beforeinput",
`"${aEvent.type}" event should ${aEvent.type === "beforeinput" ? "be" : "be never"} cancelable ${aDescription}`);
is(aEvent.bubbles, true,
`"${aEvent.type}" event should always bubble ${aDescription}`);
is(aEvent.inputType, aInputType,
`inputType of "${aEvent.type}" event should be "${aInputType}" ${aDescription}`);
is(aEvent.data, aData,
`data of "${aEvent.type}" event should be ${aData} ${aDescription}`);
if (aDataTransfer === null) {
is(aEvent.dataTransfer, null,
`dataTransfer of "${aEvent.type}" event should be null ${aDescription}`);
} else {
for (let dataTransfer of aDataTransfer) {
is(aEvent.dataTransfer.getData(dataTransfer.type), dataTransfer.data,
`dataTransfer of "${aEvent.type}" should have "${dataTransfer.data}" whose type is "${dataTransfer.type}" ${aDescription}`);
}
}
let targetRanges = aEvent.getTargetRanges();
if (aTargetRanges.length === 0) {
is(targetRanges.length, 0,
`getTargetRange() of "${aEvent.type}" event should return empty array: ${aDescription}`);
} else {
is(targetRanges.length, aTargetRanges.length,
`getTargetRange() of "${aEvent.type}" event should return static range array: ${aDescription}`);
if (targetRanges.length == aTargetRanges.length) {
for (let i = 0; i < targetRanges.length; i++) {
is(targetRanges[i].startContainer, aTargetRanges[i].startContainer,
`startContainer of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`);
is(targetRanges[i].startOffset, aTargetRanges[i].startOffset,
`startOffset of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`);
is(targetRanges[i].endContainer, aTargetRanges[i].endContainer,
`endContainer of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`);
is(targetRanges[i].endOffset, aTargetRanges[i].endOffset,
`endOffset of getTargetRanges()[${i}] of "${aEvent.type}" event does not match: ${aDescription}`);
}
}
}
}
async function doTextareaTests(aTextarea) {
let beforeInputEvents = [];
let inputEvents = [];
function onBeforeInput(aEvent) {
beforeInputEvents.push(aEvent);
}
function onInput(aEvent) {
inputEvents.push(aEvent);
}
aTextarea.addEventListener("beforeinput", onBeforeInput);
aTextarea.addEventListener("input", onInput);
await copyPlaintext("abc\ndef\nghi");
aTextarea.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1, ctrlKey: true});
is(aTextarea.value,
"> abc\n> def\n> ghi\n\n",
"Pasted each line should start with \"> \"");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired #1');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", "abc\ndef\nghi", null, [], "#1");
is(inputEvents.length, 1,
'One "input" event should be fired #1');
checkInputEvent(inputEvents[0], "insertFromPasteAsQuotation", "abc\ndef\nghi", null, [], "#1");
aTextarea.value = "";
await copyPlaintext("> abc\n> def\n> ghi");
aTextarea.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1, ctrlKey: true});
is(aTextarea.value,
">> abc\n>> def\n>> ghi\n\n",
"Pasted each line should be start with \">> \" when already quoted one level");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired #2');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", "> abc\n> def\n> ghi", null, [], "#2");
is(inputEvents.length, 1,
'One "input" event should be fired #2');
checkInputEvent(inputEvents[0], "insertFromPasteAsQuotation", "> abc\n> def\n> ghi", null, [], "#2");
aTextarea.value = "";
await copyPlaintext("> abc\n> def\n\nghi");
aTextarea.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1, ctrlKey: true});
is(aTextarea.value,
">> abc\n>> def\n> \n> ghi\n\n",
"Pasted each line should be start with \">> \" when already quoted one level");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired #3');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", "> abc\n> def\n\nghi", null, [], "#3");
is(inputEvents.length, 1,
'One "input" event should be fired #3');
checkInputEvent(inputEvents[0], "insertFromPasteAsQuotation", "> abc\n> def\n\nghi", null, [], "#3");
aTextarea.value = "";
await copyPlaintext("abc\ndef\n\n");
aTextarea.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1, ctrlKey: true});
is(aTextarea.value,
"> abc\n> def\n> \n",
"If pasted text ends with \"\\n\", only the last line should not started with \">\"");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired #4');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", "abc\ndef\n\n", null, [], "#4");
is(inputEvents.length, 1,
'One "input" event should be fired #4');
checkInputEvent(inputEvents[0], "insertFromPasteAsQuotation", "abc\ndef\n\n", null, [], "#4");
aTextarea.value = "";
await copyPlaintext("abc\ndef\n\n");
aTextarea.addEventListener("paste", (event) => { event.preventDefault(); }, {once: true});
aTextarea.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1, ctrlKey: true});
is(aTextarea.value, "",
'Pasting as quote should have been canceled if "paste" event was canceled');
is(beforeInputEvents.length, 0,
'No "beforeinput" event should be fired since "paste" event was canceled #5');
is(inputEvents.length, 0,
'No "input" event should be fired since "paste" was canceled #5');
aTextarea.value = "";
await copyPlaintext("abc\ndef\n\n");
aTextarea.addEventListener("beforeinput", (event) => { event.preventDefault(); }, {once: true});
aTextarea.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1, ctrlKey: true});
is(aTextarea.value, "",
'Pasting as quote should have been canceled if "beforeinput" event was canceled');
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired #5');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", "abc\ndef\n\n", null, [], "#6");
is(inputEvents.length, 0,
'No "input" event should be fired since "beforeinput" was canceled #6');
aTextarea.value = "";
let pasteEventCount = 0;
function pasteEventLogger() {
pasteEventCount++;
}
aTextarea.addEventListener("paste", pasteEventLogger);
await copyPlaintext("abc");
aTextarea.focus();
document.body.addEventListener("click", (event) => { event.preventDefault(); }, {capture: true, once: true});
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1});
is(aTextarea.value, "abc",
"If 'click' event is consumed at capturing phase of the , paste should not be canceled");
is(pasteEventCount, 1,
"If 'click' event is consumed at capturing phase of the , 'paste' event should still be fired");
is(beforeInputEvents.length, 1,
'"beforeinput" event should be fired when the "click" event is canceled');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", "abc", null, [], 'when the "click" event is canceled');
is(inputEvents.length, 1,
'"input" event should be fired when the "click" event is canceled');
checkInputEvent(inputEvents[0], "insertFromPaste", "abc", null, [], 'when the "click" event is canceled');
aTextarea.value = "";
await copyPlaintext("abc");
aTextarea.focus();
aTextarea.addEventListener("mouseup", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1});
is(aTextarea.value, "abc",
"Even if 'mouseup' event is consumed, paste should be done");
is(pasteEventCount, 1,
"Even if 'mouseup' event is consumed, 'paste' event should be fired once");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired even if "mouseup" event is canceled');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", "abc", null, [], 'even if "mouseup" event is canceled');
is(inputEvents.length, 1,
'One "input" event should be fired even if "mouseup" event is canceled');
checkInputEvent(inputEvents[0], "insertFromPaste", "abc", null, [], 'even if "mouseup" event is canceled');
aTextarea.value = "";
await copyPlaintext("abc");
aTextarea.focus();
aTextarea.addEventListener("click", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1});
is(aTextarea.value, "abc",
"If 'click' event handler is added to the );
is(pasteEventCount, 1,
"If 'click' event handler is added to the );
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired even if "click" event is canceled in bubbling phase');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", "abc", null, [], 'even if "click" event is canceled in bubbling phase');
is(inputEvents.length, 1,
'One "input" event should be fired even if "click" event is canceled in bubbling phase');
checkInputEvent(inputEvents[0], "insertFromPaste", "abc", null, [], 'even if "click" event is canceled in bubbling phase');
aTextarea.value = "";
await copyPlaintext("abc");
aTextarea.focus();
aTextarea.addEventListener("auxclick", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1});
is(aTextarea.value, "",
"If 'auxclick' event is consumed, paste should be canceled");
is(pasteEventCount, 0,
"If 'auxclick' event is consumed, 'paste' event should not be fired once");
is(beforeInputEvents.length, 0,
'No "beforeinput" event should be fired if "auxclick" event is canceled');
is(inputEvents.length, 0,
'No "input" event should be fired if "auxclick" event is canceled');
aTextarea.value = "";
await copyPlaintext("abc");
aTextarea.focus();
aTextarea.addEventListener("paste", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1});
is(aTextarea.value, "",
"If 'paste' event is consumed, paste should be canceled");
is(pasteEventCount, 1,
'One "paste" event should be fired for making it possible to consume');
is(beforeInputEvents.length, 0,
'No "beforeinput" event should be fired if "paste" event is canceled');
is(inputEvents.length, 0,
'No "input" event should be fired if "paste" event is canceled');
aTextarea.value = "";
await copyPlaintext("abc");
aTextarea.focus();
aTextarea.addEventListener("beforeinput", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aTextarea, {button: 1});
is(aTextarea.value, "",
"If 'beforeinput' event is consumed, paste should be canceled");
is(pasteEventCount, 1,
'One "paste" event should be fired before "beforeinput" event is consumed');
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired for making it possible to consume');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", "abc", null, [], 'when "beforeinput" is canceled in bubbling phase');
is(inputEvents.length, 0,
'No "input" event should be fired if "paste" event is canceled');
aTextarea.value = "";
aTextarea.removeEventListener("paste", pasteEventLogger);
aTextarea.removeEventListener("beforeinput", onBeforeInput);
aTextarea.removeEventListener("input", onInput);
}
async function doContenteditableTests(aEditableDiv) {
let beforeInputEvents = [];
let inputEvents = [];
let selectionRanges = [];
function onBeforeInput(aEvent) {
beforeInputEvents.push(aEvent);
let selection = document.getSelection();
selectionRanges = [];
for (let i = 0; i < selection.rangeCount; i++) {
let range = selection.getRangeAt(i);
selectionRanges.push({startContainer: range.startContainer, startOffset: range.startOffset,
endContainer: range.endContainer, endOffset: range.endOffset});
}
}
function onInput(aEvent) {
inputEvents.push(aEvent);
}
aEditableDiv.addEventListener("beforeinput", onBeforeInput);
aEditableDiv.addEventListener("input", onInput);
await copyPlaintext("abc\ndef\nghi");
aEditableDiv.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1, ctrlKey: true});
is(aEditableDiv.innerHTML,
"cite\">abc def ghi ",
"Pasted plaintext should be in element and each linebreaker should be element" );
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired on the editing host');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", null,
[{type: "text/plain", data: "abc\ndef\nghi"}], selectionRanges, "(contenteditable)");
is(inputEvents.length, 1,
'One "input" event should be fired on the editing host');
checkInputEvent(inputEvents[0], "insertFromPasteAsQuotation", null,
[{type: "text/plain", data: "abc\ndef\nghi"}], [], "(contenteditable)");
aEditableDiv.innerHTML = "";
let pasteEventCount = 0;
function pasteEventLogger() {
pasteEventCount++;
}
aEditableDiv.addEventListener("paste", pasteEventLogger);
await copyPlaintext("abc");
aEditableDiv.focus();
window.addEventListener("click", (event) => { event.preventDefault(); }, {capture: true, once: true});
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "abc",
"If 'click' event is consumed at capturing phase of the window, paste should not be canceled");
is(pasteEventCount, 1,
"If 'click' event is consumed at capturing phase of the window, 'paste' event should be fired once");
is(beforeInputEvents.length, 1,
'"beforeinput" event should still be fired when the "click" event is canceled (contenteditable)');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", null,
[{type: "text/plain", data: "abc"}], selectionRanges, 'when the "click" event is canceled (contenteditable)');
is(inputEvents.length, 1,
'"input" event should still be fired when the "click" event is canceled (contenteditable)');
checkInputEvent(inputEvents[0], "insertFromPaste", null,
[{type: "text/plain", data: "abc"}], [], 'when the "click" event is canceled (contenteditable)');
aEditableDiv.innerHTML = "";
await copyPlaintext("abc");
aEditableDiv.focus();
aEditableDiv.addEventListener("mouseup", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "abc",
"Even if 'mouseup' event is consumed, paste should be done");
is(pasteEventCount, 1,
"Even if 'mouseup' event is consumed, 'paste' event should be fired once");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired even if "mouseup" event is canceled (contenteditable)');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: "abc"}], selectionRanges,
'even if "mouseup" event is canceled (contenteditable)');
is(inputEvents.length, 1,
'One "input" event should be fired even if "mouseup" event is canceled (contenteditable)');
checkInputEvent(inputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: "abc"}], [],
'even if "mouseup" event is canceled (contenteditable)');
aEditableDiv.innerHTML = "";
await copyPlaintext("abc");
aEditableDiv.focus();
aEditableDiv.addEventListener("click", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "abc",
"Even if 'click' event handler is added to the editing host, paste should not be canceled");
is(pasteEventCount, 1,
"Even if 'click' event handler is added to the editing host, 'paste' event should be fired");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired even if "click" event is canceled in bubbling phase (contenteditable)');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: "abc"}], selectionRanges,
'even if "click" event is canceled in bubbling phase (contenteditable)');
is(inputEvents.length, 1,
'One "input" event should be fired even if "click" event is canceled in bubbling phase (contenteditable)');
checkInputEvent(inputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: "abc"}], [],
'even if "click" event is canceled in bubbling phase (contenteditable)');
aEditableDiv.innerHTML = "";
await copyPlaintext("abc");
aEditableDiv.focus();
aEditableDiv.addEventListener("auxclick", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "",
"If 'auxclick' event is consumed, paste should be canceled");
is(pasteEventCount, 0,
"If 'auxclick' event is consumed, 'paste' event should not be fired");
is(beforeInputEvents.length, 0,
'No "beforeinput" event should be fired if "auxclick" event is canceled (contenteditable)');
is(inputEvents.length, 0,
'No "input" event should be fired if "auxclick" event is canceled (contenteditable)');
aEditableDiv.innerHTML = "";
await copyPlaintext("abc");
aEditableDiv.focus();
aEditableDiv.addEventListener("paste", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "",
"If 'paste' event is consumed, paste should be canceled");
is(pasteEventCount, 1,
'One "paste" event should be fired for making it possible to consume');
is(beforeInputEvents.length, 0,
'No "beforeinput" event should be fired if "paste" event is canceled (contenteditable)');
is(inputEvents.length, 0,
'No "input" event should be fired if "paste" event is canceled (contenteditable)');
aEditableDiv.innerHTML = "";
await copyPlaintext("abc");
aEditableDiv.focus();
aEditableDiv.addEventListener("beforeinput", (event) => { event.preventDefault(); }, {once: true});
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "",
"If 'paste' event is consumed, paste should be canceled");
is(pasteEventCount, 1,
'One "paste" event should be fired before "beforeinput" event');
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired for making it possible to consume (contenteditable)');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: "abc"}], selectionRanges,
'when "beforeinput" will be canceled (contenteditable)');
is(inputEvents.length, 0,
'No "input" event should be fired if "beforeinput" event is canceled (contenteditable)');
aEditableDiv.innerHTML = "";
// If clipboard event is disabled, InputEvent.dataTransfer should have only empty string.
await SpecialPowers.pushPrefEnv({"set": [["dom.event.clipboardevents.enabled", false]]});
await copyPlaintext("abc");
aEditableDiv.focus();
pasteEventCount = 0;
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1});
is(aEditableDiv.innerHTML, "abc",
"Even if clipboard event is disabled, paste should be done");
is(pasteEventCount, 0,
"If clipboard event is disabled, 'paste' event shouldn't be fired once");
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired even if clipboard event is disabled (contenteditable)');
checkInputEvent(beforeInputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: ""}], selectionRanges,
"when clipboard event is disabled (contenteditable)");
is(inputEvents.length, 1,
'One "input" event should be fired even if clipboard event is disabled (contenteditable)');
checkInputEvent(inputEvents[0], "insertFromPaste", null, [{type: "text/plain", data: ""}], [],
"when clipboard event is disabled (contenteditable)");
await SpecialPowers.pushPrefEnv({"set": [["dom.event.clipboardevents.enabled", true]]});
aEditableDiv.innerHTML = "";
aEditableDiv.removeEventListener("paste", pasteEventLogger);
// Oddly, copyHTMLContent fails randomly only on Linux. Let's skip this.
if (navigator.platform.startsWith("Linux")) {
aEditableDiv.removeEventListener("input", onInput);
return;
}
await copyHTMLContent("abc def ghi ");
aEditableDiv.focus();
beforeInputEvents = [];
inputEvents = [];
synthesizeMouseAtCenter(aEditableDiv, {button: 1, ctrlKey: true});
if (!navigator.appVersion.includes("Android")) {
is(aEditableDiv.innerHTML,
"cite\">abc def ghi ",
"Pasted HTML content should be set to the " );
} else {
// Oddly, on Android, we use <br> elements for pasting <p> elements.
is(aEditableDiv.innerHTML,
"cite\">abc
def
ghi ",
"Pasted HTML content should be set to the " );
}
// On windows, HTML clipboard includes extra data.
// The values are from widget/windows/nsDataObj.cpp.
const kHTMLPrefix = (navigator.platform.includes("Win")) ? kTextHtmlPrefixClipboardDataWindows : "";
const kHTMLPostfix = (navigator.platform.includes("Win")) ? kTextHtmlSuffixClipboardDataWindows : "";
is(beforeInputEvents.length, 1,
'One "beforeinput" event should be fired when pasting HTML');
checkInputEvent(beforeInputEvents[0], "insertFromPasteAsQuotation", null,
[{type: "text/html",
data: `${kHTMLPrefix}<p>abc</p><p>def</p><p>ghi</p>${kHTMLPostfix}`}],
selectionRanges,
"when pasting HTML");
is(inputEvents.length, 1,
'One "input" event should be fired when pasting HTML');
checkInputEvent(inputEvents[0], "insertFromPasteAsQuotation", null,
[{type: "text/html",
data: `${kHTMLPrefix}<p>abc</p><p>def</p><p>ghi</p>${kHTMLPostfix}`}],
[],
"when pasting HTML");
aEditableDiv.innerHTML = "";
aEditableDiv.removeEventListener("beforeinput", onBeforeInput);
aEditableDiv.removeEventListener("input", onInput);
}
async function doNestedEditorTests(aEditableDiv) {
await copyPlaintext("CLIPBOARD TEXT");
aEditableDiv.innerHTML = 'foo ';
aEditableDiv.focus();
let textarea = document.getElementById("textarea");
let pasteTarget = null;
function onPaste(aEvent) {
pasteTarget = aEvent.target;
}
document.addEventListener("paste", onPaste);
synthesizeMouseAtCenter(textarea, {button: 1});
is(pasteTarget.getAttribute("id"), "textarea",
"Target of 'paste' event should be the clicked );
is(textarea.value, "CLIPBOARD TEXT",
"Clicking in |
|