зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1777695 - Add some entries in the context menu when editing a PDF r=mconley
It adds the entries Undo, Redo, Cut, Copy, Paste, Delete and Select all, only when the pdf editing mode is enabled. Differential Revision: https://phabricator.services.mozilla.com/D151122
This commit is contained in:
Родитель
a753b3db0b
Коммит
981db3428b
|
@ -893,6 +893,7 @@ class ContextMenuChild extends JSWindowActorChild {
|
|||
context.onSpellcheckable = false;
|
||||
context.onTextInput = false;
|
||||
context.onVideo = false;
|
||||
context.inPDFEditor = false;
|
||||
|
||||
// Remember the node and its owner document that was clicked
|
||||
// This may be modifed before sending to nsContextMenu
|
||||
|
@ -918,6 +919,10 @@ class ContextMenuChild extends JSWindowActorChild {
|
|||
context.inPDFViewer =
|
||||
context.target.ownerDocument.nodePrincipal.originNoSuffix ==
|
||||
"resource://pdf.js";
|
||||
if (context.inPDFViewer) {
|
||||
context.pdfEditorStates = context.target.ownerDocument.editorStates;
|
||||
context.inPDFEditor = !!context.pdfEditorStates?.isEditing;
|
||||
}
|
||||
|
||||
// Check if we are in a synthetic document (stand alone image, video, etc.).
|
||||
context.inSyntheticDoc = context.target.ownerDocument.mozSyntheticDocument;
|
||||
|
|
|
@ -310,6 +310,31 @@
|
|||
data-l10n-id="main-context-menu-print-selection"
|
||||
oncommand="gContextMenu.printSelection();"/>
|
||||
<menuseparator id="context-sep-selectall"/>
|
||||
|
||||
<menuitem id="context-pdfjs-undo"
|
||||
data-l10n-id="text-action-undo"
|
||||
oncommand="gContextMenu.pdfJSCmd('undo');"/>
|
||||
<menuitem id="context-pdfjs-redo"
|
||||
data-l10n-id="text-action-redo"
|
||||
oncommand="gContextMenu.pdfJSCmd('redo');"/>
|
||||
<menuseparator id="context-sep-pdfjs-redo"/>
|
||||
<menuitem id="context-pdfjs-cut"
|
||||
data-l10n-id="text-action-cut"
|
||||
oncommand="gContextMenu.pdfJSCmd('cut');"/>
|
||||
<menuitem id="context-pdfjs-copy"
|
||||
data-l10n-id="text-action-copy"
|
||||
oncommand="gContextMenu.pdfJSCmd('copy');"/>
|
||||
<menuitem id="context-pdfjs-paste"
|
||||
data-l10n-id="text-action-paste"
|
||||
oncommand="gContextMenu.pdfJSCmd('paste');"/>
|
||||
<menuitem id="context-pdfjs-delete"
|
||||
data-l10n-id="text-action-delete"
|
||||
oncommand="gContextMenu.pdfJSCmd('delete');"/>
|
||||
<menuitem id="context-pdfjs-selectall"
|
||||
data-l10n-id="text-action-select-all"
|
||||
oncommand="gContextMenu.pdfJSCmd('selectAll');"/>
|
||||
<menuseparator id="context-sep-pdfjs-selectall"/>
|
||||
|
||||
<menuitem id="context-take-screenshot"
|
||||
data-l10n-id="main-context-menu-take-screenshot"
|
||||
oncommand="gContextMenu.takeScreenshot();"/>
|
||||
|
|
|
@ -193,6 +193,7 @@ class nsContextMenu {
|
|||
this.isDesignMode = context.isDesignMode;
|
||||
this.inFrame = context.inFrame;
|
||||
this.inPDFViewer = context.inPDFViewer;
|
||||
this.inPDFEditor = context.inPDFEditor;
|
||||
this.inSrcdocFrame = context.inSrcdocFrame;
|
||||
this.inSyntheticDoc = context.inSyntheticDoc;
|
||||
this.inTabBrowser = context.inTabBrowser;
|
||||
|
@ -226,6 +227,8 @@ class nsContextMenu {
|
|||
this.onTextInput = context.onTextInput;
|
||||
this.onVideo = context.onVideo;
|
||||
|
||||
this.pdfEditorStates = context.pdfEditorStates;
|
||||
|
||||
this.target = context.target;
|
||||
this.targetIdentifier = context.targetIdentifier;
|
||||
|
||||
|
@ -338,6 +341,7 @@ class nsContextMenu {
|
|||
this.initViewSourceItems();
|
||||
this.initScreenshotItem();
|
||||
this.initPasswordControlItems();
|
||||
this.initPDFItems();
|
||||
|
||||
this.showHideSeparators(aXulMenu);
|
||||
if (!aXulMenu.showHideSeparators) {
|
||||
|
@ -350,6 +354,60 @@ class nsContextMenu {
|
|||
}
|
||||
}
|
||||
|
||||
initPDFItems() {
|
||||
for (const id of [
|
||||
"context-pdfjs-undo",
|
||||
"context-pdfjs-redo",
|
||||
"context-sep-pdfjs-redo",
|
||||
"context-pdfjs-cut",
|
||||
"context-pdfjs-copy",
|
||||
"context-pdfjs-paste",
|
||||
"context-pdfjs-delete",
|
||||
"context-pdfjs-selectall",
|
||||
"context-sep-pdfjs-selectall",
|
||||
]) {
|
||||
this.showItem(id, this.inPDFEditor);
|
||||
}
|
||||
|
||||
if (!this.inPDFEditor) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
isEmpty,
|
||||
hasEmptyClipboard,
|
||||
hasSomethingToUndo,
|
||||
hasSomethingToRedo,
|
||||
hasSelectedEditor,
|
||||
} = this.pdfEditorStates;
|
||||
|
||||
this.setItemAttr("context-pdfjs-undo", "disabled", !hasSomethingToUndo);
|
||||
this.setItemAttr("context-pdfjs-redo", "disabled", !hasSomethingToRedo);
|
||||
this.setItemAttr(
|
||||
"context-sep-pdfjs-redo",
|
||||
"disabled",
|
||||
!hasSomethingToUndo && !hasSomethingToRedo
|
||||
);
|
||||
this.setItemAttr(
|
||||
"context-pdfjs-cut",
|
||||
"disabled",
|
||||
isEmpty || !hasSelectedEditor
|
||||
);
|
||||
this.setItemAttr(
|
||||
"context-pdfjs-copy",
|
||||
"disabled",
|
||||
isEmpty || !hasSelectedEditor
|
||||
);
|
||||
this.setItemAttr("context-pdfjs-paste", "disabled", hasEmptyClipboard);
|
||||
this.setItemAttr(
|
||||
"context-pdfjs-delete",
|
||||
"disabled",
|
||||
isEmpty || !hasSelectedEditor
|
||||
);
|
||||
this.setItemAttr("context-pdfjs-selectall", "disabled", isEmpty);
|
||||
this.setItemAttr("context-sep-pdfjs-selectall", "disabled", isEmpty);
|
||||
}
|
||||
|
||||
initOpenItems() {
|
||||
var isMailtoInternal = false;
|
||||
if (this.onMailtoLink) {
|
||||
|
@ -551,7 +609,9 @@ class nsContextMenu {
|
|||
// (or is in a frame), or a canvas. If this isn't an image, check
|
||||
// if there is a background image.
|
||||
let showViewImage =
|
||||
(this.onImage && (!this.inSyntheticDoc || this.inFrame)) || this.onCanvas;
|
||||
((this.onImage && (!this.inSyntheticDoc || this.inFrame)) ||
|
||||
this.onCanvas) &&
|
||||
!this.inPDFViewer;
|
||||
let showBGImage =
|
||||
this.hasBGImage &&
|
||||
!this.hasMultipleBGImages &&
|
||||
|
@ -567,7 +627,10 @@ class nsContextMenu {
|
|||
this.showItem("context-viewimage", showViewImage || showBGImage);
|
||||
|
||||
// Save image depends on having loaded its content.
|
||||
this.showItem("context-saveimage", this.onLoadedImage || this.onCanvas);
|
||||
this.showItem(
|
||||
"context-saveimage",
|
||||
(this.onLoadedImage || this.onCanvas) && !this.inPDFEditor
|
||||
);
|
||||
|
||||
// Copy image contents depends on whether we're on an image.
|
||||
// Note: the element doesn't exist on all platforms, but showItem() takes
|
||||
|
@ -879,7 +942,8 @@ class nsContextMenu {
|
|||
this.onImage ||
|
||||
this.onVideo ||
|
||||
this.onAudio ||
|
||||
this.inSyntheticDoc
|
||||
this.inSyntheticDoc ||
|
||||
this.inPDFEditor
|
||||
) || this.isDesignMode
|
||||
);
|
||||
|
||||
|
@ -1402,6 +1466,10 @@ class nsContextMenu {
|
|||
}
|
||||
}
|
||||
|
||||
pdfJSCmd(name) {
|
||||
this.browser.sendMessageToActor("PDFJS:Editing", { name }, "Pdfjs");
|
||||
}
|
||||
|
||||
// View Partial Source
|
||||
viewPartialSource() {
|
||||
let { browser } = this;
|
||||
|
|
|
@ -605,6 +605,31 @@ class ChromeActions {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the different editor states in order to be able to update the context
|
||||
* menu.
|
||||
* @param {Object} details
|
||||
*/
|
||||
updateEditorStates({ details }) {
|
||||
const doc = this.domWindow.document;
|
||||
if (!doc.editorStates) {
|
||||
doc.editorStates = {
|
||||
isEditing: false,
|
||||
isEmpty: true,
|
||||
hasEmptyClipboard: true,
|
||||
hasSomethingToUndo: false,
|
||||
hasSomethingToRedo: false,
|
||||
hasSelectedEditor: false,
|
||||
};
|
||||
}
|
||||
const { editorStates } = doc;
|
||||
for (const [key, value] of Object.entries(details)) {
|
||||
if (typeof value === "boolean" && key in editorStates) {
|
||||
editorStates[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,6 +39,10 @@ class PdfjsChild extends JSWindowActorChild {
|
|||
break;
|
||||
}
|
||||
|
||||
case "PDFJS:Editing":
|
||||
let data = Cu.cloneInto(msg.data, this.contentWindow);
|
||||
this.dispatchEvent("editingaction", data);
|
||||
break;
|
||||
case "PDFJS:ZoomIn":
|
||||
case "PDFJS:ZoomOut":
|
||||
case "PDFJS:ZoomReset":
|
||||
|
|
|
@ -40,3 +40,4 @@ support-files =
|
|||
[browser_pdfjs_views.js]
|
||||
[browser_pdfjs_zoom.js]
|
||||
skip-if = (verify && debug && (os == 'win'))
|
||||
[browser_pdfjs_editing_contextmenu.js]
|
||||
|
|
|
@ -0,0 +1,431 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const RELATIVE_DIR = "toolkit/components/pdfjs/test/";
|
||||
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
||||
|
||||
// This is a modified version from browser_contextmenuFillLogins.js.
|
||||
async function openContextMenuAt(browser, x, y) {
|
||||
const doc = browser.ownerDocument;
|
||||
const contextMenu = doc.getElementById("contentAreaContextMenu");
|
||||
|
||||
const contextMenuShownPromise = BrowserTestUtils.waitForEvent(
|
||||
contextMenu,
|
||||
"popupshown"
|
||||
);
|
||||
|
||||
// Synthesize a contextmenu event to actually open the context menu.
|
||||
await BrowserTestUtils.synthesizeMouseAtPoint(
|
||||
x,
|
||||
y,
|
||||
{
|
||||
type: "contextmenu",
|
||||
button: 2,
|
||||
},
|
||||
browser
|
||||
);
|
||||
|
||||
await contextMenuShownPromise;
|
||||
return contextMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
* The text layer contains some spans with the text of the pdf.
|
||||
* @param {Object} browser
|
||||
* @param {string} text
|
||||
* @returns {Object} the bbox of the span containing the text.
|
||||
*/
|
||||
async function getSpanBox(browser, text) {
|
||||
return SpecialPowers.spawn(browser, [text], async function(text) {
|
||||
const { ContentTaskUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/ContentTaskUtils.jsm"
|
||||
);
|
||||
const { document } = content;
|
||||
|
||||
await ContentTaskUtils.waitForCondition(
|
||||
() => !!document.querySelector(".textLayer .endOfContent"),
|
||||
"The text layer must be displayed"
|
||||
);
|
||||
|
||||
let targetSpan = null;
|
||||
for (const span of document.querySelectorAll(
|
||||
`.textLayer span[role="presentation"]`
|
||||
)) {
|
||||
if (span.innerText.includes(text)) {
|
||||
targetSpan = span;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.ok(targetSpan, `document must have a span containing '${text}'`);
|
||||
|
||||
const { x, y, width, height } = targetSpan.getBoundingClientRect();
|
||||
return { x, y, width, height };
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a context menu and get the pdfjs entries
|
||||
* @param {Object} browser
|
||||
* @param {Object} box
|
||||
* @returns {Map<string,HTMLElement>} the pdfjs menu entries.
|
||||
*/
|
||||
async function getContextMenuItems(browser, box) {
|
||||
const { x, y, width, height } = box;
|
||||
const menuitems = [
|
||||
"context-pdfjs-undo",
|
||||
"context-pdfjs-redo",
|
||||
"context-sep-pdfjs-redo",
|
||||
"context-pdfjs-cut",
|
||||
"context-pdfjs-copy",
|
||||
"context-pdfjs-paste",
|
||||
"context-pdfjs-delete",
|
||||
"context-pdfjs-selectall",
|
||||
"context-sep-pdfjs-selectall",
|
||||
];
|
||||
|
||||
await openContextMenuAt(browser, x + width / 2, y + height / 2);
|
||||
|
||||
const results = new Map();
|
||||
const doc = browser.ownerDocument;
|
||||
for (const menuitem of menuitems) {
|
||||
const item = doc.getElementById(menuitem);
|
||||
results.set(menuitem, item || null);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a context menu on the element corresponding to the given selector
|
||||
* and returs the pdfjs menu entries.
|
||||
* @param {Object} browser
|
||||
* @param {string} selector
|
||||
* @returns {Map<string,HTMLElement>} the pdfjs menu entries.
|
||||
*/
|
||||
async function getContextMenuItemsOn(browser, selector) {
|
||||
const box = await SpecialPowers.spawn(browser, [selector], async function(
|
||||
selector
|
||||
) {
|
||||
const element = content.document.querySelector(selector);
|
||||
const { x, y, width, height } = element.getBoundingClientRect();
|
||||
return { x, y, width, height };
|
||||
});
|
||||
return getContextMenuItems(browser, box);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the context menu.
|
||||
* @param {Object} browser
|
||||
*/
|
||||
async function hideContextMenu(browser) {
|
||||
const doc = browser.ownerDocument;
|
||||
const contextMenu = doc.getElementById("contentAreaContextMenu");
|
||||
|
||||
const popupHiddenPromise = BrowserTestUtils.waitForEvent(
|
||||
contextMenu,
|
||||
"popuphidden"
|
||||
);
|
||||
contextMenu.hidePopup();
|
||||
await popupHiddenPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable an editor (Ink, FreeText, ...).
|
||||
* @param {Object} browser
|
||||
* @param {string} name
|
||||
*/
|
||||
async function enableEditor(browser, name) {
|
||||
await SpecialPowers.spawn(browser, [name], async function(name) {
|
||||
const button = content.document.querySelector(`#editor${name}`);
|
||||
button.click();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Click at the given coordinates.
|
||||
* @param {Object} browser
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
*/
|
||||
async function clickAt(browser, x, y) {
|
||||
BrowserTestUtils.synthesizeMouseAtPoint(
|
||||
x,
|
||||
y,
|
||||
{
|
||||
type: "mousedown",
|
||||
button: 0,
|
||||
},
|
||||
browser
|
||||
);
|
||||
BrowserTestUtils.synthesizeMouseAtPoint(
|
||||
x,
|
||||
y,
|
||||
{
|
||||
type: "mouseup",
|
||||
button: 0,
|
||||
},
|
||||
browser
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click on the element corresponding to the given selector.
|
||||
* @param {Object} browser
|
||||
* @param {string} selector
|
||||
*/
|
||||
async function clickOn(browser, selector) {
|
||||
const [x, y] = await SpecialPowers.spawn(browser, [selector], async function(
|
||||
selector
|
||||
) {
|
||||
const element = content.document.querySelector(selector);
|
||||
const { x, y, width, height } = element.getBoundingClientRect();
|
||||
return [x + width / 2, y + height / 2];
|
||||
});
|
||||
await clickAt(browser, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write some text using the keyboard.
|
||||
* @param {Object} browser
|
||||
* @param {string} text
|
||||
*/
|
||||
async function write(browser, text) {
|
||||
await SpecialPowers.spawn(browser, [text], async function(text) {
|
||||
const { ContentTaskUtils } = ChromeUtils.import(
|
||||
"resource://testing-common/ContentTaskUtils.jsm"
|
||||
);
|
||||
const EventUtils = ContentTaskUtils.getEventUtils(content);
|
||||
|
||||
for (const char of text.split("")) {
|
||||
EventUtils.synthesizeKey(char, {}, content);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a FreeText annotation and write some text inside.
|
||||
* @param {Object} browser
|
||||
* @param {string} text
|
||||
* @param {Object} box
|
||||
*/
|
||||
async function addFreeText(browser, text, box) {
|
||||
const { x, y, width, height } = box;
|
||||
await clickAt(browser, x + 0.1 * width, y + 0.5 * height);
|
||||
await write(browser, text);
|
||||
await clickAt(browser, x + 0.1 * width, y + 2 * height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of elements corresponding to the given selector.
|
||||
* @param {Object} browser
|
||||
* @param {string} selector
|
||||
* @returns
|
||||
*/
|
||||
async function countElements(browser, selector) {
|
||||
return SpecialPowers.spawn(browser, [selector], async function(selector) {
|
||||
const { document } = content;
|
||||
return document.querySelectorAll(selector).length;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the enabled pdfjs menuitems are the expected ones.
|
||||
* @param {Map<string,HTMLElement>} menuitems
|
||||
* @param {Array<string>} expected
|
||||
*/
|
||||
function assertMenuitems(menuitems, expected) {
|
||||
Assert.deepEqual(
|
||||
[...menuitems.values()]
|
||||
.filter(
|
||||
elmt =>
|
||||
!elmt.id.includes("-sep-") &&
|
||||
!elmt.hidden &&
|
||||
elmt.getAttribute("disabled") === "false"
|
||||
)
|
||||
.map(elmt => elmt.id),
|
||||
expected
|
||||
);
|
||||
}
|
||||
|
||||
// Text copy, paste, undo, redo, delete and select all in using the context
|
||||
// menu.
|
||||
add_task(async function test() {
|
||||
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
let handlerInfo = mimeService.getFromTypeAndExtension(
|
||||
"application/pdf",
|
||||
"pdf"
|
||||
);
|
||||
|
||||
// Make sure pdf.js is the default handler.
|
||||
is(
|
||||
handlerInfo.alwaysAskBeforeHandling,
|
||||
false,
|
||||
"pdf handler defaults to always-ask is false"
|
||||
);
|
||||
is(
|
||||
handlerInfo.preferredAction,
|
||||
Ci.nsIHandlerInfo.handleInternally,
|
||||
"pdf handler defaults to internal"
|
||||
);
|
||||
|
||||
info("Pref action: " + handlerInfo.preferredAction);
|
||||
|
||||
await BrowserTestUtils.withNewTab(
|
||||
{ gBrowser, url: "about:blank" },
|
||||
async function(browser) {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [["pdfjs.annotationEditorMode", 0]],
|
||||
});
|
||||
|
||||
// check that PDF is opened with internal viewer
|
||||
await waitForPdfJS(browser, TESTROOT + "file_pdfjs_test.pdf");
|
||||
|
||||
const spanBox = await getSpanBox(browser, "and found references");
|
||||
let menuitems = await getContextMenuItems(browser, spanBox);
|
||||
|
||||
// Nothing have been edited, hence the context menu doesn't contain any
|
||||
// pdf entries.
|
||||
Assert.ok(
|
||||
[...menuitems.values()].every(elmt => elmt.hidden),
|
||||
"No visible pdf menuitem"
|
||||
);
|
||||
await hideContextMenu(browser);
|
||||
|
||||
await enableEditor(browser, "FreeText");
|
||||
await addFreeText(browser, "hello", spanBox);
|
||||
|
||||
Assert.equal(await countElements(browser, ".freeTextEditor"), 1);
|
||||
|
||||
menuitems = await getContextMenuItems(browser, spanBox);
|
||||
assertMenuitems(menuitems, [
|
||||
"context-pdfjs-undo", // Last created editor is undoable
|
||||
"context-pdfjs-selectall", // and selectable.
|
||||
]);
|
||||
// Undo.
|
||||
menuitems.get("context-pdfjs-undo").click();
|
||||
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
0,
|
||||
"The FreeText editor must have been removed"
|
||||
);
|
||||
|
||||
menuitems = await getContextMenuItems(browser, spanBox);
|
||||
|
||||
// The editor removed thanks to "undo" is now redoable
|
||||
assertMenuitems(menuitems, ["context-pdfjs-redo"]);
|
||||
menuitems.get("context-pdfjs-redo").click();
|
||||
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
1,
|
||||
"The FreeText editor must have been added back"
|
||||
);
|
||||
|
||||
await clickOn(browser, "#pdfjs_internal_editor_0");
|
||||
menuitems = await getContextMenuItemsOn(
|
||||
browser,
|
||||
"#pdfjs_internal_editor_0"
|
||||
);
|
||||
|
||||
assertMenuitems(menuitems, [
|
||||
"context-pdfjs-undo",
|
||||
"context-pdfjs-cut",
|
||||
"context-pdfjs-copy",
|
||||
"context-pdfjs-delete",
|
||||
"context-pdfjs-selectall",
|
||||
]);
|
||||
|
||||
menuitems.get("context-pdfjs-cut").click();
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
0,
|
||||
"The FreeText editor must have been cut"
|
||||
);
|
||||
|
||||
menuitems = await getContextMenuItems(browser, spanBox);
|
||||
assertMenuitems(menuitems, ["context-pdfjs-undo", "context-pdfjs-paste"]);
|
||||
|
||||
menuitems.get("context-pdfjs-paste").click();
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
1,
|
||||
"The FreeText editor must have been pasted"
|
||||
);
|
||||
|
||||
await clickOn(browser, "#pdfjs_internal_editor_2");
|
||||
menuitems = await getContextMenuItemsOn(
|
||||
browser,
|
||||
"#pdfjs_internal_editor_2"
|
||||
);
|
||||
|
||||
assertMenuitems(menuitems, [
|
||||
"context-pdfjs-undo",
|
||||
"context-pdfjs-cut",
|
||||
"context-pdfjs-copy",
|
||||
"context-pdfjs-paste",
|
||||
"context-pdfjs-delete",
|
||||
"context-pdfjs-selectall",
|
||||
]);
|
||||
|
||||
menuitems.get("context-pdfjs-delete").click();
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
0,
|
||||
"The FreeText editor must have been deleted"
|
||||
);
|
||||
|
||||
menuitems = await getContextMenuItems(browser, spanBox);
|
||||
menuitems.get("context-pdfjs-paste").click();
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
1,
|
||||
"The FreeText editor must have been pasted"
|
||||
);
|
||||
|
||||
await clickOn(browser, "#pdfjs_internal_editor_3");
|
||||
menuitems = await getContextMenuItemsOn(
|
||||
browser,
|
||||
"#pdfjs_internal_editor_3"
|
||||
);
|
||||
menuitems.get("context-pdfjs-copy").click();
|
||||
menuitems.get("context-pdfjs-paste").click();
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
2,
|
||||
"The FreeText editor must have been pasted"
|
||||
);
|
||||
|
||||
menuitems = await getContextMenuItems(browser, spanBox);
|
||||
menuitems.get("context-pdfjs-selectall").click();
|
||||
menuitems.get("context-pdfjs-delete").click();
|
||||
await hideContextMenu(browser);
|
||||
|
||||
Assert.equal(
|
||||
await countElements(browser, ".freeTextEditor"),
|
||||
0,
|
||||
"All the FreeText editors must have been deleted"
|
||||
);
|
||||
|
||||
await SpecialPowers.spawn(browser, [], async function() {
|
||||
var viewer = content.wrappedJSObject.PDFViewerApplication;
|
||||
await viewer.close();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
Загрузка…
Ссылка в новой задаче