From 6a97ea874f69290d1dde932d7672144cccb430d8 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:15:42 -0600 Subject: [PATCH 1/4] test: enable testing of pages with no service worker loaded --- package.json | 1 + playwright.config.js | 25 +++++++++++++++++ test-e2e/fixtures/config-test-fixtures.ts | 34 +++++++++++++++++++++-- test-e2e/layout.test.ts | 2 +- 4 files changed, 58 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 8e3cfbb2..cba9eab1 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "test:iso": "aegir test -f dist-tsc/test/**/*.spec.js", "test:browsers": "playwright test -c playwright.config.js", "test:chrome": "playwright test -c playwright.config.js --project chromium", + "test:no-sw": "playwright test -c playwright.config.js --project no-service-worker", "test:firefox": "playwright test -c playwright.config.js --project firefox", "test:deployed": "playwright test -c playwright.config.js --project deployed", "test:inbrowser-dev": "cross-env BASE_URL='https://inbrowser.dev' playwright test -c playwright.config.js --project deployed", diff --git a/playwright.config.js b/playwright.config.js index 6390ca84..be578bb6 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -51,6 +51,31 @@ export default defineConfig({ ...devices['Desktop Firefox'], baseURL: process.env.BASE_URL } + }, + { + /** + * Test the site with service workers disabled. You need to `import {testNoServiceWorker as test, expect} from './fixtures/config-test-fixtures.js'` to use this project. + * Anything needing a service worker will be skipped when this project is ran. + */ + name: 'no-service-worker', + use: { + ...devices['Desktop Firefox'], + contextOptions: { + serviceWorkers: 'block' + }, + launchOptions: { + firefoxUserPrefs: { + 'dom.serviceWorkers.enabled': false + } + }, + beforeEach: async ({ page }) => { + await page.addInitScript(() => { + Object.defineProperty(navigator, 'serviceWorker', { + get: () => undefined + }) + }) + } + } } ], // TODO: disable webservers when testing `deployed` project diff --git a/test-e2e/fixtures/config-test-fixtures.ts b/test-e2e/fixtures/config-test-fixtures.ts index 983f51de..81c32e03 100644 --- a/test-e2e/fixtures/config-test-fixtures.ts +++ b/test-e2e/fixtures/config-test-fixtures.ts @@ -2,6 +2,10 @@ import { test as base, type Page } from '@playwright/test' import { setConfig, setSubdomainConfig } from './set-sw-config.js' import { waitForServiceWorker } from './wait-for-service-worker.js' +function isNoServiceWorkerProject (test: T): boolean { + return test.info().project.name === 'no-service-worker' +} + const rootDomain = async ({ baseURL }, use): Promise => { const url = new URL(baseURL) await use(url.host) @@ -13,13 +17,20 @@ const baseURLProtocol = async ({ baseURL }, use): Promise => { export const test = base.extend<{ rootDomain: string, baseURL: string, protocol: string }>({ rootDomain: [rootDomain, { scope: 'test' }], - protocol: [baseURLProtocol, { scope: 'test' }] + protocol: [baseURLProtocol, { scope: 'test' }], + page: async ({ page }, use) => { + if (isNoServiceWorkerProject(test)) { + test.skip() + return + } + await use(page) + } }) /** * You should use this fixture instead of the `test` fixture from `@playwright/test` when testing path routing via the service worker. */ -export const testPathRouting = base.extend<{ rootDomain: string, baseURL: string, protocol: string }>({ +export const testPathRouting = test.extend<{ rootDomain: string, baseURL: string, protocol: string }>({ rootDomain: [rootDomain, { scope: 'test' }], protocol: [baseURLProtocol, { scope: 'test' }], page: async ({ page, rootDomain }, use) => { @@ -63,7 +74,7 @@ export const testPathRouting = base.extend<{ rootDomain: string, baseURL: string * }) * ``` */ -export const testSubdomainRouting = base.extend<{ rootDomain: string, baseURL: string, protocol: string }>({ +export const testSubdomainRouting = test.extend<{ rootDomain: string, baseURL: string, protocol: string }>({ rootDomain: [rootDomain, { scope: 'test' }], protocol: [baseURLProtocol, { scope: 'test' }], page: async ({ page, baseURL }, use) => { @@ -108,4 +119,21 @@ export const testSubdomainRouting = base.extend<{ rootDomain: string, baseURL: s } }) +/** + * A fixture that skips tests that require the service worker. This is needed in order to test handling of requests where the service worker is not present. + * + * @see https://github.com/ipfs/service-worker-gateway/issues/272 + */ +export const testNoServiceWorker = base.extend<{ rootDomain: string, baseURL: string, protocol: string }>({ + rootDomain: [rootDomain, { scope: 'test' }], + protocol: [baseURLProtocol, { scope: 'test' }], + page: async ({ page }, use) => { + if (!isNoServiceWorkerProject(testNoServiceWorker)) { + testNoServiceWorker.skip() + return + } + await use(page) + } +}) + export { expect } from '@playwright/test' diff --git a/test-e2e/layout.test.ts b/test-e2e/layout.test.ts index 81510fcb..e549af4f 100644 --- a/test-e2e/layout.test.ts +++ b/test-e2e/layout.test.ts @@ -1,4 +1,4 @@ -import { test, expect } from '@playwright/test' +import { test, expect } from './fixtures/config-test-fixtures.js' import { getConfigButton, getConfigPage, getConfigPageSaveButton, getConfigPageInput, getHeader, getHeaderTitle } from './fixtures/locators.js' test.describe('smoketests', () => { From cfe7ab4b87d999aa0e83626b1b2950bc7b1d6723 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:25:56 -0600 Subject: [PATCH 2/4] test: add no-sw tests that repro #272 --- .gitignore | 1 + src/pages/errors/no-service-worker.tsx | 2 +- test-e2e/fixtures/locators.ts | 2 ++ test-e2e/no-service-worker.test.ts | 16 ++++++++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 test-e2e/no-service-worker.test.ts diff --git a/.gitignore b/.gitignore index ffd04799..c7c0beb5 100644 --- a/.gitignore +++ b/.gitignore @@ -226,3 +226,4 @@ playwright-report .coverage test-e2e/fixtures/data/test-repo test-e2e/fixtures/data/gateway-conformance-fixtures +test-results diff --git a/src/pages/errors/no-service-worker.tsx b/src/pages/errors/no-service-worker.tsx index dc373b28..13f8d577 100644 --- a/src/pages/errors/no-service-worker.tsx +++ b/src/pages/errors/no-service-worker.tsx @@ -11,7 +11,7 @@ export default function NoServiceWorkerErrorPage (): React.JSX.Element { return ( <>
-
+

Service Worker Error

This page requires a service worker to be available. Please ensure that diff --git a/test-e2e/fixtures/locators.ts b/test-e2e/fixtures/locators.ts index 41baaca1..c3d49123 100644 --- a/test-e2e/fixtures/locators.ts +++ b/test-e2e/fixtures/locators.ts @@ -21,6 +21,8 @@ export const getConfigGatewaysInput: GetLocator = (page) => page.locator('.e2e-c export const getConfigRoutersInput: GetLocator = (page) => page.locator('.e2e-config-page-input-routers') export const getConfigAutoReloadInput: GetLocator = (page) => page.locator('.e2e-config-page-input-autoreload') +export const getNoServiceWorkerError: GetLocator = (page) => page.locator('.e2e-no-service-worker-error') + /** * Iframe page parts */ diff --git a/test-e2e/no-service-worker.test.ts b/test-e2e/no-service-worker.test.ts new file mode 100644 index 00000000..628bb1c3 --- /dev/null +++ b/test-e2e/no-service-worker.test.ts @@ -0,0 +1,16 @@ +import { testNoServiceWorker as test, expect } from './fixtures/config-test-fixtures.js' +import { getNoServiceWorkerError } from './fixtures/locators.js' + +test.describe('no-service-worker', () => { + test('Error renders on landing page', async ({ page }) => { + await page.goto('/') + + await expect(getNoServiceWorkerError(page)).toBeVisible() + }) + + test('Error renders on subdomain page', async ({ page, rootDomain, protocol }) => { + await page.goto(`${protocol ?? 'http'}//bafkqablimvwgy3y.ipfs.${rootDomain}`, { waitUntil: 'networkidle' }) + + await expect(getNoServiceWorkerError(page)).toBeVisible() + }) +}) From 5e7e9fb7127059fa3d702b6b1eaab669c651c706 Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:29:46 -0600 Subject: [PATCH 3/4] fix: no-sw error shows for subdomain requests --- src/index.tsx | 1 + src/lib/routing-render-checks.ts | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/index.tsx b/src/index.tsx index c0ca7ab1..40edeb0c 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -22,6 +22,7 @@ if ('serviceWorker' in navigator) { const routes: Route[] = [ { default: true, component: ErrorPage ?? LazyHelperUi }, + { shouldRender: async () => renderChecks.shouldRenderNoServiceWorkerError(), component: LazyServiceWorkerErrorPage }, { shouldRender: async () => renderChecks.shouldRenderRedirectsInterstitial(), component: LazyInterstitial }, { path: '#/ipfs-sw-config', shouldRender: async () => renderChecks.shouldRenderConfigPage(), component: LazyConfig }, { diff --git a/src/lib/routing-render-checks.ts b/src/lib/routing-render-checks.ts index c1caa38c..3073e137 100644 --- a/src/lib/routing-render-checks.ts +++ b/src/lib/routing-render-checks.ts @@ -31,3 +31,7 @@ export function shouldRenderRedirectsInterstitial (): boolean { const heliaSw = url.searchParams.get('helia-sw') return heliaSw != null } + +export function shouldRenderNoServiceWorkerError (): boolean { + return !('serviceWorker' in navigator) +} From 71a622c9771fb8e6c2f258ce660b4d341fc58e4b Mon Sep 17 00:00:00 2001 From: Russell Dempsey <1173416+SgtPooki@users.noreply.github.com> Date: Fri, 22 Nov 2024 12:35:07 -0600 Subject: [PATCH 4/4] test: no-service-worker tests target a test file & run in CI --- package.json | 2 +- playwright.config.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index cba9eab1..ed57d402 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "test:browsers": "playwright test -c playwright.config.js", "test:chrome": "playwright test -c playwright.config.js --project chromium", "test:no-sw": "playwright test -c playwright.config.js --project no-service-worker", - "test:firefox": "playwright test -c playwright.config.js --project firefox", + "test:firefox": "playwright test -c playwright.config.js --project firefox --project no-service-worker", "test:deployed": "playwright test -c playwright.config.js --project deployed", "test:inbrowser-dev": "cross-env BASE_URL='https://inbrowser.dev' playwright test -c playwright.config.js --project deployed", "test:inbrowser-prod": "cross-env BASE_URL='https://inbrowser.link' playwright test -c playwright.config.js --project deployed", diff --git a/playwright.config.js b/playwright.config.js index be578bb6..68790691 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -58,6 +58,7 @@ export default defineConfig({ * Anything needing a service worker will be skipped when this project is ran. */ name: 'no-service-worker', + testMatch: /test-e2e\/no-service-worker\.test\.ts/, use: { ...devices['Desktop Firefox'], contextOptions: {