Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
dist
.astro
playwright-report
test-results
11 changes: 11 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
36 changes: 17 additions & 19 deletions playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
// {
Expand All @@ -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,
},
Expand Down
17 changes: 6 additions & 11 deletions scripts/docker-e2e.sh
Original file line number Diff line number Diff line change
@@ -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 "$@"
17 changes: 14 additions & 3 deletions tests-e2e/app.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);

Expand All @@ -38,7 +42,7 @@ async function expectThreeCanvas({
engine = "webgl",
}: {
locator: Locator;
engine?: "webgl" | "webgpu";
engine: "webgl" | "webgpu";
}): Promise<void> {
const canvas = locator.locator("canvas[data-engine]");
await expect(canvas).toBeVisible();
Expand All @@ -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",
);
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading