commit dc10e26ff5f635ef1a116b60f8dbd2e628891646
parent 5945d82e289bbad6935b42f5867abcd9d1cc4975
Author: Tom Schuster <tschuster@mozilla.com>
Date: Thu, 20 Nov 2025 11:16:16 +0000
Bug 2000196 - Compare favicons using new ImageTestUtils. r=tnikkel
Differential Revision: https://phabricator.services.mozilla.com/D273007
Diffstat:
6 files changed, 113 insertions(+), 15 deletions(-)
diff --git a/browser/base/content/test/favicons/browser_favicon_empty_data.js b/browser/base/content/test/favicons/browser_favicon_empty_data.js
@@ -3,6 +3,10 @@
"use strict";
+const { ImageTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ImageTestUtils.sys.mjs"
+);
+
const TEST_ROOT =
"http://mochi.test:8888/browser/browser/base/content/test/favicons/";
@@ -22,7 +26,12 @@ add_task(async function () {
.getTabForBrowser(browser)
.querySelector(".tab-icon-image");
await addContentLinkForIconUrl(ICON_URL, browser);
- Assert.equal(browser.mIconURL, ICON_DATAURI, "Favicon is correctly set.");
+ await ImageTestUtils.assertEqualImage(
+ window,
+ browser.mIconURL,
+ ICON_DATAURI,
+ "Favicon is correctly set."
+ );
// Give some time to ensure the icon is rendered.
/* eslint-disable mozilla/no-arbitrary-setTimeout */
diff --git a/browser/components/originattributes/test/browser/browser_favicon_firstParty.js b/browser/components/originattributes/test/browser/browser_favicon_firstParty.js
@@ -12,6 +12,10 @@ const { PlacesTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/PlacesTestUtils.sys.mjs"
);
+const { ImageTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ImageTestUtils.sys.mjs"
+);
+
const FIRST_PARTY_ONE = "example.com";
const FIRST_PARTY_TWO = "example.org";
const THIRD_PARTY = "example.net";
@@ -222,14 +226,19 @@ async function generateCookies(aThirdParty) {
return cookies;
}
-function assertIconIsData(item) {
+async function assertIconIsData(item) {
let icon = item.getAttribute("image");
is(
icon.substring(0, 5),
"data:",
"Expected the image element to be a data URI"
);
- is(icon, ICON_DATA, "Expected to see the correct data.");
+ await ImageTestUtils.assertEqualImage(
+ window,
+ icon,
+ ICON_DATA,
+ "Expected to see the correct data."
+ );
}
async function doTest(aTestPage, aExpectedCookies, aFaviconURL) {
@@ -255,7 +264,7 @@ async function doTest(aTestPage, aExpectedCookies, aFaviconURL) {
// Waiting until favicon loaded.
await promiseFaviconLoaded;
- assertIconIsData(tabInfo.tab);
+ await assertIconIsData(tabInfo.tab);
BrowserTestUtils.removeTab(tabInfo.tab);
// FIXME: We need to wait for the next event tick here to avoid observing
@@ -300,7 +309,7 @@ async function doTestForAllTabsFavicon(
// Waiting until the favicon loaded.
await promiseFaviconLoaded;
- assertIconIsData(tabInfo.tab);
+ await assertIconIsData(tabInfo.tab);
gTabsPanel.init();
@@ -313,7 +322,7 @@ async function doTestForAllTabsFavicon(
gTabsPanel.showAllTabsPanel();
await allTabsPopupShownPromise;
- assertIconIsData(
+ await assertIconIsData(
gTabsPanel.allTabsViewTabs.lastElementChild.firstElementChild
);
@@ -341,7 +350,7 @@ async function doTestForAllTabsFavicon(
// Wait until the favicon is fully loaded.
await promiseFaviconLoaded;
- assertIconIsData(tabInfo.tab);
+ await assertIconIsData(tabInfo.tab);
// Make the popup of allTabs showing up again.
allTabsPopupShownPromise = BrowserTestUtils.waitForEvent(
@@ -351,7 +360,7 @@ async function doTestForAllTabsFavicon(
gTabsPanel.showAllTabsPanel();
await allTabsPopupShownPromise;
- assertIconIsData(
+ await assertIconIsData(
gTabsPanel.allTabsViewTabs.lastElementChild.firstElementChild
);
diff --git a/browser/components/sessionstore/test/browser_tabicon_after_bg_tab_crash.js b/browser/components/sessionstore/test/browser_tabicon_after_bg_tab_crash.js
@@ -1,5 +1,9 @@
"use strict";
+const { ImageTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ImageTestUtils.sys.mjs"
+);
+
const FAVICON =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAALCAYAAACprHcmAAAARElEQVQYV2NkYLj3nwEnUGKEMxkYGBghilEFIQBTHKqYOIDFZHQ+DNz7j0MxdoDDGThNRgfoNsEATsXYARbFuAHtFAMAuvMbOrNomdAAAAAASUVORK5CYII=";
const PAGE_URL = `data:text/html,
@@ -36,13 +40,20 @@ add_task(async function test_tabicon_after_bg_tab_crash() {
100,
5
);
- Assert.equal(browser.mIconURL, FAVICON, "Favicon is correctly set.");
+ await ImageTestUtils.assertEqualImage(
+ window,
+ browser.mIconURL,
+ FAVICON,
+ "Favicon is correctly set."
+ );
+
await BrowserTestUtils.switchTab(gBrowser, originalTab);
await BrowserTestUtils.crashFrame(
browser,
false /* shouldShowTabCrashPage */
);
- Assert.equal(
+ await ImageTestUtils.assertEqualImage(
+ window,
browser.mIconURL,
FAVICON,
"Favicon is still set after crash."
diff --git a/devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_tab_favicons.js b/devtools/client/aboutdebugging/test/browser/browser_aboutdebugging_tab_favicons.js
@@ -3,6 +3,10 @@
"use strict";
+const { ImageTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ImageTestUtils.sys.mjs"
+);
+
/**
* Check that about:debugging uses the favicon of tab targets as the icon of their debug
* target item, and doesn't always use the default globe icon.
@@ -14,10 +18,8 @@ const TAB_URL =
"https://example.com/browser/devtools/client/aboutdebugging/" +
"test/browser/test-tab-favicons.html";
-// The favicon in the page is re-encoded, with different results depending on zlib-rs usage.
-const EXPECTED_FAVICON = AppConstants.USE_LIBZ_RS
- ? "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAXElEQVRYR+3SMQoAIAxD0fb+h9ZBEM3SKfwlTkISeEN7Va16Xt/feV9oyDsAHKCdaeDIA2AB+BEGgAO0Mw0ceQAsAD/CAHCAdqaBIw+ABeBHGAAO0M40cOQBoIANOAOf8d5vwtsAAAAASUVORK5CYII="
- : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAV0lEQVRYR+2UMQ4AIAgD4f+P1m6KcVQ7eMZBJCHNUcgWoTtOzoHeJan4dD4RYCewtvl2z3f1yx8CnhOwmxABdgLsAQjYTYgAOwGmAAJ2EyLAToAp+J5ABzgDn/EwCmG5AAAAAElFTkSuQmCC";
+const EXPECTED_FAVICON =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAV0lEQVRYR+2UMQ4AIAgD4f+P1m6KcVQ7eMZBJCHNUcgWoTtOzoHeJan4dD4RYCewtvl2z3f1yx8CnhOwmxABdgLsAQjYTYgAOwGmAAJ2EyLAToAp+J5ABzgDn/EwCmG5AAAAAElFTkSuQmCC";
add_task(async function () {
const faviconTab = await addTab(TAB_URL, { background: true });
@@ -40,7 +42,8 @@ add_task(async function () {
".qa-debug-target-item-icon"
);
- is(
+ await ImageTestUtils.assertEqualImage(
+ window,
faviconTabIcon.src,
EXPECTED_FAVICON,
"The debug target item for the tab shows the favicon of the tab"
diff --git a/testing/modules/ImageTestUtils.sys.mjs b/testing/modules/ImageTestUtils.sys.mjs
@@ -0,0 +1,65 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/**
+ * Provides testing functions working with images and image URLs.
+ */
+
+import { Assert } from "resource://testing-common/Assert.sys.mjs";
+
+export const ImageTestUtils = {
+ /**
+ * Assert that both provided image URLs are visually identical.
+ */
+ async assertEqualImage(win, first, second, msg) {
+ const firstCanvas = await this.drawImageOnCanvas(win, first);
+ const secondCanvas = await this.drawImageOnCanvas(win, second);
+
+ Assert.equal(
+ firstCanvas.width,
+ secondCanvas.width,
+ `${msg} - Both images have the same width`
+ );
+ Assert.equal(
+ firstCanvas.height,
+ secondCanvas.height,
+ `${msg} - Both images have the same height`
+ );
+
+ const differences = win.windowUtils.compareCanvases(
+ firstCanvas,
+ secondCanvas,
+ {}
+ );
+ Assert.equal(differences, 0, `${msg} - Both images are identical`);
+ },
+
+ drawImageOnCanvas(win, url) {
+ return new Promise((resolve, reject) => {
+ const img = new win.Image();
+
+ img.onload = function () {
+ // TODO: compareCanvases only works for the HTMLCanvasElement.
+ const canvas = win.document.createElementNS(
+ "http://www.w3.org/1999/xhtml",
+ "canvas"
+ );
+ canvas.width = img.naturalWidth;
+ canvas.height = img.naturalHeight;
+
+ const ctx = canvas.getContext("2d");
+ ctx.drawImage(img, 0, 0);
+
+ resolve(canvas);
+ };
+
+ img.onerror = function () {
+ reject(`error loading image ${url}`);
+ };
+
+ // Load the src image for drawing
+ img.src = url;
+ });
+ },
+};
diff --git a/testing/modules/moz.build b/testing/modules/moz.build
@@ -13,6 +13,7 @@ TESTING_JS_MODULES += [
"Assert.sys.mjs",
"CoverageUtils.sys.mjs",
"FileTestUtils.sys.mjs",
+ "ImageTestUtils.sys.mjs",
"Mochia.js",
"MockRegistrar.sys.mjs",
"sinon-7.2.7.js",