diff --git a/e2e/tests/404.spec.ts b/e2e/tests/404.spec.ts index f0521c16b..cc3144532 100644 --- a/e2e/tests/404.spec.ts +++ b/e2e/tests/404.spec.ts @@ -15,7 +15,14 @@ */ import {test, expect} from '@playwright/test'; -import {BASE_URL, expect404PageButtons, goTo404Page} from './utils'; +import { + BASE_URL, + expect404PageButtons, + goTo404Page, + expectDualThemeScreenshot, +} from './utils'; + +test.beforeEach(async () => {}); test('Bad URL redirection to 404 page', async ({page}) => { const badUrls = [ @@ -64,8 +71,10 @@ test('shows similar features and all buttons when results exist', async ({ const pageContainer = page.locator('.page-container'); // Snapshot - await expect(pageContainer).toHaveScreenshot( - 'not-found-error-page-similar-results.png', + await expectDualThemeScreenshot( + page, + pageContainer, + 'not-found-error-page-similar-results', ); // Clicking the search button should redirect to homepage with search @@ -116,5 +125,5 @@ test('should allow navigation from 404 page', async ({page}) => { test('matches the screenshot 404 not found page', async ({page}) => { await page.goto(`${BASE_URL}/bad_url`); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot('not-found-error-page.png'); + await expectDualThemeScreenshot(page, pageContainer, 'not-found-error-page'); }); diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-chromium-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-chromium-linux.png index d4798a037..dd68be925 100644 Binary files a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-chromium-linux.png and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-chromium-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-chromium-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-chromium-linux.png new file mode 100644 index 000000000..2ee1aa1f6 Binary files /dev/null and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-chromium-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-firefox-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-firefox-linux.png new file mode 100644 index 000000000..9c281b422 Binary files /dev/null and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-firefox-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-webkit-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-webkit-linux.png new file mode 100644 index 000000000..7660520b6 Binary files /dev/null and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-dark-webkit-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-firefox-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-firefox-linux.png index c4a0127f3..c12d0bc2c 100644 Binary files a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-firefox-linux.png and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-firefox-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-chromium-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-chromium-linux.png index cdaf55e83..c9bd25f32 100644 Binary files a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-chromium-linux.png and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-chromium-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-chromium-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-chromium-linux.png new file mode 100644 index 000000000..6a10d2af6 Binary files /dev/null and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-chromium-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-firefox-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-firefox-linux.png new file mode 100644 index 000000000..2baf3aca1 Binary files /dev/null and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-firefox-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-webkit-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-webkit-linux.png new file mode 100644 index 000000000..d6ec64c05 Binary files /dev/null and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-dark-webkit-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-firefox-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-firefox-linux.png index f8f898d93..ac5955d39 100644 Binary files a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-firefox-linux.png and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-firefox-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-webkit-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-webkit-linux.png index 7c3ccab95..dad92eb3d 100644 Binary files a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-webkit-linux.png and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-similar-results-webkit-linux.png differ diff --git a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-webkit-linux.png b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-webkit-linux.png index 56fa8385b..a598458bf 100644 Binary files a/e2e/tests/404.spec.ts-snapshots/not-found-error-page-webkit-linux.png and b/e2e/tests/404.spec.ts-snapshots/not-found-error-page-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts b/e2e/tests/feature-page.spec.ts index 6c123aeb0..81fdacf2e 100644 --- a/e2e/tests/feature-page.spec.ts +++ b/e2e/tests/feature-page.spec.ts @@ -15,7 +15,12 @@ */ import {test, expect} from '@playwright/test'; -import {setupFakeNow, resetUserData, loginAsUser} from './utils'; +import { + setupFakeNow, + resetUserData, + loginAsUser, + expectDualThemeScreenshot, +} from './utils'; test.beforeEach(async ({page}) => { await setupFakeNow(page); @@ -36,7 +41,7 @@ test('matches the screenshot', async ({page}) => { await page.waitForSelector('sl-card.wptScore .avail >> text=Baseline since'); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'feature-page'); }); test('matches the screenshot for a discouraged feature', async ({page}) => { @@ -49,7 +54,11 @@ test('matches the screenshot for a discouraged feature', async ({page}) => { await page.waitForSelector('sl-card.wptScore .avail >> text=Baseline since'); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot( + page, + pageContainer, + 'feature-page-discouraged', + ); }); test('chart width resizes with window', async ({page}) => { @@ -98,7 +107,7 @@ test('mobile chart displays on click and matches screenshot', async ({ await mobileTab.click(); await page.waitForTimeout(2000); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'feature-page-mobile'); }); test('date range changes are preserved in the URL', async ({page}) => { @@ -191,7 +200,7 @@ test('redirects for a moved feature', async ({page}) => { // Take a screenshot for visual verification. const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'feature-page-redirect'); }); test('shows gone page for a split feature', async ({page}) => { @@ -215,7 +224,7 @@ test('shows gone page for a split feature', async ({page}) => { // Take a screenshot for visual verification. const pageContainer = page.locator('.container'); // Assuming a generic container for the error page. - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'feature-gone-split'); }); test.describe('Subscriptions', () => { diff --git a/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-chromium-linux.png index 3a779ecac..aa4239ba8 100644 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-chromium-linux.png and b/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-firefox-linux.png index e2b033016..059613a4a 100644 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-firefox-linux.png and b/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-webkit-linux.png index 80541b07a..b139fb463 100644 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-webkit-linux.png and b/e2e/tests/feature-page.spec.ts-snapshots/chart-width-resizes-with-window-1-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-chromium-linux.png new file mode 100644 index 000000000..f90b7ab2b Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-chromium-linux.png new file mode 100644 index 000000000..4c8fd9801 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-firefox-linux.png new file mode 100644 index 000000000..62fd88384 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-webkit-linux.png new file mode 100644 index 000000000..f0e74b176 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-dark-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-firefox-linux.png new file mode 100644 index 000000000..ca93ab45a Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-webkit-linux.png new file mode 100644 index 000000000..57d0b0273 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-gone-split-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-chromium-linux.png new file mode 100644 index 000000000..254171554 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-chromium-linux.png new file mode 100644 index 000000000..99af88520 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-firefox-linux.png new file mode 100644 index 000000000..09b2b5cc3 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-webkit-linux.png new file mode 100644 index 000000000..585174a77 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-dark-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-chromium-linux.png new file mode 100644 index 000000000..6d0badff8 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-chromium-linux.png new file mode 100644 index 000000000..07b59e759 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-firefox-linux.png new file mode 100644 index 000000000..2e4d7c054 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-webkit-linux.png new file mode 100644 index 000000000..e7b1fd429 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-dark-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-firefox-linux.png new file mode 100644 index 000000000..b04c92cca Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-webkit-linux.png new file mode 100644 index 000000000..95404b585 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-discouraged-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-firefox-linux.png new file mode 100644 index 000000000..bd2f51127 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-chromium-linux.png new file mode 100644 index 000000000..80ab464e1 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-chromium-linux.png new file mode 100644 index 000000000..8716fd290 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-firefox-linux.png new file mode 100644 index 000000000..c403af068 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-webkit-linux.png new file mode 100644 index 000000000..518579e86 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-dark-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-firefox-linux.png new file mode 100644 index 000000000..b3746c8d4 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-webkit-linux.png new file mode 100644 index 000000000..f8992d661 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-mobile-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-chromium-linux.png new file mode 100644 index 000000000..b5f16f055 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-chromium-linux.png new file mode 100644 index 000000000..f0fe41716 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-chromium-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-firefox-linux.png new file mode 100644 index 000000000..83a9d7575 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-webkit-linux.png new file mode 100644 index 000000000..a3b219534 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-dark-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-firefox-linux.png new file mode 100644 index 000000000..236a214ee Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-firefox-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-webkit-linux.png new file mode 100644 index 000000000..b01f90620 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-redirect-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/feature-page-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-webkit-linux.png new file mode 100644 index 000000000..ffd0712c4 Binary files /dev/null and b/e2e/tests/feature-page.spec.ts-snapshots/feature-page-webkit-linux.png differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png deleted file mode 100644 index 402dba155..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png deleted file mode 100644 index 733d2c02e..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png deleted file mode 100644 index ce1ef0e4e..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-chromium-linux.png deleted file mode 100644 index a0b701b5e..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-firefox-linux.png deleted file mode 100644 index ab9adcd2c..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-webkit-linux.png deleted file mode 100644 index 26160c076..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/matches-the-screenshot-for-a-discouraged-feature-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-chromium-linux.png deleted file mode 100644 index 78964724e..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-firefox-linux.png deleted file mode 100644 index eb18311ff..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-webkit-linux.png deleted file mode 100644 index b85e6e809..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/mobile-chart-displays-on-click-and-matches-screenshot-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-chromium-linux.png deleted file mode 100644 index 1428bd96d..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-firefox-linux.png deleted file mode 100644 index 420c19d83..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-webkit-linux.png deleted file mode 100644 index 2d92e01f2..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/redirects-for-a-moved-feature-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-chromium-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-chromium-linux.png deleted file mode 100644 index f25cbd37f..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-firefox-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-firefox-linux.png deleted file mode 100644 index f4786c2ee..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-webkit-linux.png b/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-webkit-linux.png deleted file mode 100644 index e7ce5a060..000000000 Binary files a/e2e/tests/feature-page.spec.ts-snapshots/shows-gone-page-for-a-split-feature-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/login.spec.ts b/e2e/tests/login.spec.ts index 71d327c79..be7450a8d 100644 --- a/e2e/tests/login.spec.ts +++ b/e2e/tests/login.spec.ts @@ -15,7 +15,15 @@ */ import {test, expect} from '@playwright/test'; -import {dismissToast, freezeAnimations, loginAsUser, testUsers} from './utils'; +import { + dismissToast, + freezeAnimations, + loginAsUser, + testUsers, + expectDualThemeScreenshot, +} from './utils'; + +test.beforeEach(async () => {}); test.describe('Login Component States', () => { test('displays spinner and is disabled during profile sync', async ({ @@ -40,8 +48,10 @@ test.describe('Login Component States', () => { // Take a screenshot for visual regression. await page.mouse.move(0, 0); // Move mouse to avoid hover effects. - await expect(page.locator('webstatus-header')).toHaveScreenshot( - 'login-syncing-state.png', + await expectDualThemeScreenshot( + page, + page.locator('webstatus-header'), + 'login-syncing-state', ); // Now, wait for the sync to complete and verify the final state. @@ -75,8 +85,10 @@ test.describe('Login Component States', () => { // Take a screenshot for visual regression. await page.mouse.move(0, 0); - await expect(page.locator('webstatus-header')).toHaveScreenshot( - 'login-error-state.png', + await expectDualThemeScreenshot( + page, + page.locator('webstatus-header'), + 'login-error-state', ); }); @@ -93,8 +105,10 @@ test.describe('Login Component States', () => { // Take a screenshot for visual regression. await page.mouse.move(0, 0); - await expect(page.locator('webstatus-header')).toHaveScreenshot( - 'login-idle-state.png', + await expectDualThemeScreenshot( + page, + page.locator('webstatus-header'), + 'login-idle-state', ); }); }); @@ -106,7 +120,7 @@ test('matches the screenshot for unauthenticated user', async ({page}) => { await expect(login).toContainText('Log in'); const header = page.locator('webstatus-header'); - await expect(header).toHaveScreenshot('unauthenticated-header.png'); + await expectDualThemeScreenshot(page, header, 'unauthenticated-header'); }); test('can sign in and sign out user', async ({page}) => { @@ -130,7 +144,7 @@ test('can sign in and sign out user', async ({page}) => { expect(pingRequest).toBeTruthy(); const header = page.locator('webstatus-header'); - await expect(header).toHaveScreenshot('authenticated-header.png'); + await expectDualThemeScreenshot(page, header, 'authenticated-header'); // Show the menu await login.click(); @@ -139,5 +153,5 @@ test('can sign in and sign out user', async ({page}) => { await signOutBtn.click(); - await expect(login).toHaveScreenshot('unauthenticated-button.png'); + await expectDualThemeScreenshot(page, login, 'unauthenticated-button'); }); diff --git a/e2e/tests/login.spec.ts-snapshots/authenticated-header-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/authenticated-header-chromium-linux.png index 7e8025666..22dd8134b 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/authenticated-header-chromium-linux.png and b/e2e/tests/login.spec.ts-snapshots/authenticated-header-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-chromium-linux.png new file mode 100644 index 000000000..e3b717a1f Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-firefox-linux.png new file mode 100644 index 000000000..552e5f14b Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-webkit-linux.png new file mode 100644 index 000000000..ce4247767 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/authenticated-header-dark-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/authenticated-header-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/authenticated-header-firefox-linux.png index fca26462d..063641feb 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/authenticated-header-firefox-linux.png and b/e2e/tests/login.spec.ts-snapshots/authenticated-header-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/authenticated-header-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/authenticated-header-webkit-linux.png index 5d10f4b8c..05f47ea03 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/authenticated-header-webkit-linux.png and b/e2e/tests/login.spec.ts-snapshots/authenticated-header-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-error-state-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/login-error-state-chromium-linux.png index eee2dfeea..726ca8b6a 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-error-state-chromium-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-error-state-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-chromium-linux.png new file mode 100644 index 000000000..3a8160574 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-firefox-linux.png new file mode 100644 index 000000000..567a3c722 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-webkit-linux.png new file mode 100644 index 000000000..2f6e89511 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-error-state-dark-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-error-state-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/login-error-state-firefox-linux.png index 585b2ba42..667af15da 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-error-state-firefox-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-error-state-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-error-state-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/login-error-state-webkit-linux.png index c584fec22..0e974feee 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-error-state-webkit-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-error-state-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-idle-state-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/login-idle-state-chromium-linux.png index a5e40aeca..58cfd08a1 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-idle-state-chromium-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-idle-state-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-chromium-linux.png new file mode 100644 index 000000000..413f96a82 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-firefox-linux.png new file mode 100644 index 000000000..552e5f14b Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-webkit-linux.png new file mode 100644 index 000000000..7f80b0c4a Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-idle-state-dark-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-idle-state-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/login-idle-state-firefox-linux.png index fca26462d..063641feb 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-idle-state-firefox-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-idle-state-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-idle-state-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/login-idle-state-webkit-linux.png index ca94ed44b..ac75f0498 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-idle-state-webkit-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-idle-state-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-chromium-linux.png index ee7bc607b..7239e82d5 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-chromium-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-chromium-linux.png new file mode 100644 index 000000000..af67989c5 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-firefox-linux.png new file mode 100644 index 000000000..b084ac968 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-webkit-linux.png new file mode 100644 index 000000000..7f80b0c4a Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-dark-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-firefox-linux.png index 1fd8ce03c..fba633950 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-firefox-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-webkit-linux.png index 7eec35d07..9d8ab39ea 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/login-syncing-state-webkit-linux.png and b/e2e/tests/login.spec.ts-snapshots/login-syncing-state-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-chromium-linux.png new file mode 100644 index 000000000..75ecc5df6 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-firefox-linux.png new file mode 100644 index 000000000..ed0e8caae Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-webkit-linux.png new file mode 100644 index 000000000..c40668eed Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-button-dark-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-chromium-linux.png index db92f1a48..ce5f5c5be 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-chromium-linux.png and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-chromium-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-chromium-linux.png new file mode 100644 index 000000000..f0c8eb1ee Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-chromium-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-firefox-linux.png new file mode 100644 index 000000000..fbedd1583 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-webkit-linux.png new file mode 100644 index 000000000..30098f7b4 Binary files /dev/null and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-dark-webkit-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-firefox-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-firefox-linux.png index 3cad7e2f2..41d63e6cb 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-firefox-linux.png and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-firefox-linux.png differ diff --git a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-webkit-linux.png b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-webkit-linux.png index 4f97d1076..151bbae3f 100644 Binary files a/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-webkit-linux.png and b/e2e/tests/login.spec.ts-snapshots/unauthenticated-header-webkit-linux.png differ diff --git a/e2e/tests/notification-channels.spec.ts b/e2e/tests/notification-channels.spec.ts index d45d5113f..69ef3c3a9 100644 --- a/e2e/tests/notification-channels.spec.ts +++ b/e2e/tests/notification-channels.spec.ts @@ -15,7 +15,9 @@ */ import {test, expect} from '@playwright/test'; -import {loginAsUser, BASE_URL} from './utils'; +import {loginAsUser, BASE_URL, expectDualThemeScreenshot} from './utils'; + +test.beforeEach(async () => {}); test.describe('Notification Channels Page', () => { test('redirects unauthenticated user to home and shows toast', async ({ @@ -63,8 +65,10 @@ test.describe('Notification Channels Page', () => { // Take a screenshot for visual regression const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot( - 'notification-channels-authenticated.png', + await expectDualThemeScreenshot( + page, + pageContainer, + 'notification-channels-authenticated', ); }); }); diff --git a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-chromium-linux.png b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-chromium-linux.png index 4bce2f905..f695dffbe 100644 Binary files a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-chromium-linux.png and b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-chromium-linux.png differ diff --git a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-chromium-linux.png b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-chromium-linux.png new file mode 100644 index 000000000..947c5397e Binary files /dev/null and b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-chromium-linux.png differ diff --git a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-firefox-linux.png b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-firefox-linux.png new file mode 100644 index 000000000..cafa34c16 Binary files /dev/null and b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-firefox-linux.png differ diff --git a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-webkit-linux.png b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-webkit-linux.png new file mode 100644 index 000000000..6366bbdb0 Binary files /dev/null and b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-dark-webkit-linux.png differ diff --git a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-firefox-linux.png b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-firefox-linux.png index afd504636..dfedc0e6d 100644 Binary files a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-firefox-linux.png and b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-firefox-linux.png differ diff --git a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-webkit-linux.png b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-webkit-linux.png index c52c3995a..c9ab38728 100644 Binary files a/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-webkit-linux.png and b/e2e/tests/notification-channels.spec.ts-snapshots/notification-channels-authenticated-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts b/e2e/tests/overview-page.spec.ts index 31078653b..84c05db7f 100644 --- a/e2e/tests/overview-page.spec.ts +++ b/e2e/tests/overview-page.spec.ts @@ -14,20 +14,26 @@ * limitations under the License. */ -import {test, expect, Request, Response} from '@playwright/test'; +import {test, expect, Request, Response, Page} from '@playwright/test'; import { gotoOverviewPageUrl, getOverviewPageFeatureCount, loginAsUser, waitForOverviewPageLoad, + expectDualThemeScreenshot, + setupFakeNow, } from './utils'; const DEFAULT_PAGE_SIZE = 25; +test.beforeEach(async ({page}) => { + await setupFakeNow(page); +}); + test('matches the screenshot', async ({page}) => { await gotoOverviewPageUrl(page, 'http://localhost:5555/'); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'overview-page'); }); test('matches the screenshot for mobile columns', async ({page}) => { @@ -38,7 +44,7 @@ test('matches the screenshot for mobile columns', async ({page}) => { 'experimental_chrome_android,experimental_firefox_android,experimental_safari_ios', ); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'overview-page-mobile'); }); test('screenshot for availability sort', async ({page}) => { @@ -47,7 +53,7 @@ test('screenshot for availability sort', async ({page}) => { 'http://localhost:5555/?sort=availability_chrome_asc', ); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'overview-page-sort'); }); test('screenshot for developer upvotes column', async ({page}) => { @@ -57,7 +63,11 @@ test('screenshot for developer upvotes column', async ({page}) => { 'availability_safari,chrome_usage,developer_signal_upvotes', ); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot( + page, + pageContainer, + 'overview-page-developer-upvotes', + ); }); test('shows an error that their query is invalid', async ({page}) => { @@ -68,7 +78,7 @@ test('shows an error that their query is invalid', async ({page}) => { expect(message).toContainText('Invalid query...'); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot('invalid-query.png'); + await expectDualThemeScreenshot(page, pageContainer, 'invalid-query'); }); test('shows an unknown error when there is an internal error', async ({ @@ -91,7 +101,7 @@ test('shows an unknown error when there is an internal error', async ({ expect(message).toContainText('Something went wrong...'); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot('internal-error.png'); + await expectDualThemeScreenshot(page, pageContainer, 'internal-error'); }); test('hides the Feature column', async ({page}) => { diff --git a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-chromium-linux.png index d96ef6392..1d9490961 100644 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-chromium-linux.png and b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-chromium-linux.png new file mode 100644 index 000000000..bb710d8b1 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-firefox-linux.png new file mode 100644 index 000000000..94e2d13c2 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-webkit-linux.png new file mode 100644 index 000000000..2b59bcef3 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-dark-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-firefox-linux.png index 49a929abd..0fb482f4f 100644 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-firefox-linux.png and b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-webkit-linux.png index 671b8cf83..f693e91f7 100644 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/internal-error-webkit-linux.png and b/e2e/tests/overview-page.spec.ts-snapshots/internal-error-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-chromium-linux.png index 4c2ee2ab7..70ec8ed95 100644 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-chromium-linux.png and b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-chromium-linux.png new file mode 100644 index 000000000..b7447a18b Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-firefox-linux.png new file mode 100644 index 000000000..e3e5b9adb Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-webkit-linux.png new file mode 100644 index 000000000..db5db384a Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-dark-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-firefox-linux.png index 7feb4dd98..ab2b719d4 100644 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-firefox-linux.png and b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-webkit-linux.png index cc456e1cd..8c34c1f91 100644 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-webkit-linux.png and b/e2e/tests/overview-page.spec.ts-snapshots/invalid-query-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png deleted file mode 100644 index e84b039d8..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png deleted file mode 100644 index 902ca3889..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png deleted file mode 100644 index 733117046..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-chromium-linux.png deleted file mode 100644 index ba611e818..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-firefox-linux.png deleted file mode 100644 index 25881e932..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-webkit-linux.png deleted file mode 100644 index 16ba40e74..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/matches-the-screenshot-for-mobile-columns-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-chromium-linux.png new file mode 100644 index 000000000..61aa36fb6 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-chromium-linux.png new file mode 100644 index 000000000..efa18d32f Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-firefox-linux.png new file mode 100644 index 000000000..e262707b6 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-webkit-linux.png new file mode 100644 index 000000000..13c805eb7 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-dark-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-chromium-linux.png new file mode 100644 index 000000000..9affb9ca9 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-chromium-linux.png new file mode 100644 index 000000000..e75fdb6e2 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-firefox-linux.png new file mode 100644 index 000000000..68a7ddfb3 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-webkit-linux.png new file mode 100644 index 000000000..12e8d2b5d Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-dark-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-firefox-linux.png new file mode 100644 index 000000000..2764f272a Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-webkit-linux.png new file mode 100644 index 000000000..c6b6b7891 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-developer-upvotes-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-firefox-linux.png new file mode 100644 index 000000000..0749ed4f3 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-chromium-linux.png new file mode 100644 index 000000000..c411b38e8 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-chromium-linux.png new file mode 100644 index 000000000..420f05bed Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-firefox-linux.png new file mode 100644 index 000000000..c5108b6de Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-webkit-linux.png new file mode 100644 index 000000000..306bbaaec Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-dark-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-firefox-linux.png new file mode 100644 index 000000000..de90d0c8e Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-webkit-linux.png new file mode 100644 index 000000000..905e76f77 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-mobile-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-chromium-linux.png new file mode 100644 index 000000000..233f29110 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-chromium-linux.png new file mode 100644 index 000000000..3a8bf5f56 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-chromium-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-firefox-linux.png new file mode 100644 index 000000000..66960ac13 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-webkit-linux.png new file mode 100644 index 000000000..051e12136 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-dark-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-firefox-linux.png new file mode 100644 index 000000000..07167b6a6 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-firefox-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-webkit-linux.png new file mode 100644 index 000000000..fcd762246 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-sort-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/overview-page-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-webkit-linux.png new file mode 100644 index 000000000..24ac28741 Binary files /dev/null and b/e2e/tests/overview-page.spec.ts-snapshots/overview-page-webkit-linux.png differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-chromium-linux.png deleted file mode 100644 index 00461980f..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-firefox-linux.png deleted file mode 100644 index 02b7b29d2..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-webkit-linux.png deleted file mode 100644 index 6ac6ba332..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-availability-sort-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-chromium-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-chromium-linux.png deleted file mode 100644 index 0ccb86fce..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-firefox-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-firefox-linux.png deleted file mode 100644 index c088a2c40..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-webkit-linux.png b/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-webkit-linux.png deleted file mode 100644 index 7aba88b69..000000000 Binary files a/e2e/tests/overview-page.spec.ts-snapshots/screenshot-for-developer-upvotes-column-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/sidebar.spec.ts b/e2e/tests/sidebar.spec.ts index fa00ffa7e..8407883f8 100644 --- a/e2e/tests/sidebar.spec.ts +++ b/e2e/tests/sidebar.spec.ts @@ -14,15 +14,17 @@ * limitations under the License. */ -import {test, expect} from '@playwright/test'; -import {loginAsUser} from './utils'; +import {test} from '@playwright/test'; +import {loginAsUser, expectDualThemeScreenshot} from './utils'; + +test.beforeEach(async () => {}); test('matches the screenshot', async ({page}) => { await page.goto('http://localhost:5555/'); // The sidebar menu should be shown by default. const sidebar = page.locator('webstatus-sidebar'); - await expect(sidebar).toHaveScreenshot('sidebar.png'); + await expectDualThemeScreenshot(page, sidebar, 'sidebar'); }); test('matches the screenshot for an authenticated user', async ({page}) => { @@ -31,5 +33,5 @@ test('matches the screenshot for an authenticated user', async ({page}) => { // The sidebar menu should be shown by default. const sidebar = page.locator('webstatus-sidebar'); - await expect(sidebar).toHaveScreenshot('sidebar-authenticated.png'); + await expectDualThemeScreenshot(page, sidebar, 'sidebar-authenticated'); }); diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-chromium-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-chromium-linux.png index a2b73c92b..3cc3cc76d 100644 Binary files a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-chromium-linux.png and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-chromium-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-chromium-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-chromium-linux.png new file mode 100644 index 000000000..f2ecc0878 Binary files /dev/null and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-chromium-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-firefox-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-firefox-linux.png new file mode 100644 index 000000000..948364db5 Binary files /dev/null and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-firefox-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-webkit-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-webkit-linux.png new file mode 100644 index 000000000..5ffb04933 Binary files /dev/null and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-dark-webkit-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-firefox-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-firefox-linux.png index 5c3423c50..20d1bdc67 100644 Binary files a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-firefox-linux.png and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-authenticated-firefox-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-chromium-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-chromium-linux.png index 4eaea5a31..8f56b3a06 100644 Binary files a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-chromium-linux.png and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-chromium-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-chromium-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-chromium-linux.png new file mode 100644 index 000000000..22603a893 Binary files /dev/null and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-chromium-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-firefox-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-firefox-linux.png new file mode 100644 index 000000000..96c0f32ee Binary files /dev/null and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-firefox-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-webkit-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-webkit-linux.png new file mode 100644 index 000000000..b3a9c41f7 Binary files /dev/null and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-dark-webkit-linux.png differ diff --git a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-firefox-linux.png b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-firefox-linux.png index 7a8f0892b..17dba475c 100644 Binary files a/e2e/tests/sidebar.spec.ts-snapshots/sidebar-firefox-linux.png and b/e2e/tests/sidebar.spec.ts-snapshots/sidebar-firefox-linux.png differ diff --git a/e2e/tests/stats-page.spec.ts b/e2e/tests/stats-page.spec.ts index 44f288be5..074b9d759 100644 --- a/e2e/tests/stats-page.spec.ts +++ b/e2e/tests/stats-page.spec.ts @@ -15,7 +15,7 @@ */ import {test, expect, Page} from '@playwright/test'; -import {setupFakeNow} from './utils'; +import {setupFakeNow, expectDualThemeScreenshot} from './utils'; async function waitForAllChartsToLoad(page: Page) { // Wait for all charts to finish loading. @@ -39,5 +39,5 @@ test('matches the screenshot', async ({page}) => { await waitForAllChartsToLoad(page); const pageContainer = page.locator('.page-container'); - await expect(pageContainer).toHaveScreenshot(); + await expectDualThemeScreenshot(page, pageContainer, 'stats-page'); }); diff --git a/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png deleted file mode 100644 index 0fd352313..000000000 Binary files a/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-chromium-linux.png and /dev/null differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png deleted file mode 100644 index 40124d999..000000000 Binary files a/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-firefox-linux.png and /dev/null differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png deleted file mode 100644 index 5ced50719..000000000 Binary files a/e2e/tests/stats-page.spec.ts-snapshots/matches-the-screenshot-1-webkit-linux.png and /dev/null differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/stats-page-chromium-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-chromium-linux.png new file mode 100644 index 000000000..da5e57f22 Binary files /dev/null and b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-chromium-linux.png differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-chromium-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-chromium-linux.png new file mode 100644 index 000000000..dd6b492dc Binary files /dev/null and b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-chromium-linux.png differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-firefox-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-firefox-linux.png new file mode 100644 index 000000000..3b3e19045 Binary files /dev/null and b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-firefox-linux.png differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-webkit-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-webkit-linux.png new file mode 100644 index 000000000..03d25ae87 Binary files /dev/null and b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-dark-webkit-linux.png differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/stats-page-firefox-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-firefox-linux.png new file mode 100644 index 000000000..0a8ee1c0b Binary files /dev/null and b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-firefox-linux.png differ diff --git a/e2e/tests/stats-page.spec.ts-snapshots/stats-page-webkit-linux.png b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-webkit-linux.png new file mode 100644 index 000000000..540c86794 Binary files /dev/null and b/e2e/tests/stats-page.spec.ts-snapshots/stats-page-webkit-linux.png differ diff --git a/e2e/tests/utils.ts b/e2e/tests/utils.ts index 2938e1836..4074e7a7c 100644 --- a/e2e/tests/utils.ts +++ b/e2e/tests/utils.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import {Page, expect} from '@playwright/test'; +import {Page, expect, type Locator} from '@playwright/test'; import {execSync} from 'child_process'; import path from 'node:path'; import {fileURLToPath} from 'node:url'; @@ -23,6 +23,35 @@ const DEFAULT_FAKE_NOW = 'Dec 1 2020 12:34:56'; export const BASE_URL = 'http://localhost:5555'; +export async function forceTheme(page: Page, theme: 'light' | 'dark') { + await page.addInitScript(theme => { + localStorage.setItem('webstatus-theme', theme); + }, theme); + await page.emulateMedia({colorScheme: theme}); +} + +/** + * Captures screenshots for both light and dark themes. + * Resets the theme to light after capturing. + */ +export async function expectDualThemeScreenshot( + page: Page, + locator: Locator | Page, + name: string, + options?: Parameters[0], +) { + // 1. Ensure light theme and capture + await forceTheme(page, 'light'); + await expect(locator).toHaveScreenshot(`${name}.png`, options); + + // 2. Change to dark theme and capture + await forceTheme(page, 'dark'); + await expect(locator).toHaveScreenshot(`${name}-dark.png`, options); + + // 3. Reset to light for subsequent tests + await forceTheme(page, 'light'); +} + export async function setupFakeNow( page: Page, fakeNowDateString = DEFAULT_FAKE_NOW, diff --git a/frontend/src/static/img/shoelace/assets/icons/moon.svg b/frontend/src/static/img/shoelace/assets/icons/moon.svg new file mode 100644 index 000000000..46458ecfb --- /dev/null +++ b/frontend/src/static/img/shoelace/assets/icons/moon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/src/static/img/shoelace/assets/icons/sun.svg b/frontend/src/static/img/shoelace/assets/icons/sun.svg new file mode 100644 index 000000000..3777f070f --- /dev/null +++ b/frontend/src/static/img/shoelace/assets/icons/sun.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/frontend/src/static/js/components/test/webstatus-theme-button.test.ts b/frontend/src/static/js/components/test/webstatus-theme-button.test.ts new file mode 100644 index 000000000..d1388a4c8 --- /dev/null +++ b/frontend/src/static/js/components/test/webstatus-theme-button.test.ts @@ -0,0 +1,76 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {expect, fixture, html} from '@open-wc/testing'; +import {WebstatusThemeButton} from '../webstatus-theme-button.js'; +import '../webstatus-theme-button.js'; +import sinon from 'sinon'; + +describe('webstatus-theme-button', () => { + it('renders correctly with light theme', async () => { + const component = await fixture( + html``, + ); + const iconButton = component.shadowRoot?.querySelector('sl-icon-button'); + expect(iconButton).to.exist; + expect(iconButton?.getAttribute('name')).to.equal('moon'); + expect(iconButton?.getAttribute('label')).to.equal('Switch to dark theme'); + + const tooltip = component.shadowRoot?.querySelector('sl-tooltip'); + expect(tooltip?.getAttribute('content')).to.equal('Switch to dark theme'); + }); + + it('renders correctly with dark theme', async () => { + const component = await fixture( + html``, + ); + const iconButton = component.shadowRoot?.querySelector('sl-icon-button'); + expect(iconButton).to.exist; + expect(iconButton?.getAttribute('name')).to.equal('sun'); + expect(iconButton?.getAttribute('label')).to.equal('Switch to light theme'); + + const tooltip = component.shadowRoot?.querySelector('sl-tooltip'); + expect(tooltip?.getAttribute('content')).to.equal('Switch to light theme'); + }); + + it('renders correctly when theme is detecting (undefined)', async () => { + const component = await fixture( + html``, + ); + const iconButton = component.shadowRoot?.querySelector('sl-icon-button'); + expect(iconButton).to.exist; + expect(iconButton?.getAttribute('name')).to.equal('moon'); + expect(iconButton?.getAttribute('label')).to.equal('Detecting theme...'); + + const tooltip = component.shadowRoot?.querySelector('sl-tooltip'); + expect(tooltip?.getAttribute('content')).to.equal('Detecting theme...'); + }); + + it('dispatches theme-toggle event when clicked', async () => { + const component = await fixture( + html``, + ); + const toggleSpy = sinon.spy(); + component.addEventListener('theme-toggle', toggleSpy); + + const iconButton = component.shadowRoot?.querySelector('sl-icon-button'); + iconButton?.click(); + + expect(toggleSpy).to.have.been.calledOnce; + }); +}); diff --git a/frontend/src/static/js/components/webstatus-feature-gone-split-page.ts b/frontend/src/static/js/components/webstatus-feature-gone-split-page.ts index e06215859..11cc0eaf4 100644 --- a/frontend/src/static/js/components/webstatus-feature-gone-split-page.ts +++ b/frontend/src/static/js/components/webstatus-feature-gone-split-page.ts @@ -86,7 +86,7 @@ export class WebstatusFeatureGoneSplitPage extends LitElement { display: flex; } #error-status-code { - color: #2563eb; + color: var(--status-code-color); font-size: 15px; font-weight: 700; line-height: 22.5px; @@ -99,7 +99,7 @@ export class WebstatusFeatureGoneSplitPage extends LitElement { gap: var(--content-padding); } #error-headline { - color: #1d2430; + color: var(--heading-color); font-size: 32px; font-weight: 700; word-wrap: break-word; @@ -112,7 +112,7 @@ export class WebstatusFeatureGoneSplitPage extends LitElement { } .error-message { - color: #6c7381; + color: var(--unimportant-text-color); } .new-features-container { text-align: left; @@ -120,7 +120,7 @@ export class WebstatusFeatureGoneSplitPage extends LitElement { max-width: 400px; } .new-results-header { - color: #1a1a1a; + color: var(--default-color); font-weight: 500; margin-bottom: 6px; } @@ -134,12 +134,12 @@ export class WebstatusFeatureGoneSplitPage extends LitElement { } .feature-list li a { text-decoration: none; - color: #007bff; + color: var(--link-color); font-weight: 500; } .feature-list li a:hover { text-decoration: underline; - color: #0056b3; + color: var(--link-hover-color); } `, ]; diff --git a/frontend/src/static/js/components/webstatus-feature-page.ts b/frontend/src/static/js/components/webstatus-feature-page.ts index 12c0bec29..c76e8a5d6 100644 --- a/frontend/src/static/js/components/webstatus-feature-page.ts +++ b/frontend/src/static/js/components/webstatus-feature-page.ts @@ -103,7 +103,7 @@ export class FeaturePage extends BaseChartsPage { SHARED_STYLES, css` .crumbs { - color: #aaa; + color: var(--unimportant-text-color); } .crumbs a { text-decoration: none; diff --git a/frontend/src/static/js/components/webstatus-gchart.ts b/frontend/src/static/js/components/webstatus-gchart.ts index 3328941ed..f23fc3f71 100644 --- a/frontend/src/static/js/components/webstatus-gchart.ts +++ b/frontend/src/static/js/components/webstatus-gchart.ts @@ -19,16 +19,17 @@ import {consume} from '@lit/context'; import { + CSSResultGroup, LitElement, + PropertyValues, type TemplateResult, - type CSSResultGroup, css, html, - PropertyValues, nothing, } from 'lit'; import {customElement, property, state} from 'lit/decorators.js'; import {gchartsContext} from '../contexts/gcharts-context.js'; +import {themeContext, type Theme} from '../contexts/theme-context.js'; import {TaskStatus} from '@lit/task'; import {classMap} from 'lit/directives/class-map.js'; @@ -67,6 +68,10 @@ export class WebstatusGChart extends LitElement { @property({attribute: false}) gchartsLibraryLoaded?: boolean; + @consume({context: themeContext, subscribe: true}) + @property({attribute: false}) + theme: Theme = 'light'; + private _pendingDataObj: WebStatusDataObj | undefined; // Properties for chartwrapper spec fields. @@ -189,6 +194,48 @@ export class WebstatusGChart extends LitElement { augmentOptions( options: google.visualization.ComboChartOptions, ): google.visualization.ComboChartOptions { + const isDark = this.theme === 'dark'; + const textColor = isDark ? '#e2e8f0' : '#0f172a'; + const gridlineColor = + this.theme === 'dark' ? 'rgba(255, 255, 255, 0.05)' : '#ccc'; + + const chartArea = options.chartArea || {}; + const hAxis = options.hAxis || {}; + const vAxis = options.vAxis || {}; + const legend = typeof options.legend === 'object' ? options.legend : {}; + + options = { + ...options, + titleTextStyle: { + ...(options.titleTextStyle || {}), + color: textColor, + }, + backgroundColor: 'transparent', + chartArea: { + ...chartArea, + backgroundColor: 'transparent', + }, + hAxis: { + ...hAxis, + titleTextStyle: {...hAxis.titleTextStyle, color: textColor}, + textStyle: {...hAxis.textStyle, color: textColor}, + gridlines: {...hAxis.gridlines, color: gridlineColor}, + }, + vAxis: { + ...vAxis, + titleTextStyle: {...vAxis.titleTextStyle, color: textColor}, + textStyle: {...vAxis.textStyle, color: textColor}, + gridlines: {...vAxis.gridlines, color: gridlineColor}, + }, + legend: + typeof options.legend === 'object' + ? { + ...legend, + textStyle: {...legend.textStyle, color: textColor}, + } + : options.legend, + }; + if (!this.hasMax) { options = { ...options, @@ -222,7 +269,7 @@ export class WebstatusGChart extends LitElement { const seriesOptions = options.series || {}; seriesOptions[totalSeriesIndex] = { type: 'area', - areaOpacity: 0.08, + areaOpacity: isDark ? 0.15 : 0.08, // Slightly more opaque in dark mode opacity: 0.25, lineWidth: 0.2, pointSize: pointSize, diff --git a/frontend/src/static/js/components/webstatus-header.ts b/frontend/src/static/js/components/webstatus-header.ts index b2c43ac38..da453916e 100644 --- a/frontend/src/static/js/components/webstatus-header.ts +++ b/frontend/src/static/js/components/webstatus-header.ts @@ -25,6 +25,7 @@ import {customElement} from 'lit/decorators.js'; import {SHARED_STYLES} from '../css/shared-css.js'; import './webstatus-login.js'; +import './webstatus-theme-button.js'; @customElement('webstatus-header') export class WebstatusHeader extends LitElement { @@ -35,8 +36,9 @@ export class WebstatusHeader extends LitElement { header { flex-grow: 1; /* .hbox > .halign-stretch */ align-items: center; - border-bottom: 1px solid #e1e3e8; + border-bottom: var(--default-border); height: 94px; + background-color: var(--header-background); } .title { display: flex; @@ -45,7 +47,7 @@ export class WebstatusHeader extends LitElement { .website-logo { width: 31px; height: 31px; - background-color: #ccc; + background-color: var(--color-highlight-2); margin-left: 1em; margin-top: auto; margin-bottom: auto; @@ -54,7 +56,7 @@ export class WebstatusHeader extends LitElement { .website-title { font-weight: 700; font-size: 24px; - color: #1f1f1f; + color: var(--default-color); margin-left: 5px; margin-top: auto; margin-bottom: auto; @@ -68,6 +70,11 @@ export class WebstatusHeader extends LitElement { webstatus-login { padding: var(--content-padding); } + + .theme-toggle { + margin-right: var(--content-padding); + font-size: 1.5rem; + } `, ]; } @@ -103,6 +110,7 @@ export class WebstatusHeader extends LitElement {
+ `; diff --git a/frontend/src/static/js/components/webstatus-line-chart-panel.ts b/frontend/src/static/js/components/webstatus-line-chart-panel.ts index afe88a109..4b1e6e5e3 100644 --- a/frontend/src/static/js/components/webstatus-line-chart-panel.ts +++ b/frontend/src/static/js/components/webstatus-line-chart-panel.ts @@ -29,6 +29,7 @@ import {Task} from '@lit/task'; import {APIClient, apiClientContext} from '../contexts/api-client-context.js'; import {consume} from '@lit/context'; import {SHARED_STYLES} from '../css/shared-css.js'; +import {themeContext, type Theme} from '../contexts/theme-context.js'; /** * Interface defining the structure of metric data for the line chart. @@ -188,6 +189,10 @@ export abstract class WebstatusLineChartPanel extends LitElement { @consume({context: apiClientContext}) apiClient!: APIClient; + @consume({context: themeContext, subscribe: true}) + @state() + theme: Theme = 'light'; + /** * The Lit task for managing the asynchronous data loading process. * Subclasses must implement this method to define how data is fetched. @@ -294,6 +299,7 @@ export abstract class WebstatusLineChartPanel extends LitElement { .chart-description { font-size: 14px; font-style: italic; + color: var(--unimportant-text-color); } .datapoint-details-panel { @@ -477,16 +483,18 @@ export abstract class WebstatusLineChartPanel extends LitElement { ); // Add one day to this.endDate. const endDate = new Date(this.endDate.getTime() + 1000 * 60 * 60 * 24); + const isDark = this.theme === 'dark'; const options: google.visualization.LineChartOptions = { height: 300, // This is necessary to avoid shrinking to 0 or 18px. hAxis: { title: '', - titleTextStyle: {color: '#333'}, + titleTextStyle: {color: isDark ? '#fff' : '#333'}, viewWindow: {min: this.startDate, max: endDate}, }, vAxis: { minValue: 0, title: vAxisTitle, + titleTextStyle: {color: isDark ? '#fff' : '#333'}, format: '#,###', }, legend: {position: 'top'}, @@ -817,7 +825,10 @@ export abstract class WebstatusLineChartPanel extends LitElement { render(): TemplateResult { return html` - +
${this.getPanelText()}
diff --git a/frontend/src/static/js/components/webstatus-notfound-error-page.ts b/frontend/src/static/js/components/webstatus-notfound-error-page.ts index 2446da02a..6a65e8d78 100644 --- a/frontend/src/static/js/components/webstatus-notfound-error-page.ts +++ b/frontend/src/static/js/components/webstatus-notfound-error-page.ts @@ -97,7 +97,7 @@ export class WebstatusNotFoundErrorPage extends LitElement { display: flex; } #error-status-code { - color: #2563eb; + color: var(--status-code-color); font-size: 15px; font-weight: 700; line-height: 22.5px; @@ -110,7 +110,7 @@ export class WebstatusNotFoundErrorPage extends LitElement { gap: var(--content-padding); } #error-headline { - color: #1d2430; + color: var(--heading-color); font-size: 32px; font-weight: 700; word-wrap: break-word; @@ -123,7 +123,7 @@ export class WebstatusNotFoundErrorPage extends LitElement { } .error-message { - color: #6c7381; + color: var(--unimportant-text-color); } .similar-features-container { text-align: left; @@ -131,7 +131,7 @@ export class WebstatusNotFoundErrorPage extends LitElement { max-width: 400px; } .similar-results-header { - color: #1a1a1a; + color: var(--default-color); font-weight: 500; margin-bottom: 6px; } @@ -145,12 +145,12 @@ export class WebstatusNotFoundErrorPage extends LitElement { } .feature-list li a { text-decoration: none; - color: #007bff; + color: var(--link-color); font-weight: 500; } .feature-list li a:hover { text-decoration: underline; - color: #0056b3; + color: var(--link-hover-color); } `, ]; diff --git a/frontend/src/static/js/components/webstatus-notification-email-channels.ts b/frontend/src/static/js/components/webstatus-notification-email-channels.ts index ee31d991e..fa8c5f9a5 100644 --- a/frontend/src/static/js/components/webstatus-notification-email-channels.ts +++ b/frontend/src/static/js/components/webstatus-notification-email-channels.ts @@ -19,39 +19,43 @@ import {customElement, property} from 'lit/decorators.js'; import {repeat} from 'lit/directives/repeat.js'; import {components} from 'webstatus.dev-backend'; import './webstatus-notification-panel.js'; +import {SHARED_STYLES} from '../css/shared-css.js'; type NotificationChannelResponse = components['schemas']['NotificationChannelResponse']; @customElement('webstatus-notification-email-channels') export class WebstatusNotificationEmailChannels extends LitElement { - static styles = css` - .channel-item { - background-color: #f9f9f9; - display: flex; - align-items: center; - justify-content: space-between; - padding: 8px 16px; - border-bottom: 1px solid #e4e4e7; - } + static styles = [ + SHARED_STYLES, + css` + .channel-item { + color: var(--default-color); + display: flex; + align-items: center; + justify-content: space-between; + padding: 8px 16px; + border-bottom: 1px solid var(--border-color); + } - .channel-item:last-child { - border-bottom: none; - } + .channel-item:last-child { + border-bottom: none; + } - .channel-info { - display: flex; - flex-direction: column; - } + .channel-info { + display: flex; + flex-direction: column; + } - .channel-info .name { - font-size: 14px; - } + .channel-info .name { + font-size: 14px; + } - .info-icon-button { - font-size: 1.2rem; - } - `; + .info-icon-button { + font-size: 1.2rem; + } + `, + ]; @property({type: Array}) channels: NotificationChannelResponse[] = []; diff --git a/frontend/src/static/js/components/webstatus-notification-rss-channels.ts b/frontend/src/static/js/components/webstatus-notification-rss-channels.ts index a7d25d04b..3f932c37c 100644 --- a/frontend/src/static/js/components/webstatus-notification-rss-channels.ts +++ b/frontend/src/static/js/components/webstatus-notification-rss-channels.ts @@ -23,7 +23,7 @@ export class WebstatusNotificationRssChannels extends LitElement { static styles = css` .card-body { padding: 20px; - color: #71717a; + color: var(--unimportant-text-color); } `; diff --git a/frontend/src/static/js/components/webstatus-notification-webhook-channels.ts b/frontend/src/static/js/components/webstatus-notification-webhook-channels.ts index ac02f9b0a..a78be6c55 100644 --- a/frontend/src/static/js/components/webstatus-notification-webhook-channels.ts +++ b/frontend/src/static/js/components/webstatus-notification-webhook-channels.ts @@ -23,7 +23,7 @@ export class WebstatusNotificationWebhookChannels extends LitElement { static styles = css` .card-body { padding: 20px; - color: #71717a; + color: var(--unimportant-text-color); } `; diff --git a/frontend/src/static/js/components/webstatus-overview-table.ts b/frontend/src/static/js/components/webstatus-overview-table.ts index eb68359fd..89b46ba21 100644 --- a/frontend/src/static/js/components/webstatus-overview-table.ts +++ b/frontend/src/static/js/components/webstatus-overview-table.ts @@ -141,7 +141,7 @@ export class WebstatusOverviewTable extends LitElement { } .sortable-icon { - color: gray; + color: var(--unimportant-text-color); opacity: 70%; } img.platform { diff --git a/frontend/src/static/js/components/webstatus-page.ts b/frontend/src/static/js/components/webstatus-page.ts index da58d888b..8a94e7218 100644 --- a/frontend/src/static/js/components/webstatus-page.ts +++ b/frontend/src/static/js/components/webstatus-page.ts @@ -42,7 +42,7 @@ export class WebstatusPage extends LitElement { #sidebar-drawer { max-width: ${DRAWER_WIDTH_PX}px; - border-right: 1px solid #e1e3e8; + border-right: var(--default-border); flex-shrink: 0; } #sidebar-drawer:not([open]), diff --git a/frontend/src/static/js/components/webstatus-services-container.ts b/frontend/src/static/js/components/webstatus-services-container.ts index 2a5ee38cc..f321217f0 100644 --- a/frontend/src/static/js/components/webstatus-services-container.ts +++ b/frontend/src/static/js/components/webstatus-services-container.ts @@ -23,6 +23,7 @@ import '../services/webstatus-firebase-auth-service.js'; import '../services/webstatus-gcharts-loader-service.js'; import '../services/webstatus-api-client-service.js'; import '../services/webstatus-bookmarks-service.js'; +import '../services/webstatus-theme-service.js'; /** * WebstatusServiceContainer: Centralized container for web status services. @@ -57,7 +58,9 @@ export class WebstatusServicesContainer extends LitElement { .settings="${this.settings.firebase.auth}" > - + + + diff --git a/frontend/src/static/js/components/webstatus-theme-button.ts b/frontend/src/static/js/components/webstatus-theme-button.ts new file mode 100644 index 000000000..a991739d3 --- /dev/null +++ b/frontend/src/static/js/components/webstatus-theme-button.ts @@ -0,0 +1,68 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {consume} from '@lit/context'; +import {LitElement, css, html} from 'lit'; +import {customElement, state} from 'lit/decorators.js'; +import {themeContext, Theme} from '../contexts/theme-context.js'; + +@customElement('webstatus-theme-button') +export class WebstatusThemeButton extends LitElement { + static styles = css` + .theme-toggle { + margin-right: var(--content-padding); + font-size: 1.5rem; + } + `; + + @consume({context: themeContext, subscribe: true}) + @state() + theme: Theme | undefined; + + _fireEvent(eventName: string, detail: CustomEventInit | undefined): void { + const event = new CustomEvent(eventName, { + bubbles: true, + composed: true, + detail, + }); + this.dispatchEvent(event); + } + + handleThemeToggle(): void { + this._fireEvent('theme-toggle', {}); + } + + render() { + const isDark = this.theme === 'dark'; + const detectingTheme = this.theme === undefined; + let themeBtnLabel = ''; + if (detectingTheme) { + themeBtnLabel = 'Detecting theme...'; + } else { + themeBtnLabel = isDark ? 'Switch to light theme' : 'Switch to dark theme'; + } + return html` + + + + `; + } +} diff --git a/frontend/src/static/js/components/webstatus-typeahead.ts b/frontend/src/static/js/components/webstatus-typeahead.ts index 7d9c8cba9..41217ad24 100644 --- a/frontend/src/static/js/components/webstatus-typeahead.ts +++ b/frontend/src/static/js/components/webstatus-typeahead.ts @@ -434,7 +434,7 @@ export class WebstatusTypeaheadItem extends LitElement { font-weight: var(--sl-font-weight-normal); line-height: var(--sl-line-height-normal); letter-spacing: var(--sl-letter-spacing-normal); - color: var(--sl-color-neutral-700); + color: var(--default-color); padding: var(--sl-spacing-2x-small) var(--sl-spacing-2x-small); transition: var(--sl-transition-fast) fill; user-select: none; @@ -445,7 +445,8 @@ export class WebstatusTypeaheadItem extends LitElement { .active { outline: none; - background-color: var(--sl-color-primary-200); + background-color: var(--color-primary); + color: white; opacity: 1; } #value { @@ -454,7 +455,8 @@ export class WebstatusTypeaheadItem extends LitElement { } code { font-size: 85%; - background: #eee; + background: var(--color-highlight-2); + color: var(--default-color); padding: var(--content-padding-quarter); } `, diff --git a/frontend/src/static/js/contexts/theme-context.ts b/frontend/src/static/js/contexts/theme-context.ts new file mode 100644 index 000000000..daf7c2cf3 --- /dev/null +++ b/frontend/src/static/js/contexts/theme-context.ts @@ -0,0 +1,21 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {createContext} from '@lit/context'; + +export type Theme = 'light' | 'dark'; + +export const themeContext = createContext('theme'); diff --git a/frontend/src/static/js/css/_theme-css.ts b/frontend/src/static/js/css/_theme-css.ts index 4886081a8..c7ca659a4 100644 --- a/frontend/src/static/js/css/_theme-css.ts +++ b/frontend/src/static/js/css/_theme-css.ts @@ -18,19 +18,20 @@ import {css} from 'lit'; export const THEME = css` :host { + /* Base Variables - Using semantic Shoelace variables that auto-toggle globally */ --color-primary: var(--sl-color-primary-600); --color-strong-primary: var(--sl-color-primary-800); - --color-strongest: var(--sl-color-gray-900); - --color-strong: var(--sl-color-gray-600); - --color-medium: var(--sl-color-gray-400); - --color-light: var(--sl-color-gray-200); - --color-lightest: var(--sl-color-gray-50); - --color-background: white; - --color-highlight-1: var(--sl-color-gray-100); - --color-highlight-2: var(--sl-color-gray-300); - - --color-gray-bg: var(--sl-color-gray-100); - --color-gray-fg: var(--sl-color-gray-600); + --color-strongest: var(--sl-color-neutral-900); + --color-strong: var(--sl-color-neutral-600); + --color-medium: var(--sl-color-neutral-400); + --color-light: var(--sl-color-neutral-200); + --color-lightest: var(--sl-color-neutral-50); + --color-background: var(--sl-color-neutral-0); + --color-highlight-1: var(--sl-color-neutral-100); + --color-highlight-2: var(--sl-color-neutral-300); + + --color-gray-bg: var(--sl-color-neutral-100); + --color-gray-fg: var(--sl-color-neutral-600); --color-green-bg: var(--sl-color-green-100); --color-green-fg: var(--sl-color-green-600); --color-blue-bg: var(--sl-color-blue-100); @@ -38,11 +39,14 @@ export const THEME = css` --color-red-bg: var(--sl-color-red-100); --color-red-fg: var(--sl-color-red-600); --color-yellow-fg: var(--sl-color-yellow-800); - } + --border-color: var(--color-light); + --header-background: var(--color-background); + --heading-color: var(--color-strongest); + --heading-background: transparent; + --status-code-color: var(--color-primary); - :host { --default-color: var(--color-strongest); - --unimportant-text-color: var(--color-strong); + --unimportant-text-color: var(--sl-color-neutral-700); --content-padding-large: 24px; --content-padding: 16px; @@ -58,9 +62,10 @@ export const THEME = css` --browser-logo-size: 24px; --platform-logo-size: 18px; - --default-border: 1px solid var(--color-light); + --default-border-color: var(--border-color); + --default-border: 1px solid var(--default-border-color); - --card-background: white; + --card-background: var(--sl-color-neutral-0); --card-border-width: 1px; --card-border-color: var(--color-light); --card-radius: var(--border-radius); @@ -90,8 +95,32 @@ export const THEME = css` --chip-background-unchanged: var(--color-gray-bg); --chip-color-unchanged: var(--color-gray-fg); --chip-background-increased: var(--color-green-bg); - --chip-color-incresed: var(--color-green-fg); + --chip-color-increased: var(--color-green-fg); --chip-background-decreased: var(--color-red-bg); - --chip-color-decresed: var(--color-red-fg); + --chip-color-decreased: var(--color-red-fg); + } + + /* Specific Overrides for Dark Mode */ + :host-context(.sl-theme-dark), + :host(.sl-theme-dark), + .sl-theme-dark { + --color-primary: var(--sl-color-primary-500); + --color-strong-primary: var(--sl-color-primary-400); + + /* Dark mode variants for color chips */ + --color-green-bg: var(--sl-color-green-900); + --color-green-fg: var(--sl-color-green-400); + --color-blue-bg: var(--sl-color-blue-900); + --color-blue-fg: var(--sl-color-blue-400); + --color-red-bg: var(--sl-color-red-900); + --color-red-fg: var(--sl-color-red-400); + --color-yellow-fg: var(--sl-color-yellow-400); + + --header-background: transparent; + --heading-color: var(--sl-color-neutral-1000); + --default-color: var(--sl-color-neutral-1000); + + --link-color: var(--sl-color-primary-400); + --link-hover-color: var(--sl-color-primary-300); } `; diff --git a/frontend/src/static/js/css/shared-css.ts b/frontend/src/static/js/css/shared-css.ts index 25b47fadb..551bdbec9 100644 --- a/frontend/src/static/js/css/shared-css.ts +++ b/frontend/src/static/js/css/shared-css.ts @@ -77,6 +77,7 @@ export const SHARED_STYLES = [ font-weight: 300; } + h1, h2, h3, h4 { @@ -107,7 +108,7 @@ export const SHARED_STYLES = [ } sl-details::part(base) { - background: var(--card-background); + background: var(--header-background); border: none; } diff --git a/frontend/src/static/js/index.ts b/frontend/src/static/js/index.ts index 98869850a..6ec2910f5 100644 --- a/frontend/src/static/js/index.ts +++ b/frontend/src/static/js/index.ts @@ -37,6 +37,7 @@ import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js'; import '@shoelace-style/shoelace/dist/components/tree/tree.js'; import '@shoelace-style/shoelace/dist/components/tree-item/tree-item.js'; import '@shoelace-style/shoelace/dist/themes/light.css'; +import '@shoelace-style/shoelace/dist/themes/dark.css'; import {setBasePath} from '@shoelace-style/shoelace/dist/utilities/base-path.js'; import {registerIconLibrary} from '@shoelace-style/shoelace/dist/utilities/icon-library.js'; diff --git a/frontend/src/static/js/services/test/webstatus-theme-service.test.ts b/frontend/src/static/js/services/test/webstatus-theme-service.test.ts new file mode 100644 index 000000000..55396b5a3 --- /dev/null +++ b/frontend/src/static/js/services/test/webstatus-theme-service.test.ts @@ -0,0 +1,141 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {LitElement, html} from 'lit'; +import {customElement, state} from 'lit/decorators.js'; +import {consume} from '@lit/context'; +import {themeContext, type Theme} from '../../contexts/theme-context.js'; +import {WebstatusThemeService} from '../webstatus-theme-service.js'; +import {fixture, expect} from '@open-wc/testing'; +import '../webstatus-theme-service.js'; +import sinon from 'sinon'; + +@customElement('test-theme-consumer') +class TestThemeConsumer extends LitElement { + @consume({context: themeContext, subscribe: true}) + @state() + theme?: Theme; + + render() { + return html`
${this.theme}
`; + } +} + +describe('webstatus-theme-service', () => { + let matchMediaStub: sinon.SinonStub; + + beforeEach(() => { + localStorage.clear(); + matchMediaStub = sinon.stub(window, 'matchMedia'); + matchMediaStub.returns({ + matches: false, + addEventListener: () => {}, + removeEventListener: () => {}, + }); + document.documentElement.classList.remove('sl-theme-dark'); + }); + + afterEach(() => { + matchMediaStub.restore(); + }); + + it('can be added to the page and provides light theme by default', async () => { + const el = await fixture(html` + + + + `); + const consumer = el.querySelector('test-theme-consumer'); + expect(el).to.exist; + expect(consumer).to.exist; + expect(consumer!.theme).to.equal('light'); + expect(document.documentElement.classList.contains('sl-theme-dark')).to.be + .false; + expect(document.documentElement.classList.contains('sl-theme-light')).to.be + .true; + }); + + it('provides dark theme if system preference is dark', async () => { + matchMediaStub.returns({ + matches: true, + addEventListener: () => {}, + removeEventListener: () => {}, + }); + const el = await fixture(html` + + + + `); + const consumer = el.querySelector('test-theme-consumer'); + expect(consumer!.theme).to.equal('dark'); + expect(document.documentElement.classList.contains('sl-theme-dark')).to.be + .true; + expect(document.documentElement.classList.contains('sl-theme-light')).to.be + .false; + }); + + it('prefers saved theme from localStorage', async () => { + localStorage.setItem('webstatus-theme', 'dark'); + matchMediaStub.returns({ + matches: false, // system is light + addEventListener: () => {}, + removeEventListener: () => {}, + }); + const el = await fixture(html` + + + + `); + const consumer = el.querySelector('test-theme-consumer'); + expect(consumer!.theme).to.equal('dark'); + expect(document.documentElement.classList.contains('sl-theme-dark')).to.be + .true; + expect(document.documentElement.classList.contains('sl-theme-light')).to.be + .false; + }); + + it('toggles theme on toggle-theme event', async () => { + const el = await fixture(html` + + + + `); + const consumer = el.querySelector('test-theme-consumer'); + + expect(consumer!.theme).to.equal('light'); + + el.dispatchEvent( + new CustomEvent('theme-toggle', {bubbles: true, composed: true}), + ); + + expect(consumer!.theme).to.equal('dark'); + expect(document.documentElement.classList.contains('sl-theme-dark')).to.be + .true; + expect(document.documentElement.classList.contains('sl-theme-light')).to.be + .false; + expect(localStorage.getItem('webstatus-theme')).to.equal('dark'); + + el.dispatchEvent( + new CustomEvent('theme-toggle', {bubbles: true, composed: true}), + ); + expect(consumer!.theme).to.equal('light'); + expect(document.documentElement.classList.contains('sl-theme-dark')).to.be + .false; + expect(document.documentElement.classList.contains('sl-theme-light')).to.be + .true; + expect(localStorage.getItem('webstatus-theme')).to.equal('light'); + }); +}); diff --git a/frontend/src/static/js/services/webstatus-theme-service.ts b/frontend/src/static/js/services/webstatus-theme-service.ts new file mode 100644 index 000000000..21bc42109 --- /dev/null +++ b/frontend/src/static/js/services/webstatus-theme-service.ts @@ -0,0 +1,89 @@ +/** + * Copyright 2026 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import {provide} from '@lit/context'; +import {customElement, state} from 'lit/decorators.js'; +import {themeContext, type Theme} from '../contexts/theme-context.js'; +import {ServiceElement} from './service-element.js'; + +const THEME_STORAGE_KEY = 'webstatus-theme'; + +@customElement('webstatus-theme-service') +export class WebstatusThemeService extends ServiceElement { + @provide({context: themeContext}) + @state() + theme: Theme = 'light'; + + willUpdate() { + this.applyTheme(this.getInitialTheme()); + } + + connectedCallback() { + super.connectedCallback(); + this.addEventListener('theme-toggle', this.handleThemeToggle); + + // Listen for system theme changes + window + .matchMedia('(prefers-color-scheme: dark)') + .addEventListener('change', this.handleSystemThemeChange); + } + + disconnectedCallback() { + this.removeEventListener('theme-toggle', this.handleThemeToggle); + window + .matchMedia('(prefers-color-scheme: dark)') + .removeEventListener('change', this.handleSystemThemeChange); + super.disconnectedCallback(); + } + + private getInitialTheme(): Theme { + const savedTheme = localStorage.getItem(THEME_STORAGE_KEY); + if (savedTheme === 'light' || savedTheme === 'dark') { + return savedTheme; + } + return window.matchMedia('(prefers-color-scheme: dark)').matches + ? 'dark' + : 'light'; + } + + private handleThemeToggle = () => { + const newTheme = this.theme === 'light' ? 'dark' : 'light'; + this.applyTheme(newTheme); + localStorage.setItem(THEME_STORAGE_KEY, newTheme); + this.requestUpdate(); + }; + + private handleSystemThemeChange = (e: MediaQueryListEvent) => { + // Only auto-switch if user hasn't set a preference? + // For now, let's just stick to the current theme unless toggled. + // Or if we want to follow system by default if no storage exists. + if (!localStorage.getItem(THEME_STORAGE_KEY)) { + const newTheme = e.matches ? 'dark' : 'light'; + this.applyTheme(newTheme); + } + }; + + private applyTheme(theme: Theme) { + if (theme === 'dark') { + document.documentElement.classList.add('sl-theme-dark'); + document.documentElement.classList.remove('sl-theme-light'); + } else { + document.documentElement.classList.remove('sl-theme-dark'); + document.documentElement.classList.add('sl-theme-light'); + } + this.theme = theme; + } +} diff --git a/skills/webstatus-frontend/SKILL.md b/skills/webstatus-frontend/SKILL.md index c9aab88cb..90dc82af8 100644 --- a/skills/webstatus-frontend/SKILL.md +++ b/skills/webstatus-frontend/SKILL.md @@ -24,6 +24,10 @@ This skill provides architectural guidance and conventions for the `frontend/` d - **DON'T** render the full page layout (header, sidebar, etc.) inside a page component. Page components should focus on route-specific content; `webstatus-app` provides the shell. - **DON'T** add generic class names to `shared-css.ts`. **DO** leverage Shadow DOM encapsulation and use composition with slots for reusable layout patterns. - **DO** write unit tests for all component logic. +- **DO** place application-wide service providers within `WebstatusServicesContainer` to ensure a stable context hierarchy. +- **DO** use specialized child components (the "Context Bridge" pattern) to consume global context if high-level components (like `WebstatusHeader`) don't reliably subscribe to context changes due to slotting or complex rendering lifecycles. +- **DO** use Shoelace semantic CSS variables (e.g., `--sl-color-neutral-0`) for themeable properties to ensure cross-browser inheritance (Firefox/WebKit) without relying on unsupported selectors like `:host-context`. +- **DON'T** directly use Shoelace variables (starting with `--sl-`) in component stylesheets. **DO** use custom variables defined in `_theme-css.ts` (e.g., `--color-background`, `--table-padding`) that act as a project-specific abstraction layer. ## Testing & Linting @@ -32,6 +36,13 @@ This skill provides architectural guidance and conventions for the `frontend/` d - **ES Module Testing**: When testing components that use ES module exports directly (e.g. Firebase Auth), use a helper property (e.g. `credentialGetter`) that can be overridden with a Sinon stub. - **Typing**: Use generic arguments for `querySelector` in tests (e.g. `querySelector(...)`) for type safety. +## Theming & Inheritance + +- **Global Classes**: The `WebstatusThemeService` toggles the `.sl-theme-dark` class on the `document.documentElement`. +- **Inheritance**: Shoelace variables (e.g., `--sl-color-neutral-0`) automatically switch values based on the root class. Our custom theme variables in `_theme-css.ts` should derive from these semantic Shoelace variables to inherit fixed values across Shadow DOM boundaries consistently. +- **Abstraction Layer**: Components should exclusively use custom variables from `_theme-css.ts`. Mapping these to Shoelace variables should only happen in the central theme file. This ensures that a library or color palette change can be managed in one place. +- **Avoid Unsupported Selectors**: Do not use `:host-context` for theme overrides as it lacks support in Firefox and WebKit. Use root-inherited variables instead. + ## Debugging Frontend Tests If a frontend unit test is timing out or failing mysteriously, Web Test Runner's console output is often unhelpful.