diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8ad749a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,5 @@ +node_modules +dist +.astro +playwright-report +test-results diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..106c258 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM mcr.microsoft.com/playwright:v1.63.0-noble + +WORKDIR /app + +RUN npm install -g pnpm@12 + +COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./ +RUN pnpm install --frozen-lockfile + +COPY . . +RUN pnpm build diff --git a/README.md b/README.md index 6796a37..50f938d 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ pnpm test:e2e ``` > [!WARNING] -> The `pnpm test:e2e` example was made on macOS (Darwin), which means that the screenshot tests will fail for other operating systems due to low-level rendering differences between them. To update the snapshots for CI (Linux), run `pnpm test:e2e:docker`. After running it, you may also need to re-run `pnpm install` to continue working normally on the project. +> The `pnpm test:e2e` example was made on macOS (Darwin), which means that the screenshot tests will fail for other operating systems due to low-level rendering differences between them. To update the snapshots for CI (Linux), run `pnpm test:e2e:docker`. > > More details: > - [Playwright docs / Continuous Integration / Containers](https://playwright.dev/docs/ci#via-containers) diff --git a/playwright.config.ts b/playwright.config.ts index 7b7c94b..a246899 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -38,26 +38,24 @@ export default defineConfig({ name: "chromium", use: { ...devices["Desktop Chrome"] }, }, - - // { - // name: 'firefox', - // use: { ...devices['Desktop Firefox'] }, - // }, - - // { - // name: 'webkit', - // use: { ...devices['Desktop Safari'] }, - // }, + { + name: "firefox", + use: { ...devices["Desktop Firefox"] }, + }, + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, + }, /* Test against mobile viewports. */ - // { - // name: 'Mobile Chrome', - // use: { ...devices['Pixel 5'] }, - // }, - // { - // name: 'Mobile Safari', - // use: { ...devices['iPhone 12'] }, - // }, + { + name: "chromium-mobile", + use: { ...devices["Pixel 5"] }, + }, + { + name: "safari-mobile", + use: { ...devices["iPhone 12"] }, + }, /* Test against branded browsers. */ // { @@ -72,7 +70,7 @@ export default defineConfig({ /* Run your local dev server before starting the tests */ webServer: { - command: "pnpm preview", + command: "exec node node_modules/astro/bin/astro.mjs preview", url: "http://localhost:4321/three-visual-testing", reuseExistingServer: !process.env.CI, }, diff --git a/scripts/docker-e2e.sh b/scripts/docker-e2e.sh index 12a3138..72de478 100755 --- a/scripts/docker-e2e.sh +++ b/scripts/docker-e2e.sh @@ -1,18 +1,13 @@ #!/usr/bin/env bash set -euo pipefail -IMAGE="mcr.microsoft.com/playwright:v1.63.0-noble" +docker build -t three-visual-testing-e2e . -docker run --rm --ipc=host \ - -u "$(id -u):$(id -g)" \ - -e HOME=/tmp \ - -v "$(pwd)":/work \ - -w /work \ - "$IMAGE" \ +docker run --rm --init --ipc=host \ + -v "$(pwd)/tests-e2e:/app/tests-e2e" \ + -v "$(pwd)/test-results:/app/test-results" \ + -v "$(pwd)/playwright-report:/app/playwright-report" \ + three-visual-testing-e2e \ /bin/bash -c ' - wget -qO- https://get.pnpm.io/install.sh | env ENV="$HOME/.bashrc" SHELL="$(which bash)" bash - - source "$HOME/.bashrc" - pnpm install --frozen-lockfile - pnpm build pnpm test:e2e "$@" ' bash "$@" diff --git a/tests-e2e/app.spec.ts b/tests-e2e/app.spec.ts index 023d846..67b0ef2 100644 --- a/tests-e2e/app.spec.ts +++ b/tests-e2e/app.spec.ts @@ -10,7 +10,9 @@ test("has title", async ({ page }) => { await expect(page).toHaveTitle("three-visual-testing"); }); -test("has 2 scenes", async ({ page }) => { +test("has 2 scenes", async ({ page, browserName }) => { + skipIfUnsupported({ browserName }); + await expect(page.locator(".scene")).toHaveCount(2); const sceneWebGL = page.locator(".scene").nth(0); @@ -23,7 +25,9 @@ test("has 2 scenes", async ({ page }) => { await expectThreeCanvas({ locator: sceneWebGPU, engine: "webgpu" }); }); -test("renders scenes @visual", async ({ page }) => { +test("renders scenes @visual", async ({ page, browserName }) => { + skipIfUnsupported({ browserName }); + const sceneWebGL = page.locator(".scene").nth(0); const sceneWebGPU = page.locator(".scene").nth(1); @@ -38,7 +42,7 @@ async function expectThreeCanvas({ engine = "webgl", }: { locator: Locator; - engine?: "webgl" | "webgpu"; + engine: "webgl" | "webgpu"; }): Promise { const canvas = locator.locator("canvas[data-engine]"); await expect(canvas).toBeVisible(); @@ -52,3 +56,10 @@ async function expectThreeCanvas({ await expect(engineAttr).toBe("three.js r186 webgpu"); } } + +function skipIfUnsupported({ browserName }: { browserName: string }): void { + test.skip( + browserName === "firefox" && process.platform === "linux", + "Headless Firefox on Linux has no WebGL context", + ); +} diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-chromium-mobile-darwin.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-chromium-mobile-darwin.png new file mode 100644 index 0000000..e8c4d1a Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-chromium-mobile-darwin.png differ diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-chromium-mobile-linux.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-chromium-mobile-linux.png new file mode 100644 index 0000000..2b3df65 Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-chromium-mobile-linux.png differ diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-firefox-darwin.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-firefox-darwin.png new file mode 100644 index 0000000..b323475 Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-firefox-darwin.png differ diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-safari-mobile-darwin.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-safari-mobile-darwin.png new file mode 100644 index 0000000..97c6837 Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-safari-mobile-darwin.png differ diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-safari-mobile-linux.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-safari-mobile-linux.png new file mode 100644 index 0000000..299ed72 Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-safari-mobile-linux.png differ diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-webkit-darwin.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-webkit-darwin.png new file mode 100644 index 0000000..3926bbe Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-webkit-darwin.png differ diff --git a/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-webkit-linux.png b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-webkit-linux.png new file mode 100644 index 0000000..045c184 Binary files /dev/null and b/tests-e2e/app.spec.ts-snapshots/renders-scenes-visual-1-webkit-linux.png differ