Skip to content

Commit a36d024

Browse files
aksOpsclaude
andcommitted
test: add Playwright e2e suite + CI workflow
- 28 tests across desktop + mobile (chromium-only): • smoke — landing pages render, /docs/ lists 40+ components, representative sample of 17 component pages renders all demos without errors, playground default executes • mobile — no horizontal overflow on home and Button at 390x844, sidebar drawer toggles via hamburger and backdrop, Escape closes, sidebar link nav closes drawer, apps grid stacks to one column • theme — toggle changes data-theme + writes localStorage atomically, persists across reloads - scripts/build-site.mjs — single-command site build (esbuild + docs) - scripts/serve-site.mjs — tiny zero-dep static server for tests - playwright.config.ts — webServer-driven, two projects: desktop (Chrome 1280x800) + mobile (iPhone 13, chromium browser) - .github/workflows/e2e.yml — Node 24, browser cache by playwright version, uploads report+traces on failure - generator fix: variantsDemo / sizesDemo / statesDemo now reuse requiredAttrs so Select/Tabs/Menu render with their `options`/`items` populated instead of throwing at runtime - mobile fix: body { overflow-x: clip } on small screens stops minor flex+pre overflow from making the page horizontally scrollable Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 902ed08 commit a36d024

12 files changed

Lines changed: 812 additions & 31 deletions

File tree

.github/workflows/e2e.yml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
name: E2E
2+
3+
# Runs the Playwright end-to-end suite against a freshly built docs site.
4+
# Uses chromium only (single browser binary for speed).
5+
6+
on:
7+
push:
8+
branches: [main]
9+
paths:
10+
- "src/**"
11+
- "scripts/**"
12+
- "tests/e2e/**"
13+
- "playwright.config.ts"
14+
- "colors_and_type.css"
15+
- "preview/**"
16+
- "ui_kits/**"
17+
- "package.json"
18+
- "pnpm-lock.yaml"
19+
- ".github/workflows/e2e.yml"
20+
pull_request:
21+
branches: [main]
22+
workflow_dispatch:
23+
24+
permissions:
25+
contents: read
26+
27+
concurrency:
28+
group: e2e-${{ github.ref }}
29+
cancel-in-progress: true
30+
31+
jobs:
32+
e2e:
33+
name: Playwright (chromium)
34+
runs-on: ubuntu-latest
35+
timeout-minutes: 12
36+
steps:
37+
- uses: actions/checkout@v6
38+
39+
- uses: pnpm/action-setup@v5
40+
41+
- uses: actions/setup-node@v6
42+
with:
43+
node-version: 24
44+
cache: pnpm
45+
46+
- name: Install
47+
run: pnpm install --frozen-lockfile
48+
49+
- name: Resolve playwright version
50+
id: pw
51+
run: |
52+
v=$(node -p "require('./node_modules/@playwright/test/package.json').version")
53+
echo "version=$v" >> "$GITHUB_OUTPUT"
54+
55+
- name: Cache playwright browsers
56+
id: pw-cache
57+
uses: actions/cache@v5
58+
with:
59+
path: ~/.cache/ms-playwright
60+
key: playwright-${{ runner.os }}-${{ steps.pw.outputs.version }}
61+
62+
- name: Install browsers
63+
if: steps.pw-cache.outputs.cache-hit != 'true'
64+
run: pnpm exec playwright install --with-deps chromium
65+
66+
- name: Install browser system deps (cache hit only)
67+
if: steps.pw-cache.outputs.cache-hit == 'true'
68+
run: pnpm exec playwright install-deps chromium
69+
70+
- name: Build site
71+
run: pnpm run build:site
72+
73+
- name: Run tests
74+
run: pnpm test:e2e
75+
76+
- name: Upload report
77+
if: failure()
78+
uses: actions/upload-artifact@v7
79+
with:
80+
name: playwright-report-${{ github.sha }}
81+
path: |
82+
playwright-report/
83+
test-results/
84+
retention-days: 7

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ Thumbs.db
3434
# Test
3535
coverage/
3636
.nyc_output/
37+
test-results/
38+
playwright-report/
39+
playwright/.cache/
3740

3841
# Misc
3942
*.tgz

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@
4949
"scripts": {
5050
"typecheck": "tsc --noEmit",
5151
"build": "tsc -p tsconfig.build.json && node -e \"require('fs').writeFileSync('dist/styles.css', require('fs').readFileSync('colors_and_type.css','utf8') + '\\n' + require('fs').readFileSync('src/styles.css','utf8'))\"",
52+
"build:site": "node scripts/build-site.mjs _site",
5253
"lint": "eslint \"src/**/*.{ts,tsx}\"",
5354
"test": "vitest run",
55+
"test:e2e": "playwright test",
56+
"test:e2e:install": "playwright install --with-deps chromium",
5457
"preview": "echo 'Open preview/responsive-check.html in a browser' ",
5558
"prepublishOnly": "pnpm run typecheck && pnpm run build",
5659
"release": "pnpm version"
@@ -61,10 +64,13 @@
6164
},
6265
"devDependencies": {
6366
"@babel/standalone": "^7.29.0",
67+
"@playwright/test": "^1.59.1",
68+
"@types/node": "^22.0.0",
6469
"@types/react": "^18.3.0",
6570
"@types/react-dom": "^18.3.0",
6671
"@typescript-eslint/eslint-plugin": "^8.0.0",
6772
"@typescript-eslint/parser": "^8.0.0",
73+
"esbuild": "^0.24.0",
6874
"eslint": "^9.0.0",
6975
"jsdom": "^22.1.0",
7076
"typescript": "^5.6.0",

playwright.config.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { defineConfig, devices } from "@playwright/test";
2+
3+
const PORT = parseInt(process.env.PORT || "4173", 10);
4+
5+
export default defineConfig({
6+
testDir: "./tests/e2e",
7+
fullyParallel: true,
8+
forbidOnly: !!process.env.CI,
9+
retries: process.env.CI ? 1 : 0,
10+
workers: process.env.CI ? 2 : undefined,
11+
reporter: process.env.CI
12+
? [["github"], ["html", { open: "never" }]]
13+
: "list",
14+
timeout: 30_000,
15+
expect: { timeout: 7_000 },
16+
use: {
17+
baseURL: `http://localhost:${PORT}`,
18+
trace: "retain-on-failure",
19+
screenshot: "only-on-failure",
20+
},
21+
projects: [
22+
{
23+
name: "desktop",
24+
testIgnore: /mobile\.spec\.ts$/,
25+
use: { ...devices["Desktop Chrome"], viewport: { width: 1280, height: 800 } },
26+
},
27+
{
28+
name: "mobile",
29+
testMatch: /mobile\.spec\.ts$/,
30+
use: {
31+
...devices["iPhone 13"],
32+
// iPhone 13 profile defaults to webkit; force chromium so we can
33+
// run the suite with a single browser binary.
34+
browserName: "chromium",
35+
defaultBrowserType: "chromium",
36+
},
37+
},
38+
],
39+
webServer: {
40+
command: "node scripts/serve-site.mjs _site",
41+
port: PORT,
42+
reuseExistingServer: !process.env.CI,
43+
timeout: 30_000,
44+
stdout: "pipe",
45+
stderr: "pipe",
46+
},
47+
});

0 commit comments

Comments
 (0)