summaryrefslogtreecommitdiffstats
path: root/browser/components/screenshots/tests
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/screenshots/tests')
-rw-r--r--browser/components/screenshots/tests/browser/browser.ini25
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_drag_scroll_test.js317
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js475
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_focus_test.js34
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_overlay_panel_sync.js82
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_page_unload.js72
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_short_page_test.js40
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js137
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_escape.js25
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js192
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_page_crash.js70
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_toggle_pref.js288
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_toolbar_button.js26
-rw-r--r--browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js374
-rw-r--r--browser/components/screenshots/tests/browser/head.js496
-rw-r--r--browser/components/screenshots/tests/browser/short-test-page.html11
-rw-r--r--browser/components/screenshots/tests/browser/test-page.html11
17 files changed, 2675 insertions, 0 deletions
diff --git a/browser/components/screenshots/tests/browser/browser.ini b/browser/components/screenshots/tests/browser/browser.ini
new file mode 100644
index 0000000000..47cafe5bb2
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser.ini
@@ -0,0 +1,25 @@
+[DEFAULT]
+support-files =
+ head.js
+ test-page.html
+ short-test-page.html
+
+prefs =
+ extensions.screenshots.disabled=false
+ screenshots.browser.component.enabled=true
+
+[browser_screenshots_drag_scroll_test.js]
+[browser_screenshots_drag_test.js]
+[browser_screenshots_focus_test.js]
+[browser_screenshots_overlay_panel_sync.js]
+[browser_screenshots_page_unload.js]
+[browser_screenshots_short_page_test.js]
+[browser_screenshots_test_downloads.js]
+[browser_screenshots_test_escape.js]
+[browser_screenshots_test_full_page.js]
+skip-if = (!debug && os == 'win' && os_version == '6.1') # Bug 1746281
+[browser_screenshots_test_page_crash.js]
+skip-if = !crashreporter
+[browser_screenshots_test_toggle_pref.js]
+[browser_screenshots_test_toolbar_button.js]
+[browser_screenshots_test_visible.js]
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_drag_scroll_test.js b/browser/components/screenshots/tests/browser/browser_screenshots_drag_scroll_test.js
new file mode 100644
index 0000000000..77d361b26b
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_drag_scroll_test.js
@@ -0,0 +1,317 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * Test that screenshots overlay covers the entire page
+ */
+add_task(async function test_overlayCoversEntirePage() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let dimensions = await helper.getSelectionLayerDimensions();
+ info(JSON.stringify(dimensions));
+ is(
+ dimensions.scrollWidth,
+ 4000,
+ "The overlay spans the entire width of the page"
+ );
+
+ is(
+ dimensions.scrollHeight,
+ 4000,
+ "The overlay spans the entire height of the page"
+ );
+ }
+ );
+});
+
+/**
+ * Test dragging screenshots box off top left of screen
+ */
+add_task(async function test_draggingBoxOffTopLeft() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ let startX = 10;
+ let startY = 10;
+ let endX = 500;
+ let endY = 500;
+ await helper.dragOverlay(startX, startY, endX, endY);
+
+ mouse.down(
+ startX + Math.floor((endX - startX) / 2),
+ startY + Math.floor((endY - startY) / 2)
+ );
+
+ await helper.waitForStateChange("resizing");
+ let state = await helper.getOverlayState();
+ is(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(10, 10);
+
+ // We moved the box to the edge of the screen so we need to wait until the box size is updated
+ await helper.waitForSelectionBoxSizeChange(490);
+
+ let dimensions = await helper.getSelectionBoxDimensions();
+
+ is(dimensions.x1, 0, "The box x1 position is now 0");
+ is(dimensions.y1, 0, "The box y1 position is now 0");
+ is(dimensions.width, 255, "The box width is now 255");
+ is(dimensions.height, 255, "The box height is now 255");
+
+ mouse.move(
+ startX + Math.floor((endX - startX) / 2),
+ startY + Math.floor((endY - startY) / 2)
+ );
+
+ mouse.up(
+ startX + Math.floor((endX - startX) / 2),
+ startY + Math.floor((endY - startY) / 2)
+ );
+
+ // We moved the box off the edge of the screen so we need to wait until the box size is updated
+ await helper.waitForSelectionBoxSizeChange(255);
+
+ dimensions = await helper.getSelectionBoxDimensions();
+
+ is(dimensions.x1, 10, "The box x1 position is now 10 again");
+ is(dimensions.y1, 10, "The box y1 position is now 10 again");
+ is(dimensions.width, 490, "The box width is now 490 again");
+ is(dimensions.height, 490, "The box height is now 490 again");
+ }
+ );
+});
+
+/**
+ * Test dragging screenshots box off bottom right of screen
+ */
+add_task(async function test_draggingBoxOffBottomRight() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ info(JSON.stringify(contentInfo));
+ ok(contentInfo, "Got dimensions back from the content");
+
+ await helper.scrollContentWindow(4000, 4000);
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ let startX = contentInfo.scrollWidth - 500;
+ let startY = contentInfo.scrollHeight - 500;
+ let endX = contentInfo.scrollWidth - 20;
+ let endY = contentInfo.scrollHeight - 20;
+
+ await helper.dragOverlay(startX, startY, endX, endY);
+
+ // move box off the bottom right of the screen
+ mouse.down(
+ startX + Math.floor((endX - startX) / 2),
+ startY + Math.floor((endY - startY) / 2)
+ );
+ mouse.move(
+ startX + 50 + Math.floor((endX - startX) / 2),
+ startY + 50 + Math.floor((endY - startY) / 2)
+ );
+
+ await helper.waitForStateChange("resizing");
+ let state = await helper.getOverlayState();
+ is(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(endX, endY);
+
+ // We moved the box to the edge of the screen so we need to wait until the box size is updated
+ await helper.waitForSelectionBoxSizeChange(480);
+
+ let dimensions = await helper.getSelectionBoxDimensions();
+
+ is(dimensions.x1, startX + 240, "The box x1 position is now 3748");
+ is(dimensions.y1, startY + 240, "The box y1 position is now 3756");
+ is(dimensions.width, 252, "The box width is now 252");
+ is(dimensions.height, 244, "The box height is now 244");
+
+ mouse.move(
+ startX + Math.floor((endX - startX) / 2),
+ startY + Math.floor((endY - startY) / 2)
+ );
+
+ mouse.up(
+ startX + Math.floor((endX - startX) / 2),
+ startY + Math.floor((endY - startY) / 2)
+ );
+
+ // We moved the box off the edge of the screen so we need to wait until the box size is updated
+ await helper.waitForSelectionBoxSizeChange(252);
+
+ dimensions = await helper.getSelectionBoxDimensions();
+
+ is(dimensions.x1, startX, "The box x1 position is now 3508 again");
+ is(dimensions.y1, startY, "The box y1 position is now 3516 again");
+ is(dimensions.width, 480, "The box width is now 480 again");
+ is(dimensions.height, 480, "The box height is now 480 again");
+ }
+ );
+});
+
+/**
+ * test scrolling while screenshots is open
+ */
+add_task(async function test_scrollingScreenshotsOpen() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ info(JSON.stringify(contentInfo));
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ let startX = 10;
+ let startY = 10;
+ let endX = 100;
+ let endY = 100;
+
+ await helper.dragOverlay(startX, startY, endX, endY);
+
+ let scrollX = 1000;
+ let scrollY = 1000;
+
+ await helper.scrollContentWindow(scrollX, scrollY);
+
+ let dimensions = await helper.getSelectionBoxDimensions();
+
+ is(dimensions.x1, startX, "The box x1 position is 10");
+ is(dimensions.y1, startY, "The box y1 position is 10");
+ is(dimensions.width, endX - startX, "The box width is now 90");
+ is(dimensions.height, endY - startY, "The box height is now 90");
+
+ // reset screenshots box
+ mouse.click(scrollX + startX, scrollY + endY);
+ await helper.waitForStateChange("crosshairs");
+
+ await helper.dragOverlay(
+ scrollX + startX,
+ scrollY + startY,
+ scrollX + endX,
+ scrollY + endY
+ );
+
+ await helper.scrollContentWindow(0, 0);
+
+ dimensions = await helper.getSelectionBoxDimensions();
+
+ is(dimensions.x1, scrollX + startX, "The box x1 position is 1010");
+ is(dimensions.y1, scrollY + startY, "The box y1 position is 1010");
+ is(dimensions.width, endX - startX, "The box width is now 90");
+ is(dimensions.height, endY - startY, "The box height is now 90");
+
+ // reset screenshots box
+ mouse.click(10, 10);
+ await helper.waitForStateChange("crosshairs");
+
+ await helper.dragOverlay(
+ startX,
+ startY,
+ contentInfo.clientWidth - 10,
+ contentInfo.clientHeight - 10
+ );
+
+ await helper.scrollContentWindow(
+ contentInfo.clientWidth - 20,
+ contentInfo.clientHeight - 20
+ );
+
+ mouse.down(contentInfo.clientWidth - 10, contentInfo.clientHeight - 10);
+
+ await helper.waitForStateChange("resizing");
+
+ mouse.move(
+ contentInfo.clientWidth * 2 - 30,
+ contentInfo.clientHeight * 2 - 30
+ );
+
+ mouse.up(
+ contentInfo.clientWidth * 2 - 30,
+ contentInfo.clientHeight * 2 - 30
+ );
+
+ await helper.waitForStateChange("selected");
+
+ dimensions = await helper.getSelectionLayerDimensions();
+ info(JSON.stringify(dimensions));
+ is(dimensions.boxLeft, startX, "The box left is 10");
+ is(dimensions.boxTop, startY, "The box top is 10");
+ is(
+ dimensions.boxRight,
+ contentInfo.clientWidth * 2 - 30,
+ "The box right is 2 x clientWidth - 30"
+ );
+ is(
+ dimensions.boxBottom,
+ contentInfo.clientHeight * 2 - 30,
+ "The box right is 2 x clientHeight - 30"
+ );
+ is(
+ dimensions.boxWidth,
+ contentInfo.clientWidth * 2 - 40,
+ "The box right is 2 x clientWidth - 40"
+ );
+ is(
+ dimensions.boxHeight,
+ contentInfo.clientHeight * 2 - 40,
+ "The box right is 2 x clientHeight - 40"
+ );
+ is(
+ dimensions.scrollWidth,
+ 4000,
+ "The overlay spans the entire width of the page"
+ );
+ is(
+ dimensions.scrollHeight,
+ 4000,
+ "The overlay spans the entire height of the page"
+ );
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js b/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js
new file mode 100644
index 0000000000..aba38dccc0
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_drag_test.js
@@ -0,0 +1,475 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * This function drags to a 490x490 area and copies to the clipboard
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ helper.clickCopyButton();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+
+ let expected = Math.floor(
+ 490 * (await getContentDevicePixelRatio(browser))
+ );
+
+ Assert.equal(
+ result.width,
+ expected,
+ `The copied image from the overlay is ${expected}px in width`
+ );
+ Assert.equal(
+ result.height,
+ expected,
+ `The copied image from the overlay is ${expected}px in height`
+ );
+ }
+ );
+});
+
+/**
+ * This function drags a 1.5 zoomed browser to a 490x490 area and copies to the clipboard
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ const zoom = 1.5;
+ let helper = new ScreenshotsHelper(browser);
+ helper.zoomBrowser(zoom);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ helper.clickCopyButton();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+ result.zoom = zoom;
+ result.devicePixelRatio = window.devicePixelRatio;
+ result.contentDevicePixelRatio = await getContentDevicePixelRatio(
+ browser
+ );
+
+ info("result: " + JSON.stringify(result, null, 2));
+
+ let expected = Math.floor(
+ 490 * (await getContentDevicePixelRatio(browser))
+ );
+
+ Assert.equal(
+ result.width,
+ expected,
+ `The copied image from the overlay is ${expected}px in width`
+ );
+ Assert.equal(
+ result.height,
+ expected,
+ `The copied image from the overlay is ${expected}px in height`
+ );
+ }
+ );
+});
+
+/**
+ * This function drags an area and clicks elsewhere
+ * on the overlay to go back to the crosshairs state
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 100, 100);
+
+ // click outside overlay
+ mouse.click(200, 200);
+
+ await helper.waitForStateChange("crosshairs");
+ let state = await helper.getOverlayState();
+ Assert.equal(state, "crosshairs", "The state is back to crosshairs");
+ }
+ );
+});
+
+/**
+ * This function drags an area and clicks the
+ * cancel button to cancel the overlay
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 300, 300);
+
+ helper.clickCancelButton();
+
+ await helper.waitForOverlayClosed();
+
+ ok(!(await helper.isOverlayInitialized()), "Overlay is not initialized");
+ }
+ );
+});
+
+/**
+ * This function drags a 490x490 area and moves it along the edges
+ * and back to the center to confirm that the original size is preserved
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let startX = 10;
+ let startY = 10;
+ let endX = 500;
+ let endY = 500;
+
+ mouse.down(
+ Math.floor((endX - startX) / 2),
+ Math.floor((endY - startY) / 2)
+ );
+
+ await helper.waitForStateChange("resizing");
+ let state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(10, 10);
+
+ mouse.move(contentInfo.clientWidth - 10, contentInfo.clientHeight - 10);
+
+ mouse.up(
+ Math.floor((endX - startX) / 2),
+ Math.floor((endY - startY) / 2)
+ );
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ helper.clickCopyButton();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+
+ let expected = Math.floor(
+ 490 * (await getContentDevicePixelRatio(browser))
+ );
+
+ Assert.equal(
+ result.width,
+ expected,
+ `The copied image from the overlay is ${expected}px in width`
+ );
+ Assert.equal(
+ result.height,
+ expected,
+ `The copied image from the overlay is ${expected}px in height`
+ );
+ }
+ );
+});
+
+/**
+ * This function drags a 490x490 area and resizes it to a 300x300 area
+ * with the 4 sides of the box
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let startX = 10;
+ let startY = 10;
+ let endX = 500;
+ let endY = 500;
+
+ let x = Math.floor((endX - startX) / 2);
+
+ // drag top
+ mouse.down(x, 10);
+
+ await helper.waitForStateChange("resizing");
+ let state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(x, 100);
+ mouse.up(x, 100);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ // drag bottom
+ mouse.down(x, 500);
+
+ await helper.waitForStateChange("resizing");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(x, 400);
+ mouse.up(x, 400);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ // drag right
+ let y = Math.floor((endY - startY) / 2);
+ mouse.down(500, y);
+
+ await helper.waitForStateChange("resizing");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(400, y);
+ mouse.up(400, y);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ // drag left
+ mouse.down(10, y);
+
+ await helper.waitForStateChange("resizing");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(100, y);
+ mouse.up(100, y);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ helper.endX = 400;
+ helper.endY = 400;
+
+ helper.clickCopyButton();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+
+ let expected = Math.floor(
+ 300 * (await getContentDevicePixelRatio(browser))
+ );
+
+ Assert.equal(
+ result.width,
+ expected,
+ `The copied image from the overlay is ${expected}px in width`
+ );
+ Assert.equal(
+ result.height,
+ expected,
+ `The copied image from the overlay is ${expected}px in height`
+ );
+ }
+ );
+});
+
+/**
+ * This function drags a 490x490 area and resizes it to a 300x300 area
+ * with the 4 corners of the box
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ // drag topright
+ mouse.down(500, 10);
+
+ await helper.waitForStateChange("resizing");
+ let state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(450, 50);
+ mouse.up(450, 50);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ // drag bottomright
+ mouse.down(450, 500);
+
+ await helper.waitForStateChange("resizing");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(400, 450);
+ mouse.up(400, 450);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ // drag bottomleft
+ mouse.down(10, 450);
+
+ await helper.waitForStateChange("resizing");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(50, 400);
+ mouse.up(50, 400);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ // drag topleft
+ mouse.down(50, 50);
+
+ await helper.waitForStateChange("resizing");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "resizing", "The overlay is in the resizing state");
+
+ mouse.move(100, 100);
+ mouse.up(100, 100);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ helper.endX = 400;
+ helper.endY = 400;
+
+ helper.clickCopyButton();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+
+ let expected = Math.floor(
+ 300 * (await getContentDevicePixelRatio(browser))
+ );
+
+ Assert.equal(
+ result.width,
+ expected,
+ `The copied image from the overlay is ${expected}px in width`
+ );
+ Assert.equal(
+ result.height,
+ expected,
+ `The copied image from the overlay is ${expected}px in height`
+ );
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_focus_test.js b/browser/components/screenshots/tests/browser/browser_screenshots_focus_test.js
new file mode 100644
index 0000000000..d992327128
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_focus_test.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function testPanelFocused() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ EventUtils.synthesizeKey("KEY_Tab");
+
+ let screenshotsButtons = gBrowser.selectedBrowser.ownerDocument
+ .querySelector("#screenshotsPagePanel")
+ .querySelector("screenshots-buttons").shadowRoot;
+
+ let focusedElement = screenshotsButtons.querySelector(".visible-page");
+
+ is(
+ focusedElement,
+ screenshotsButtons.activeElement,
+ "Visible button is focused"
+ );
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_overlay_panel_sync.js b/browser/components/screenshots/tests/browser/browser_screenshots_overlay_panel_sync.js
new file mode 100644
index 0000000000..b66a4d2b57
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_overlay_panel_sync.js
@@ -0,0 +1,82 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+async function waitOnTabSwitch() {
+ // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
+ await new Promise(r => setTimeout(r, 300));
+}
+
+add_task(async function test_overlay_and_panel_state() {
+ let tab1 = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_PAGE);
+
+ let screenshotsTab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ TEST_PAGE
+ );
+ let browser = screenshotsTab.linkedBrowser;
+
+ let helper = new ScreenshotsHelper(browser);
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ helper.assertPanelVisible();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ await helper.waitForStateChange("selected");
+ let state = await helper.getOverlayState();
+ is(state, "selected", "The overlay is in the selected state");
+
+ helper.assertPanelNotVisible();
+
+ mouse.click(600, 600);
+
+ await helper.waitForStateChange("crosshairs");
+ state = await helper.getOverlayState();
+ is(state, "crosshairs", "The overlay is in the crosshairs state");
+
+ await helper.waitForOverlay();
+
+ helper.assertPanelVisible();
+
+ await BrowserTestUtils.switchTab(gBrowser, tab1);
+ await BrowserTestUtils.switchTab(gBrowser, screenshotsTab);
+
+ await helper.waitForOverlayClosed();
+
+ Assert.ok(!(await helper.isOverlayInitialized()), "Overlay is closed");
+ helper.assertPanelNotVisible();
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ helper.assertPanelVisible();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ await helper.waitForStateChange("selected");
+ state = await helper.getOverlayState();
+ is(state, "selected", "The overlay is in the selected state");
+
+ await BrowserTestUtils.switchTab(gBrowser, tab1);
+ await BrowserTestUtils.switchTab(gBrowser, screenshotsTab);
+
+ Assert.ok(await helper.isOverlayInitialized(), "Overlay is open");
+ helper.assertPanelNotVisible();
+ state = await helper.getOverlayState();
+ is(state, "selected", "The overlay is in the selected state");
+
+ helper.triggerUIFromToolbar();
+ await helper.waitForOverlayClosed();
+
+ Assert.ok(!(await helper.isOverlayInitialized()), "Overlay is closed");
+ helper.assertPanelNotVisible();
+
+ gBrowser.removeTab(tab1);
+ gBrowser.removeTab(screenshotsTab);
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_page_unload.js b/browser/components/screenshots/tests/browser/browser_screenshots_page_unload.js
new file mode 100644
index 0000000000..dea97978e4
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_page_unload.js
@@ -0,0 +1,72 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ await SpecialPowers.spawn(browser, [TEST_PAGE], url => {
+ let a = content.document.createElement("a");
+ a.id = "clickMe";
+ a.href = url;
+ a.textContent = "Click me to unload page";
+ content.document.querySelector("body").appendChild(a);
+ });
+
+ let helper = new ScreenshotsHelper(browser);
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ await ContentTask.spawn(browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ Assert.ok(screenshotsChild._overlay._initialized, "The overlay exists");
+ });
+
+ await SpecialPowers.spawn(browser, [], () => {
+ content.document.querySelector("#clickMe").click();
+ });
+
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_hidden(panel);
+ }
+ );
+ ok(
+ BrowserTestUtils.is_hidden(panel),
+ "Panel buttons are hidden after page unload"
+ );
+
+ await ContentTask.spawn(browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ Assert.ok(
+ !screenshotsChild._overlay._initialized,
+ "The overlay doesn't exist"
+ );
+ });
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_short_page_test.js b/browser/components/screenshots/tests/browser/browser_screenshots_short_page_test.js
new file mode 100644
index 0000000000..5772eeb7c3
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_short_page_test.js
@@ -0,0 +1,40 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/**
+ * This test ensures the overlay is covering the entire window event thought the body is only 100px by 100px
+ */
+add_task(async function() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: SHORT_TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let dimensions = await helper.getSelectionLayerDimensions();
+ Assert.equal(
+ dimensions.scrollWidth,
+ contentInfo.clientWidth,
+ "The overlay spans the width of the window"
+ );
+
+ Assert.equal(
+ dimensions.scrollHeight,
+ contentInfo.clientHeight,
+ "The overlay spans the height of the window"
+ );
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js
new file mode 100644
index 0000000000..45dc960fc6
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_downloads.js
@@ -0,0 +1,137 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const MockFilePicker = SpecialPowers.MockFilePicker;
+
+add_setup(async function() {
+ let tmpDir = PathUtils.join(
+ PathUtils.tempDir,
+ "testsavedir" + Math.floor(Math.random() * 2 ** 32)
+ );
+ // Create this dir if it doesn't exist (ignores existing dirs)
+ await IOUtils.makeDirectory(tmpDir);
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.download.start_downloads_in_tmp_dir", true],
+ ["browser.helperApps.deleteTempFileOnExit", true],
+ ["browser.download.folderList", 2],
+ ["browser.download.dir", tmpDir],
+ ],
+ });
+
+ MockFilePicker.init(window);
+ MockFilePicker.useAnyFile();
+ MockFilePicker.returnValue = MockFilePicker.returnOK;
+
+ registerCleanupFunction(async () => {
+ Services.prefs.clearUserPref("browser.download.dir");
+ Services.prefs.clearUserPref("browser.download.folderList");
+
+ MockFilePicker.cleanup();
+ });
+});
+
+function waitForFilePicker() {
+ return new Promise(resolve => {
+ MockFilePicker.showCallback = () => {
+ MockFilePicker.showCallback = null;
+ ok(true, "Saw the file picker");
+ resolve();
+ };
+ });
+}
+
+add_task(async function test_download_without_filepicker() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.download.useDownloadDir", true]],
+ });
+
+ let publicDownloads = await Downloads.getList(Downloads.PUBLIC);
+ // First ensure we catch the download finishing.
+ let downloadFinishedPromise = new Promise(resolve => {
+ publicDownloads.addView({
+ onDownloadChanged(download) {
+ info("Download changed!");
+ if (download.succeeded || download.error) {
+ info("Download succeeded or errored");
+ publicDownloads.removeView(this);
+ resolve(download);
+ }
+ },
+ });
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ helper.triggerUIFromToolbar();
+ await helper.waitForOverlay();
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ helper.clickDownloadButton();
+
+ info("wait for download to finish");
+ let download = await downloadFinishedPromise;
+
+ ok(download.succeeded, "Download should succeed");
+
+ await publicDownloads.removeFinished();
+ }
+ );
+});
+
+add_task(async function test_download_with_filepicker() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.download.useDownloadDir", false]],
+ });
+
+ let publicDownloads = await Downloads.getList(Downloads.PUBLIC);
+ // First ensure we catch the download finishing.
+ let downloadFinishedPromise = new Promise(resolve => {
+ publicDownloads.addView({
+ onDownloadChanged(download) {
+ info("Download changed!");
+ if (download.succeeded || download.error) {
+ info("Download succeeded or errored");
+ publicDownloads.removeView(this);
+ resolve(download);
+ }
+ },
+ });
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ helper.triggerUIFromToolbar();
+ await helper.waitForOverlay();
+ await helper.dragOverlay(10, 10, 500, 500);
+
+ let filePicker = waitForFilePicker();
+
+ helper.clickDownloadButton();
+
+ await filePicker;
+ ok(true, "Export file picker opened");
+
+ info("wait for download to finish");
+ let download = await downloadFinishedPromise;
+
+ ok(download.succeeded, "Download should succeed");
+
+ await publicDownloads.removeFinished();
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_escape.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_escape.js
new file mode 100644
index 0000000000..09605fd316
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_escape.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_fullpageScreenshot() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ EventUtils.synthesizeKey("KEY_Escape");
+
+ await helper.waitForOverlayClosed();
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js
new file mode 100644
index 0000000000..cf83537d87
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_full_page.js
@@ -0,0 +1,192 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_fullpageScreenshot() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ let screenshotReady = TestUtils.topicObserved(
+ "screenshots-preview-ready"
+ );
+
+ // click the full page button in panel
+ let visiblePage = panel
+ .querySelector("screenshots-buttons")
+ .shadowRoot.querySelector(".full-page");
+ visiblePage.click();
+
+ let dialog = helper.getDialog();
+
+ await screenshotReady;
+
+ let copyButton = dialog._frame.contentDocument.querySelector(
+ ".highlight-button-copy"
+ );
+ ok(copyButton, "Got the copy button");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ // click copy button on dialog box
+ copyButton.click();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+ info("result: " + JSON.stringify(result, null, 2));
+ info("contentInfo: " + JSON.stringify(contentInfo, null, 2));
+
+ Assert.equal(
+ contentInfo.scrollWidth,
+ result.width,
+ "Widths should be equal"
+ );
+
+ Assert.equal(
+ contentInfo.scrollHeight,
+ result.height,
+ "Heights should be equal"
+ );
+
+ // top left
+ Assert.equal(111, result.color.topLeft[0], "R color value");
+ Assert.equal(111, result.color.topLeft[1], "G color value");
+ Assert.equal(111, result.color.topLeft[2], "B color value");
+
+ // top right
+ Assert.equal(55, result.color.topRight[0], "R color value");
+ Assert.equal(155, result.color.topRight[1], "G color value");
+ Assert.equal(155, result.color.topRight[2], "B color value");
+
+ // bottom left
+ Assert.equal(105, result.color.bottomLeft[0], "R color value");
+ Assert.equal(55, result.color.bottomLeft[1], "G color value");
+ Assert.equal(105, result.color.bottomLeft[2], "B color value");
+
+ // bottom right
+ Assert.equal(52, result.color.bottomRight[0], "R color value");
+ Assert.equal(127, result.color.bottomRight[1], "G color value");
+ Assert.equal(152, result.color.bottomRight[2], "B color value");
+ }
+ );
+});
+
+add_task(async function test_fullpageScreenshotScrolled() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ await SpecialPowers.spawn(browser, [], () => {
+ content.scrollTo(0, 2008);
+ });
+
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ let screenshotReady = TestUtils.topicObserved(
+ "screenshots-preview-ready"
+ );
+
+ // click the full page button in panel
+ let visiblePage = panel
+ .querySelector("screenshots-buttons")
+ .shadowRoot.querySelector(".full-page");
+ visiblePage.click();
+
+ let dialog = helper.getDialog();
+
+ await screenshotReady;
+
+ let copyButton = dialog._frame.contentDocument.querySelector(
+ ".highlight-button-copy"
+ );
+ ok(copyButton, "Got the copy button");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ // click copy button on dialog box
+ copyButton.click();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+ info("result: " + JSON.stringify(result, null, 2));
+ info("contentInfo: " + JSON.stringify(contentInfo, null, 2));
+
+ Assert.equal(
+ contentInfo.scrollWidth,
+ result.width,
+ "Widths should be equal"
+ );
+
+ Assert.equal(
+ contentInfo.scrollHeight,
+ result.height,
+ "Heights should be equal"
+ );
+
+ // top left
+ Assert.equal(111, result.color.topLeft[0], "R color value");
+ Assert.equal(111, result.color.topLeft[1], "G color value");
+ Assert.equal(111, result.color.topLeft[2], "B color value");
+
+ // top right
+ Assert.equal(55, result.color.topRight[0], "R color value");
+ Assert.equal(155, result.color.topRight[1], "G color value");
+ Assert.equal(155, result.color.topRight[2], "B color value");
+
+ // bottom left
+ Assert.equal(105, result.color.bottomLeft[0], "R color value");
+ Assert.equal(55, result.color.bottomLeft[1], "G color value");
+ Assert.equal(105, result.color.bottomLeft[2], "B color value");
+
+ // bottom right
+ Assert.equal(52, result.color.bottomRight[0], "R color value");
+ Assert.equal(127, result.color.bottomRight[1], "G color value");
+ Assert.equal(152, result.color.bottomRight[2], "B color value");
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_page_crash.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_page_crash.js
new file mode 100644
index 0000000000..ab5afe49a1
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_page_crash.js
@@ -0,0 +1,70 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_fullpageScreenshot() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+
+ // click toolbar button so UI shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ await ContentTask.spawn(browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ Assert.ok(screenshotsChild._overlay._initialized, "The overlay exists");
+ });
+
+ let waitForPanelHide = BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_hidden(panel);
+ }
+ );
+
+ await BrowserTestUtils.crashFrame(browser);
+
+ await waitForPanelHide;
+ ok(
+ BrowserTestUtils.is_hidden(panel),
+ "Panel buttons are hidden after page crash"
+ );
+
+ await ContentTask.spawn(browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ Assert.ok(!screenshotsChild._overlay, "The overlay doesn't exist");
+ });
+
+ let tab = gBrowser.getTabForBrowser(browser);
+
+ SessionStore.reviveCrashedTab(tab);
+
+ ok(
+ BrowserTestUtils.is_hidden(panel),
+ "Panel buttons are hidden after page crash"
+ );
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_toggle_pref.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_toggle_pref.js
new file mode 100644
index 0000000000..b778c63163
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_toggle_pref.js
@@ -0,0 +1,288 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { sinon } = ChromeUtils.import("resource://testing-common/Sinon.jsm");
+const { XPCOMUtils } = ChromeUtils.importESModule(
+ "resource://gre/modules/XPCOMUtils.sys.mjs"
+);
+
+ChromeUtils.defineESModuleGetters(this, {
+ ScreenshotsUtils: "resource:///modules/ScreenshotsUtils.sys.mjs",
+});
+XPCOMUtils.defineLazyGetter(this, "ExtensionManagement", () => {
+ const { Management } = ChromeUtils.import(
+ "resource://gre/modules/Extension.jsm"
+ );
+ return Management;
+});
+
+add_task(async function test() {
+ let observerSpy = sinon.spy();
+ let notifierSpy = sinon.spy();
+
+ let observerStub = sinon
+ .stub(ScreenshotsUtils, "observe")
+ .callsFake(observerSpy);
+ let notifierStub = sinon
+ .stub(ScreenshotsUtils, "notify")
+ .callsFake(function(window, type) {
+ notifierSpy();
+ ScreenshotsUtils.notify.wrappedMethod.apply(this, arguments);
+ });
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ function awaitExtensionEvent(eventName, id) {
+ return new Promise(resolve => {
+ let listener = (_eventName, ...args) => {
+ let extension = args[0];
+ if (_eventName === eventName && extension.id == id) {
+ ExtensionManagement.off(eventName, listener);
+ resolve();
+ }
+ };
+ ExtensionManagement.on(eventName, listener);
+ });
+ }
+ const SCREENSHOT_EXTENSION = "screenshots@mozilla.org";
+
+ let helper = new ScreenshotsHelper(browser);
+
+ ok(observerSpy.notCalled, "Observer not called");
+ helper.triggerUIFromToolbar();
+ Assert.equal(observerSpy.callCount, 1, "Observer function called once");
+
+ ok(notifierSpy.notCalled, "Notifier not called");
+ EventUtils.synthesizeKey("s", { accelKey: true, shiftKey: true });
+
+ await TestUtils.waitForCondition(() => notifierSpy.callCount == 1);
+ Assert.equal(notifierSpy.callCount, 1, "Notify function called once");
+
+ await TestUtils.waitForCondition(() => observerSpy.callCount == 2);
+ Assert.equal(observerSpy.callCount, 2, "Observer function called twice");
+
+ let menu = document.getElementById("contentAreaContextMenu");
+ let popupshown = BrowserTestUtils.waitForPopupEvent(menu, "shown");
+ EventUtils.synthesizeMouseAtCenter(document.body, {
+ type: "contextmenu",
+ });
+ await popupshown;
+ Assert.equal(menu.state, "open", "Context menu is open");
+
+ let popuphidden = BrowserTestUtils.waitForPopupEvent(menu, "hidden");
+ menu.activateItem(menu.querySelector("#context-take-screenshot"));
+ await popuphidden;
+
+ Assert.equal(observerSpy.callCount, 3, "Observer function called thrice");
+
+ const COMPONENT_PREF = "screenshots.browser.component.enabled";
+ await SpecialPowers.pushPrefEnv({
+ set: [[COMPONENT_PREF, false]],
+ });
+ ok(!Services.prefs.getBoolPref(COMPONENT_PREF), "Extension enabled");
+ await awaitExtensionEvent("ready", SCREENSHOT_EXTENSION);
+
+ helper.triggerUIFromToolbar();
+ Assert.equal(
+ observerSpy.callCount,
+ 3,
+ "Observer function still called thrice"
+ );
+
+ await SpecialPowers.spawn(
+ browser,
+ ["#firefox-screenshots-preselection-iframe"],
+ async function(iframeSelector) {
+ info(
+ `in waitForUIContent content function, iframeSelector: ${iframeSelector}`
+ );
+ let iframe;
+ await ContentTaskUtils.waitForCondition(() => {
+ iframe = content.document.querySelector(iframeSelector);
+ if (!iframe || !ContentTaskUtils.is_visible(iframe)) {
+ info("in waitForUIContent, no visible iframe yet");
+ return false;
+ }
+ return true;
+ });
+ // wait a frame for the screenshots UI to finish any init
+ await new content.Promise(res => content.requestAnimationFrame(res));
+ }
+ );
+
+ helper.triggerUIFromToolbar();
+ await SpecialPowers.spawn(
+ browser,
+ ["#firefox-screenshots-preselection-iframe"],
+ async function(iframeSelector) {
+ info(
+ `in waitForUIContent content function, iframeSelector: ${iframeSelector}`
+ );
+ let iframe;
+ await ContentTaskUtils.waitForCondition(() => {
+ iframe = content.document.querySelector(iframeSelector);
+ if (!iframe || !ContentTaskUtils.is_visible(iframe)) {
+ info("in waitForUIContent, no visible iframe yet");
+ return true;
+ }
+ return false;
+ });
+ // wait a frame for the screenshots UI to finish any init
+ await new content.Promise(res => content.requestAnimationFrame(res));
+ }
+ );
+
+ popupshown = BrowserTestUtils.waitForPopupEvent(menu, "shown");
+ EventUtils.synthesizeMouseAtCenter(document.body, {
+ type: "contextmenu",
+ });
+ await popupshown;
+ Assert.equal(menu.state, "open", "Context menu is open");
+
+ popuphidden = BrowserTestUtils.waitForPopupEvent(menu, "hidden");
+ menu.activateItem(menu.querySelector("#context-take-screenshot"));
+ await popuphidden;
+
+ Assert.equal(
+ observerSpy.callCount,
+ 3,
+ "Observer function still called thrice"
+ );
+
+ await SpecialPowers.spawn(
+ browser,
+ ["#firefox-screenshots-preselection-iframe"],
+ async function(iframeSelector) {
+ info(
+ `in waitForUIContent content function, iframeSelector: ${iframeSelector}`
+ );
+ let iframe;
+ await ContentTaskUtils.waitForCondition(() => {
+ iframe = content.document.querySelector(iframeSelector);
+ if (!iframe || !ContentTaskUtils.is_visible(iframe)) {
+ info("in waitForUIContent, no visible iframe yet");
+ return false;
+ }
+ return true;
+ });
+ // wait a frame for the screenshots UI to finish any init
+ await new content.Promise(res => content.requestAnimationFrame(res));
+ }
+ );
+
+ helper.triggerUIFromToolbar();
+ await SpecialPowers.spawn(
+ browser,
+ ["#firefox-screenshots-preselection-iframe"],
+ async function(iframeSelector) {
+ info(
+ `in waitForUIContent content function, iframeSelector: ${iframeSelector}`
+ );
+ let iframe;
+ await ContentTaskUtils.waitForCondition(() => {
+ iframe = content.document.querySelector(iframeSelector);
+ if (!iframe || !ContentTaskUtils.is_visible(iframe)) {
+ return true;
+ }
+ info("in waitForUIContent, iframe still visible");
+ info(iframe);
+ return false;
+ });
+ // wait a frame for the screenshots UI to finish any init
+ await new content.Promise(res => content.requestAnimationFrame(res));
+ }
+ );
+
+ let componentReady = TestUtils.topicObserved(
+ "screenshots-component-initialized"
+ );
+
+ await SpecialPowers.pushPrefEnv({
+ set: [[COMPONENT_PREF, true]],
+ });
+ ok(Services.prefs.getBoolPref(COMPONENT_PREF), "Component enabled");
+ // Needed for component to initialize
+ await componentReady;
+
+ helper.triggerUIFromToolbar();
+ Assert.equal(
+ observerSpy.callCount,
+ 4,
+ "Observer function called four times"
+ );
+
+ const SCREENSHOTS_PREF = "extensions.screenshots.disabled";
+ await SpecialPowers.pushPrefEnv({
+ set: [[SCREENSHOTS_PREF, true]],
+ });
+ ok(Services.prefs.getBoolPref(SCREENSHOTS_PREF), "Screenshots disabled");
+ }
+ );
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ const SCREENSHOTS_PREF = "extensions.screenshots.disabled";
+ ok(Services.prefs.getBoolPref(SCREENSHOTS_PREF), "Screenshots disabled");
+
+ ok(
+ document.getElementById("screenshot-button").disabled,
+ "Toolbar button disabled"
+ );
+
+ let menu = document.getElementById("contentAreaContextMenu");
+ let popupshown = BrowserTestUtils.waitForPopupEvent(menu, "shown");
+ EventUtils.synthesizeMouseAtCenter(document.body, {
+ type: "contextmenu",
+ });
+ await popupshown;
+ Assert.equal(menu.state, "open", "Context menu is open");
+
+ ok(
+ menu.querySelector("#context-take-screenshot").hidden,
+ "Take screenshot is not in context menu"
+ );
+
+ let popuphidden = BrowserTestUtils.waitForPopupEvent(menu, "hidden");
+ menu.hidePopup();
+ await popuphidden;
+
+ await SpecialPowers.pushPrefEnv({
+ set: [[SCREENSHOTS_PREF, false]],
+ });
+ ok(!Services.prefs.getBoolPref(SCREENSHOTS_PREF), "Screenshots enabled");
+ }
+ );
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ const SCREENSHOTS_PREF = "extensions.screenshots.disabled";
+ ok(!Services.prefs.getBoolPref(SCREENSHOTS_PREF), "Screenshots enabled");
+
+ let helper = new ScreenshotsHelper(browser);
+
+ helper.triggerUIFromToolbar();
+ Assert.equal(
+ observerSpy.callCount,
+ 5,
+ "Observer function called for the fifth time"
+ );
+ }
+ );
+
+ observerStub.restore();
+ notifierStub.restore();
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_toolbar_button.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_toolbar_button.js
new file mode 100644
index 0000000000..5ad7d32192
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_toolbar_button.js
@@ -0,0 +1,26 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function testScreenshotButtonDisabled() {
+ info("Test the Screenshots button in the panel");
+
+ let screenshotBtn = document.getElementById("screenshot-button");
+ Assert.ok(screenshotBtn, "The screenshots button was added to the nav bar");
+
+ await BrowserTestUtils.withNewTab("https://example.com/", () => {
+ Assert.equal(
+ screenshotBtn.disabled,
+ false,
+ "Screenshots button is enabled"
+ );
+ });
+ await BrowserTestUtils.withNewTab("about:home", () => {
+ Assert.equal(
+ screenshotBtn.disabled,
+ false,
+ "Screenshots button is still enabled on about pages"
+ );
+ });
+});
diff --git a/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js b/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js
new file mode 100644
index 0000000000..a23d07140e
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/browser_screenshots_test_visible.js
@@ -0,0 +1,374 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_visibleScreenshot() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+ let devicePixelRatio = await getContentDevicePixelRatio(browser);
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ await helper.waitForOverlay();
+
+ let screenshotReady = TestUtils.topicObserved(
+ "screenshots-preview-ready"
+ );
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+
+ // click the visible page button in panel
+ let visiblePageButton = panel
+ .querySelector("screenshots-buttons")
+ .shadowRoot.querySelector(".visible-page");
+ visiblePageButton.click();
+
+ let dialog = helper.getDialog();
+
+ await screenshotReady;
+
+ let copyButton = dialog._frame.contentDocument.querySelector(
+ ".highlight-button-copy"
+ );
+ ok(copyButton, "Got the copy button");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ // click copy button on dialog box
+ copyButton.click();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+ info("result: " + JSON.stringify(result, null, 2));
+ info("contentInfo: " + JSON.stringify(contentInfo, null, 2));
+
+ let expectedWidth = Math.floor(
+ devicePixelRatio * contentInfo.clientWidth
+ );
+ Assert.equal(result.width, expectedWidth, "Widths should be equal");
+
+ let expectedHeight = Math.floor(
+ devicePixelRatio * contentInfo.clientHeight
+ );
+ Assert.equal(result.height, expectedHeight, "Heights should be equal");
+
+ // top left
+ Assert.equal(111, result.color.topLeft[0], "R color value");
+ Assert.equal(111, result.color.topLeft[1], "G color value");
+ Assert.equal(111, result.color.topLeft[2], "B color value");
+
+ // top right
+ Assert.equal(111, result.color.topRight[0], "R color value");
+ Assert.equal(111, result.color.topRight[1], "G color value");
+ Assert.equal(111, result.color.topRight[2], "B color value");
+
+ // bottom left
+ Assert.equal(111, result.color.bottomLeft[0], "R color value");
+ Assert.equal(111, result.color.bottomLeft[1], "G color value");
+ Assert.equal(111, result.color.bottomLeft[2], "B color value");
+
+ // bottom right
+ Assert.equal(111, result.color.bottomRight[0], "R color value");
+ Assert.equal(111, result.color.bottomRight[1], "G color value");
+ Assert.equal(111, result.color.bottomRight[2], "B color value");
+ }
+ );
+});
+
+add_task(async function test_visibleScreenshotScrolled() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ await SpecialPowers.spawn(browser, [], () => {
+ content.scrollTo(0, 2008);
+ });
+
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ let screenshotReady = TestUtils.topicObserved(
+ "screenshots-preview-ready"
+ );
+
+ // click the visible page button in panel
+ let visiblePageButton = panel
+ .querySelector("screenshots-buttons")
+ .shadowRoot.querySelector(".visible-page");
+ visiblePageButton.click();
+
+ let dialog = helper.getDialog();
+
+ await screenshotReady;
+
+ let copyButton = dialog._frame.contentDocument.querySelector(
+ ".highlight-button-copy"
+ );
+ ok(copyButton, "Got the copy button");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ // click copy button on dialog box
+ copyButton.click();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+ info("contentInfo: " + JSON.stringify(contentInfo, null, 2));
+
+ let expectedWidth = Math.floor(
+ devicePixelRatio * contentInfo.clientWidth
+ );
+ Assert.equal(result.width, expectedWidth, "Widths should be equal");
+
+ let expectedHeight = Math.floor(
+ devicePixelRatio * contentInfo.clientHeight
+ );
+ Assert.equal(result.height, expectedHeight, "Heights should be equal");
+
+ // top left
+ Assert.equal(105, result.color.topLeft[0], "R color value");
+ Assert.equal(55, result.color.topLeft[1], "G color value");
+ Assert.equal(105, result.color.topLeft[2], "B color value");
+
+ // top right
+ Assert.equal(105, result.color.topRight[0], "R color value");
+ Assert.equal(55, result.color.topRight[1], "G color value");
+ Assert.equal(105, result.color.topRight[2], "B color value");
+
+ // bottom left
+ Assert.equal(105, result.color.bottomLeft[0], "R color value");
+ Assert.equal(55, result.color.bottomLeft[1], "G color value");
+ Assert.equal(105, result.color.bottomLeft[2], "B color value");
+
+ // bottom right
+ Assert.equal(105, result.color.bottomRight[0], "R color value");
+ Assert.equal(55, result.color.bottomRight[1], "G color value");
+ Assert.equal(105, result.color.bottomRight[2], "B color value");
+ }
+ );
+});
+
+add_task(async function test_visibleScreenshotScrolled() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ await SpecialPowers.spawn(browser, [], () => {
+ content.scrollTo(2004, 0);
+ });
+
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ let screenshotReady = TestUtils.topicObserved(
+ "screenshots-preview-ready"
+ );
+
+ // click the visible page button in panel
+ let visiblePageButton = panel
+ .querySelector("screenshots-buttons")
+ .shadowRoot.querySelector(".visible-page");
+ visiblePageButton.click();
+
+ let dialog = helper.getDialog();
+
+ await screenshotReady;
+
+ let copyButton = dialog._frame.contentDocument.querySelector(
+ ".highlight-button-copy"
+ );
+ ok(copyButton, "Got the copy button");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ // click copy button on dialog box
+ copyButton.click();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+ info("contentInfo: " + JSON.stringify(contentInfo, null, 2));
+
+ let expectedWidth = Math.floor(
+ devicePixelRatio * contentInfo.clientWidth
+ );
+ Assert.equal(result.width, expectedWidth, "Widths should be equal");
+
+ let expectedHeight = Math.floor(
+ devicePixelRatio * contentInfo.clientHeight
+ );
+ Assert.equal(result.height, expectedHeight, "Heights should be equal");
+
+ // top left
+ Assert.equal(55, result.color.topLeft[0], "R color value");
+ Assert.equal(155, result.color.topLeft[1], "G color value");
+ Assert.equal(155, result.color.topLeft[2], "B color value");
+
+ // top right
+ Assert.equal(55, result.color.topRight[0], "R color value");
+ Assert.equal(155, result.color.topRight[1], "G color value");
+ Assert.equal(155, result.color.topRight[2], "B color value");
+
+ // bottom left
+ Assert.equal(55, result.color.bottomLeft[0], "R color value");
+ Assert.equal(155, result.color.bottomLeft[1], "G color value");
+ Assert.equal(155, result.color.bottomLeft[2], "B color value");
+
+ // bottom right
+ Assert.equal(55, result.color.bottomRight[0], "R color value");
+ Assert.equal(155, result.color.bottomRight[1], "G color value");
+ Assert.equal(155, result.color.bottomRight[2], "B color value");
+ }
+ );
+});
+
+add_task(async function test_visibleScreenshotScrolled() {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: TEST_PAGE,
+ },
+ async browser => {
+ await SpecialPowers.spawn(browser, [], () => {
+ content.scrollTo(2004, 2008);
+ });
+
+ let helper = new ScreenshotsHelper(browser);
+ let contentInfo = await helper.getContentDimensions();
+ ok(contentInfo, "Got dimensions back from the content");
+
+ // click toolbar button so panel shows
+ helper.triggerUIFromToolbar();
+
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ let screenshotReady = TestUtils.topicObserved(
+ "screenshots-preview-ready"
+ );
+
+ // click the visible page button in panel
+ let visiblePageButton = panel
+ .querySelector("screenshots-buttons")
+ .shadowRoot.querySelector(".visible-page");
+ visiblePageButton.click();
+
+ let dialog = helper.getDialog();
+
+ await screenshotReady;
+
+ let copyButton = dialog._frame.contentDocument.querySelector(
+ ".highlight-button-copy"
+ );
+ ok(copyButton, "Got the copy button");
+
+ let clipboardChanged = helper.waitForRawClipboardChange();
+
+ // click copy button on dialog box
+ copyButton.click();
+
+ info("Waiting for clipboard change");
+ await clipboardChanged;
+
+ let result = await helper.getImageSizeAndColorFromClipboard();
+
+ info("result: " + JSON.stringify(result, null, 2));
+ info("contentInfo: " + JSON.stringify(contentInfo, null, 2));
+
+ let expectedWidth = Math.floor(
+ devicePixelRatio * contentInfo.clientWidth
+ );
+ Assert.equal(result.width, expectedWidth, "Widths should be equal");
+
+ let expectedHeight = Math.floor(
+ devicePixelRatio * contentInfo.clientHeight
+ );
+ Assert.equal(result.height, expectedHeight, "Heights should be equal");
+
+ // top left
+ Assert.equal(52, result.color.topLeft[0], "R color value");
+ Assert.equal(127, result.color.topLeft[1], "G color value");
+ Assert.equal(152, result.color.topLeft[2], "B color value");
+
+ // top right
+ Assert.equal(52, result.color.topRight[0], "R color value");
+ Assert.equal(127, result.color.topRight[1], "G color value");
+ Assert.equal(152, result.color.topRight[2], "B color value");
+
+ // bottom left
+ Assert.equal(52, result.color.bottomLeft[0], "R color value");
+ Assert.equal(127, result.color.bottomLeft[1], "G color value");
+ Assert.equal(152, result.color.bottomLeft[2], "B color value");
+
+ // bottom right
+ Assert.equal(52, result.color.bottomRight[0], "R color value");
+ Assert.equal(127, result.color.bottomRight[1], "G color value");
+ Assert.equal(152, result.color.bottomRight[2], "B color value");
+ }
+ );
+});
diff --git a/browser/components/screenshots/tests/browser/head.js b/browser/components/screenshots/tests/browser/head.js
new file mode 100644
index 0000000000..cda6aed601
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/head.js
@@ -0,0 +1,496 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const TEST_ROOT = getRootDirectory(gTestPath).replace(
+ "chrome://mochitests/content",
+ "http://example.com"
+);
+
+const TEST_PAGE = TEST_ROOT + "test-page.html";
+const SHORT_TEST_PAGE = TEST_ROOT + "short-test-page.html";
+
+const gScreenshotUISelectors = {
+ panelButtons: "#screenshotsPagePanel",
+ fullPageButton: "button.full-page",
+ visiblePageButton: "button.visible-page",
+ copyButton: "button.highlight-button-copy",
+};
+
+// MouseEvents is for the mouse events on the Anonymous content
+const MouseEvents = {
+ mouse: new Proxy(
+ {},
+ {
+ get: (target, name) =>
+ async function(x, y, selector = ":root") {
+ if (name === "click") {
+ this.down(x, y);
+ this.up(x, y);
+ } else {
+ await safeSynthesizeMouseEventInContentPage(selector, x, y, {
+ type: "mouse" + name,
+ });
+ }
+ },
+ }
+ ),
+};
+
+const { mouse } = MouseEvents;
+
+class ScreenshotsHelper {
+ constructor(browser) {
+ this.browser = browser;
+ this.selector = gScreenshotUISelectors;
+ }
+
+ get toolbarButton() {
+ return document.getElementById("screenshot-button");
+ }
+
+ /**
+ * Click the screenshots button in the toolbar
+ */
+ triggerUIFromToolbar() {
+ let button = this.toolbarButton;
+ ok(
+ BrowserTestUtils.is_visible(button),
+ "The screenshot toolbar button is visible"
+ );
+ button.click();
+ }
+
+ async waitForPanel() {
+ return BrowserTestUtils.waitForCondition(async () => {
+ return gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ });
+ }
+
+ async waitForOverlay() {
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ if (!panel) {
+ panel = await this.waitForPanel();
+ }
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_visible(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_visible(panel), "Panel buttons are visible");
+
+ await BrowserTestUtils.waitForCondition(async () => {
+ let init = await this.isOverlayInitialized();
+ return init;
+ });
+ info("Overlay is visible");
+ }
+
+ async waitForOverlayClosed() {
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ if (!panel) {
+ panel = await this.waitForPanel();
+ }
+ await BrowserTestUtils.waitForMutationCondition(
+ panel,
+ { attributes: true },
+ () => {
+ return BrowserTestUtils.is_hidden(panel);
+ }
+ );
+ ok(BrowserTestUtils.is_hidden(panel), "Panel buttons are hidden");
+
+ await BrowserTestUtils.waitForCondition(async () => {
+ let init = !(await this.isOverlayInitialized());
+ info("Is overlay initialized: " + !init);
+ return init;
+ });
+ info("Overlay is not visible");
+ }
+
+ async isOverlayInitialized() {
+ return SpecialPowers.spawn(this.browser, [], () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ return screenshotsChild?._overlay?._initialized;
+ });
+ }
+
+ async getOverlayState() {
+ return ContentTask.spawn(this.browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ return screenshotsChild._overlay.stateHandler.getState();
+ });
+ }
+
+ async waitForStateChange(newState) {
+ await BrowserTestUtils.waitForCondition(async () => {
+ let state = await this.getOverlayState();
+ return state === newState;
+ });
+ }
+
+ async waitForSelectionBoxSizeChange(currentWidth) {
+ await ContentTask.spawn(
+ this.browser,
+ [currentWidth],
+ async ([currWidth]) => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+
+ let dimensions = screenshotsChild._overlay.screenshotsContainer.getSelectionLayerDimensions();
+ // return dimensions.boxWidth;
+ await ContentTaskUtils.waitForCondition(() => {
+ dimensions = screenshotsChild._overlay.screenshotsContainer.getSelectionLayerDimensions();
+ return dimensions.boxWidth !== currWidth;
+ }, "Wait for selection box width change");
+ }
+ );
+ }
+
+ async dragOverlay(startX, startY, endX, endY) {
+ await this.waitForStateChange("crosshairs");
+ let state = await this.getOverlayState();
+ Assert.equal(state, "crosshairs", "The overlay is in the crosshairs state");
+
+ mouse.down(startX, startY);
+
+ await this.waitForStateChange("draggingReady");
+ state = await this.getOverlayState();
+ Assert.equal(
+ state,
+ "draggingReady",
+ "The overlay is in the draggingReady state"
+ );
+
+ mouse.move(endX, endY);
+
+ await this.waitForStateChange("dragging");
+ state = await this.getOverlayState();
+ Assert.equal(state, "dragging", "The overlay is in the dragging state");
+
+ mouse.up(endX, endY);
+
+ await this.waitForStateChange("selected");
+ state = await this.getOverlayState();
+ Assert.equal(state, "selected", "The overlay is in the selected state");
+
+ this.endX = endX;
+ this.endY = endY;
+ }
+
+ async scrollContentWindow(x, y) {
+ await ContentTask.spawn(this.browser, [x, y], async ([xPos, yPos]) => {
+ content.window.scroll(xPos, yPos);
+ });
+ }
+
+ clickDownloadButton() {
+ mouse.click(this.endX - 60, this.endY + 30);
+ }
+
+ clickCopyButton(overrideX = null, overrideY = null) {
+ // click copy button with last x and y position from dragOverlay
+ // the middle of the copy button is last X - 163 and last Y + 30.
+ // Ex. 500, 500 would be 336, 530
+ if (overrideX && overrideY) {
+ mouse.click(overrideX - 166, overrideY + 30);
+ } else {
+ mouse.click(this.endX - 166, this.endY + 30);
+ }
+ }
+
+ clickCancelButton() {
+ // click copy button with last x and y position from dragOverlay
+ // the middle of the copy button is last X - 230 and last Y + 30.
+ // Ex. 500, 500 would be 270, 530
+ mouse.click(this.endX - 230, this.endY + 30);
+ }
+
+ async zoomBrowser(zoom) {
+ await SpecialPowers.spawn(this.browser, [zoom], zoomLevel => {
+ const { Layout } = ChromeUtils.import(
+ "chrome://mochitests/content/browser/accessible/tests/browser/Layout.jsm"
+ );
+ Layout.zoomDocument(content.document, zoomLevel);
+ });
+ }
+
+ /**
+ * Gets the dialog box
+ * @returns The dialog box
+ */
+ getDialog() {
+ let currDialogBox = this.browser.tabDialogBox;
+ let manager = currDialogBox.getTabDialogManager();
+ let dialogs = manager.hasDialogs && manager.dialogs;
+ return dialogs[0];
+ }
+
+ assertPanelVisible() {
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ Assert.ok(
+ BrowserTestUtils.is_visible(panel),
+ "Screenshots panel is visible"
+ );
+ }
+
+ assertPanelNotVisible() {
+ let panel = gBrowser.selectedBrowser.ownerDocument.querySelector(
+ "#screenshotsPagePanel"
+ );
+ Assert.ok(
+ BrowserTestUtils.is_hidden(panel),
+ "Screenshots panel is not visible"
+ );
+ }
+
+ /**
+ * Copied from screenshots extension
+ * Returns a promise that resolves when the clipboard data has changed
+ * Otherwise rejects
+ */
+ waitForRawClipboardChange() {
+ const initialClipboardData = Date.now().toString();
+ SpecialPowers.clipboardCopyString(initialClipboardData);
+
+ let promiseChanged = TestUtils.waitForCondition(() => {
+ let data;
+ try {
+ data = getRawClipboardData("image/png");
+ } catch (e) {
+ console.log("Failed to get image/png clipboard data:", e);
+ return false;
+ }
+ return data && initialClipboardData !== data;
+ });
+ return promiseChanged;
+ }
+
+ /**
+ * 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
+ */
+ getContentDimensions() {
+ return SpecialPowers.spawn(this.browser, [], async function() {
+ let doc = content.document.documentElement;
+ return {
+ clientHeight: doc.clientHeight,
+ clientWidth: doc.clientWidth,
+ scrollHeight: doc.scrollHeight,
+ scrollWidth: doc.scrollWidth,
+ };
+ });
+ }
+
+ getSelectionLayerDimensions() {
+ return ContentTask.spawn(this.browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ Assert.ok(screenshotsChild._overlay._initialized, "The overlay exists");
+
+ return screenshotsChild._overlay.screenshotsContainer.getSelectionLayerDimensions();
+ });
+ }
+
+ getSelectionBoxDimensions() {
+ return ContentTask.spawn(this.browser, null, async () => {
+ let screenshotsChild = content.windowGlobalChild.getActor(
+ "ScreenshotsComponent"
+ );
+ Assert.ok(screenshotsChild._overlay._initialized, "The overlay exists");
+
+ return screenshotsChild._overlay.screenshotsContainer.getSelectionLayerBoxDimensions();
+ });
+ }
+
+ /**
+ * Clicks an element on the screen
+ * @param eleSel The selector for the element to click
+ */
+ async clickUIElement(eleSel) {
+ await SpecialPowers.spawn(this.browser, [eleSel], async function(
+ eleSelector
+ ) {
+ info(
+ `in clickScreenshotsUIElement content function, eleSelector: ${eleSelector}`
+ );
+ const EventUtils = ContentTaskUtils.getEventUtils(content);
+ let ele = content.document.querySelector(eleSelector);
+ info(`Found the thing to click: ${eleSelector}: ${!!ele}`);
+
+ EventUtils.synthesizeMouseAtCenter(ele, {});
+ // wait a frame for the screenshots UI to finish any init
+ await new content.Promise(res => content.requestAnimationFrame(res));
+ });
+ }
+
+ /**
+ * 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() {
+ let flavor = "image/png";
+ let image = getRawClipboardData(flavor);
+ ok(image, "screenshot data exists on the clipboard");
+
+ // 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.
+
+ if (image instanceof Ci.imgIContainer) {
+ image = Cc["@mozilla.org/image/tools;1"]
+ .getService(Ci.imgITools)
+ .encodeImage(image, flavor);
+ }
+
+ if (!(image instanceof Ci.nsIInputStream)) {
+ throw new Error("Unable to read image data");
+ }
+
+ const binaryStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance(
+ Ci.nsIBinaryInputStream
+ );
+ binaryStream.setInputStream(image);
+ const available = binaryStream.available();
+ const buffer = new ArrayBuffer(available);
+ is(
+ binaryStream.readArrayBuffer(available, buffer),
+ available,
+ "Read expected amount of data"
+ );
+
+ // 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], async function(_buffer) {
+ 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" })
+ );
+
+ img.src = url;
+ content.document.documentElement.appendChild(img);
+
+ info("Waiting for the clipboard image to load in the content page");
+ await loaded;
+
+ let canvas = content.document.createElementNS(
+ "http://www.w3.org/1999/xhtml",
+ "html:canvas"
+ );
+ let context = canvas.getContext("2d");
+ canvas.width = img.width;
+ canvas.height = img.height;
+ context.drawImage(img, 0, 0);
+ let topLeft = context.getImageData(0, 0, 1, 1);
+ let topRight = context.getImageData(img.width - 1, 0, 1, 1);
+ let bottomLeft = context.getImageData(0, img.height - 1, 1, 1);
+ let bottomRight = context.getImageData(
+ img.width - 1,
+ img.height - 1,
+ 1,
+ 1
+ );
+
+ img.remove();
+ content.URL.revokeObjectURL(url);
+
+ return {
+ width: img.width,
+ height: img.height,
+ color: {
+ topLeft: topLeft.data,
+ topRight: topRight.data,
+ bottomLeft: bottomLeft.data,
+ bottomRight: bottomRight.data,
+ },
+ };
+ });
+ }
+}
+
+/**
+ * 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);
+ 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, after ensuring that it is visible
+ * 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 = {}
+) {
+ let context = gBrowser.selectedBrowser.browsingContext;
+ BrowserTestUtils.synthesizeMouse(selector, x, y, options, context);
+}
+
+add_setup(async () => {
+ CustomizableUI.addWidgetToArea(
+ "screenshot-button",
+ CustomizableUI.AREA_NAVBAR
+ );
+ let screenshotBtn = document.getElementById("screenshot-button");
+ Assert.ok(screenshotBtn, "The screenshots button was added to the nav bar");
+});
+
+function getContentDevicePixelRatio(browser) {
+ return SpecialPowers.spawn(browser, [], async function() {
+ return content.window.devicePixelRatio;
+ });
+}
diff --git a/browser/components/screenshots/tests/browser/short-test-page.html b/browser/components/screenshots/tests/browser/short-test-page.html
new file mode 100644
index 0000000000..4ba4f10394
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/short-test-page.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Screenshots</title>
+</head>
+<body style="height:100px; width:100px;">
+</body>
+</html>
diff --git a/browser/components/screenshots/tests/browser/test-page.html b/browser/components/screenshots/tests/browser/test-page.html
new file mode 100644
index 0000000000..9f9ae8d652
--- /dev/null
+++ b/browser/components/screenshots/tests/browser/test-page.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Screenshots</title>
+</head>
+<body style="height:4000px; width:4000px; background-repeat: no-repeat; background-size: 4008px 4016px; background-color: rgb(111, 111, 111); background-image:linear-gradient(to right, transparent 50%, rgba(0, 200, 200, 0.5) 50%),linear-gradient(to bottom, transparent 50%, rgba(100, 0, 100, 0.5) 50%);">
+</body>
+</html>