get toolbarButton() { returnthis.browser.ownerDocument.getElementById("screenshot-button");
}
get panel() { returnthis.browser.ownerDocument.querySelector(this.selector.panel);
}
/** * Click the screenshots button in the toolbar
*/
triggerUIFromToolbar() {
let button = this.toolbarButton;
ok(
BrowserTestUtils.isVisible(button), "The screenshot toolbar button is visible"
);
button.click();
}
async getPanelButton(selector) {
let panel = await this.waitForPanel();
let screenshotsButtons = panel.querySelector("screenshots-buttons");
ok(screenshotsButtons, "Found the screenshots-buttons");
let button = screenshotsButtons.shadowRoot.querySelector(selector);
ok(button, `Found ${selector} button`); return button;
}
/** * Get the button from screenshots preview dialog * @param {Sting} name The id of the button to query * @returns The button or null
*/
getDialogButton(name) {
let dialog = this.getDialog();
let screenshotsPreviewEl = dialog._frame.contentDocument.querySelector( "screenshots-preview"
);
await ContentTaskUtils.waitForCondition(() => {
info(`got ${screenshotsChild.overlay.state}. expected ${stateArr}`); return stateArr.includes(screenshotsChild.overlay.state);
}, `Wait for overlay state to be ${stateArr}`);
return screenshotsChild.overlay.state;
});
}
async assertStateChange(newState) {
let currentState = await this.waitForStateChange([newState]);
is(
currentState,
newState,
`The current state is ${currentState}, expected ${newState}`
);
}
/** * This will drag an overlay starting at the given startX and startY coordinates and ending * at the given endX and endY coordinates. * * endY should be at least 70px from the bottom of window and endX should be at least * 265px from the left of the window. If these requirements are not met then the * overlay buttons (cancel, copy, download) will be positioned different from the default * and the methods to click the overlay buttons will not work unless the updated * position coordinates are supplied. * See https://searchfox.org/mozilla-central/rev/af78418c4b5f2c8721d1a06486cf4cf0b33e1e8d/browser/components/screenshots/ScreenshotsOverlayChild.sys.mjs#1789,1798 * for how the overlay buttons are positioned when the overlay rect is near the bottom or * left edge of the window. * * Note: The distance of the rect should be greater than 40 to enter in the "dragging" state. * See https://searchfox.org/mozilla-central/rev/af78418c4b5f2c8721d1a06486cf4cf0b33e1e8d/browser/components/screenshots/ScreenshotsOverlayChild.sys.mjs#809 * @param {Number} startX The starting X coordinate. The left edge of the overlay rect. * @param {Number} startY The starting Y coordinate. The top edge of the overlay rect. * @param {Number} endX The end X coordinate. The right edge of the overlay rect. * @param {Number} endY The end Y coordinate. The bottom edge of the overlay rect.
*/
async dragOverlay(
startX,
startY,
endX,
endY,
expectedStartingState = "crosshairs"
) {
await this.assertStateChange(expectedStartingState);
mouse.down(startX, startY);
await this.waitForStateChange(["draggingReady", "resizing"]); Assert.ok(true, "The overlay is in the draggingReady or resizing state");
Assert.ok(true, "The overlay is in the dragging or resizing state"); // We intentionally turn off this a11y check, because the following mouse // event is emitted at the end of the dragging event. Its keyboard // accessible alternative is provided and tested elsewhere, therefore // this rule check shall be ignored by a11y_checks suite.
AccessibilityUtils.setEnv({ mustHaveAccessibleRule: false });
mouse.up(endX, endY);
// Sometimes (read intermittently) the scroll width/height will be // off by the width/height of the scrollbar when we are expecting the // page to be scrolled to the very end. To mitigate this, we check // that the below differences are within the scrollbar width/height. return (
(content.window.scrollX === xPos ||
isCloseEnough(
cDims.clientWidth + content.window.scrollX,
cDims.scrollWidth,
scrollbarWidth.value + 1
)) &&
(content.window.scrollY === yPos ||
isCloseEnough(
cDims.clientHeight + content.window.scrollY,
cDims.scrollHeight,
scrollbarHeight.value + 1
))
);
}, `Waiting for window to scroll to ${xPos}, ${yPos}`);
}
);
}
async hoverTestPageElement(elementId = "testPageElement") {
let rect = await this.getTestPageElementRect(elementId);
let dims = await this.getContentDimensions();
let x = Math.floor(rect.x + dims.scrollX + rect.width / 2);
let y = Math.floor(rect.y + dims.scrollY + rect.height / 2);
async clickTestPageElement(elementId = "testPageElement") {
let rect = await this.getTestPageElementRect(elementId);
let dims = await this.getContentDimensions();
let x = Math.floor(rect.x + dims.scrollX + rect.width / 2);
let y = Math.floor(rect.y + dims.scrollY + rect.height / 2);
assertPanelNotVisible() {
info("assertPanelNotVisible, panel.hidden:" + this.panel?.hidden); Assert.ok(
!this.panel || BrowserTestUtils.isHidden(this.panel), "Screenshots panel is not visible"
);
}
/** * Copied from screenshots extension * Returns a promise that resolves when the clipboard data has changed * Otherwise rejects
*/
waitForRawClipboardChange(epectedWidth, expectedHeight, options = {}) { const initialClipboardData = Date.now().toString();
SpecialPowers.clipboardCopyString(initialClipboardData);
return TestUtils.waitForCondition(
async () => {
let data; try {
data = await this.getImageSizeAndColorFromClipboard(options);
} catch (e) {
console.log("Failed to get image/png clipboard data:", e); returnfalse;
} if (
data &&
initialClipboardData !== data &&
data.height === expectedHeight &&
data.width === epectedWidth
) { return data;
}
info(`Got from clipboard: ${JSON.stringify(data, null, 2)}`); returnfalse;
}, "Waiting for screenshot to copy to clipboard",
200
);
}
/** * Gets the client and scroll demensions on the window * @returns { Object } * clientHeight The visible height * clientWidth The visible width * scrollHeight The scrollable height * scrollWidth The scrollable width * scrollX The scroll x position * scrollY The scroll y position
*/
getContentDimensions() { return SpecialPowers.spawn(this.browser, [], async function () {
let {
innerWidth,
innerHeight,
scrollMaxX,
scrollMaxY,
scrollX,
scrollY,
scrollMinX,
scrollMinY,
} = content.window;
let scrollWidth = innerWidth + scrollMaxX - scrollMinX;
let scrollHeight = innerHeight + scrollMaxY - scrollMinY;
let clientHeight = innerHeight;
let clientWidth = innerWidth;
/** * Copied from screenshots extension * A helper that returns the size of the image that was just put into the clipboard by the * :screenshot command. * @return The {width, height, color} dimension and color object.
*/
async getImageSizeAndColorFromClipboard(options = {}) {
let flavor = "image/png";
let image = getRawClipboardData(flavor); if (!image) { returnfalse;
}
// Due to the differences in how images could be stored in the clipboard the // checks below are needed. The clipboard could already provide the image as // byte streams or as image container. If it's not possible obtain a // byte stream, the function throws.
// We are going to load the image in the content page to measure its size. // We don't want to insert the image directly in the browser's document // which could mess all sorts of things up return SpecialPowers.spawn( this.browser,
[buffer, options],
async function (_buffer, _options) { const img = content.document.createElement("img"); const loaded = new Promise(r => {
img.addEventListener("load", r, { once: true });
}); const url = content.URL.createObjectURL( new Blob([_buffer], { type: "image/png" })
);
/** * Get the raw clipboard data * @param flavor Type of data to get from clipboard * @returns The data from the clipboard
*/
function getRawClipboardData(flavor) { const whichClipboard = Services.clipboard.kGlobalClipboard; const xferable = Cc["@mozilla.org/widget/transferable;1"].createInstance(
Ci.nsITransferable
);
xferable.init(null);
xferable.addDataFlavor(flavor);
Services.clipboard.getData(
xferable,
whichClipboard,
SpecialPowers.wrap(window).browsingContext.currentWindowContext
);
let data = {}; try { // xferable.getTransferData(flavor, data);
xferable.getAnyTransferData({}, data);
info(JSON.stringify(data, null, 2));
} catch (e) {
info(e);
}
data = data.value || null; return data;
}
/** * Synthesize a mouse event on an element * in the viewport. * * @param {String} selector: The node selector to get the node target for the event. * @param {number} x * @param {number} y * @param {object} options: Options that will be passed to BrowserTestUtils.synthesizeMouse
*/
async function safeSynthesizeMouseEventInContentPage(
selector,
x,
y,
options = {},
browser
) {
let context; if (!browser) {
context = gBrowser.selectedBrowser.browsingContext;
} else {
context = browser.browsingContext;
}
await BrowserTestUtils.synthesizeMouse(selector, x, y, options, context);
}
/** * Synthesize a key event on an element * in the viewport. * * @param {string} key The key * @param {object} options: Options that will be passed to BrowserTestUtils.synthesizeKey
*/
async function safeSynthesizeKeyEventInContentPage(aKey, options, browser) {
let context; if (!browser) {
context = gBrowser.selectedBrowser.browsingContext;
} else {
context = browser.browsingContext;
}
await BrowserTestUtils.synthesizeKey(aKey, options, context);
}
/** * Synthesize a touch event on an element * in the viewport. * * @param {String} selector: The node selector to get the node target for the event. * @param {number} x * @param {number} y * @param {object} options: Options that will be passed to BrowserTestUtils.synthesizeTouch
*/
async function safeSynthesizeTouchEventInContentPage(
selector,
x,
y,
options = {},
browser
) {
let context; if (!browser) {
context = gBrowser.selectedBrowser.browsingContext;
} else {
context = browser.browsingContext;
}
await BrowserTestUtils.synthesizeTouch(selector, x, y, options, context);
}
add_setup(async () => {
CustomizableUI.addWidgetToArea( "screenshot-button",
CustomizableUI.AREA_NAVBAR,
0
);
let screenshotBtn = document.getElementById("screenshot-button");
Assert.ok(screenshotBtn, "The screenshots button was added to the nav bar");
registerCleanupFunction(async () => {
info(`downloads panel should be visible: ${DownloadsPanel.isPanelShowing}`); if (DownloadsPanel.isPanelShowing) {
let hiddenPromise = BrowserTestUtils.waitForEvent(
DownloadsPanel.panel, "popuphidden"
);
DownloadsPanel.hidePanel();
await hiddenPromise;
info(
`downloads panel should not be visible: ${DownloadsPanel.isPanelShowing}`
);
}
});
});
function getContentDevicePixelRatio(browser) { return SpecialPowers.spawn(browser, [], async function () { return content.window.devicePixelRatio;
});
}
async function clearAllTelemetryEvents() { // Clear everything.
info("Clearing all telemetry events");
await TestUtils.waitForCondition(() => {
Services.telemetry.clearEvents();
let events = Services.telemetry.snapshotEvents(
Ci.nsITelemetry.DATASET_PRERELEASE_CHANNELS, true
);
let content = events.content;
let parent = events.parent;
async function assertScreenshotsEvents(
expectedEvents,
process = "parent",
clearEvents = true
) {
info(`Expected events: ${JSON.stringify(expectedEvents, null, 2)}`); // Make sure we have recorded the correct number of events
await waitForScreenshotsEventCount(expectedEvents.length, process);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.