Skip to content

Commit 35a63e8

Browse files
authored
chore(css-modules): 🤖 support local visual regression testing via docker (#931)
* chore: 🤖 add pkg vite-plugin-static-copy * chore: 🤖 use vite setup to copy css to distribution * refactor: 💡 make static copy process common for cjs and esm * docs: 📝 about css modules * style: 💄 add Button css module * style: 💄 assign css module to component Button * chore: 🤖 add class-variance-authority and clsx * style: 💄 migrate styled component to css modules * style: 💄 migrate styled component to css modules * refactor: 💡 token generator * chore: 🤖 storybook support for css modules * chore: 🤖 add button stories for each state, e.g. primary, secondary, etc * chore: 🤖 add changeset * chore: 🤖 remove comment * chore: 🤖 update changeset * chore: 🤖 declare css files as sideEffects * refactor: 💡 make class utility libraries, e.g. cva; actual dependencies * chore: 🤖 add TODO button * style: 💄 possible typo, e.g. make similar bg size as others * refactor: 💡 role button is redundant per the ARIA in HTML spec, add aria-busy={loading} * chore: 🤖 format * refactor: 💡 generate tokens, e.g. theme config shared file as json, remove generate quotes,e tc * chore: 🤖 add TODO regarding removal of styled components for the future, e.g. remove babel plugins * chore: 🤖 add migration note to changeset * refactor: 💡 forward props (delegated) * fix: 🐛 checkout design tokens from main * fix: 🐛 if a consumer passes className, it would overwrite the variant classes * fix: 🐛 avoid double colmns * chore: 🤖 regenerate tokens * fix: 🐛 replace missing by global focus token * fix: 🐛 focus rings restored for keyboard users * refactor: 💡 follow BEM naming convention * chore: 🤖 include BEM rule in llm conventions * fix: 🐛 empty token * fix: 🐛 .button > span selector to explicit .button__label class * chore: 🤖 format * fix: 🐛 claude review, missing prefers-reduced-motion support for the shimmer animation. * fix: 🐛 add line * refactor: 💡 remove sideEffects redundancy * fix: 🐛 package.json typo * style: 💄 missing background repeat, as commented by claude PR * fix: 🐛 Changed both attributes to use || undefined: - aria-disabled={(disabled || loading) || undefined} - aria-busy={loading || undefined} due to accessibility * chore: 🤖 initial playwright Docker setup * chore: 🤖 create docker ignore file * chore: 🤖 update gitignore to filter out snapshots, e.g. darwin * chore: 🤖 create a docker compose to ease orchestration * chore: 🤖 update playwright-docker script port to 8282 * test: 💍 create button visual regression test covering all states * docs: 📝 visual regression playwright setup * fix: 🐛 bash syntax error in the playwright-docker script * docs: 📝 visual regression docker requirement * test: 💍 added the aria-busy assertion * chore: 🤖 track visual regression snapshots * test: 💍 preevnts shimmer animation from causing noin-deterministic screenshot comparisons * chore: 🤖 removed docker stop block, and unused DOCKER_INSTANCE_NAME var. The docker rm -f playwright-ui command handles both stopping and removing the container * refactor: 💡 added role="group" to ButtonGroupWrapper (semantically correct for a group of related buttons) and updated the test to use page.getByRole('group') * docs: 📝 amend typo (separatily/separately) * test: 💍 throw if null * chore: 🤖 map source to docker * fix: 🐛 button attribute values * chore: 🤖 update snapshots
1 parent f6a2cd2 commit 35a63e8

File tree

54 files changed

+704
-11
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+704
-11
lines changed

.dockerignore

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
node_modules
2+
3+
dist
4+
.storybook/out
5+
storybook-static
6+
7+
playwright-report
8+
test-results
9+
10+
.git
11+
.gitignore
12+
13+
.idea
14+
.vscode
15+
*.swp
16+
*.swo
17+
18+
.DS_Store
19+
Thumbs.db
20+
21+
*.log
22+
*.md
23+
!README.md

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ tmp/*
1414
!.yarn/releases
1515
!.yarn/plugins
1616

17-
**.ts-snapshots
1817
tests/**/*-actual.png
1918
tests/**/*-diff.png
19+
tests/**/*-darwin.png
2020
test-results
21+
playwright-report
2122

2223
.install
2324
.vscode

.scripts/bash/playwright-docker

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/bin/bash
2+
3+
COMMAND="${1:-test}"
4+
5+
PORT="8282"
6+
7+
if [[ "$COMMAND" = "update" ]]; then
8+
docker compose \
9+
-f docker-compose.playwright.yml \
10+
run \
11+
--rm update-snapshots
12+
elif [[ "$COMMAND" = "ui" ]]; then
13+
docker rm -f playwright-ui 2>/dev/null
14+
15+
echo "🎭 Starting Playwright UI at http://localhost:$PORT..."
16+
17+
(sleep 3 &&
18+
open "http://localhost:$PORT" 2>/dev/null ||
19+
xdg-open "http://localhost:$PORT" 2>/dev/null) &
20+
21+
docker compose \
22+
-f docker-compose.playwright.yml \
23+
run \
24+
--rm \
25+
--service-ports \
26+
--name playwright-ui \
27+
ui
28+
elif [[ "$COMMAND" = "report" ]]; then
29+
npx playwright show-report
30+
else
31+
docker compose \
32+
-f docker-compose.playwright.yml \
33+
run \
34+
--rm \
35+
test
36+
fi

Dockerfile.playwright

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
FROM mcr.microsoft.com/playwright:v1.58.2-noble
2+
3+
WORKDIR /app
4+
5+
RUN corepack enable && corepack prepare yarn@4.5.3 --activate
6+
7+
COPY package.json yarn.lock .yarnrc.yml ./
8+
9+
RUN yarn install
10+
11+
COPY . .
12+
13+
CMD ["yarn", "test:visual"]

docker-compose.playwright.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
services:
2+
playwright:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile.playwright
6+
volumes:
7+
- ./src:/app/src
8+
- ./tests:/app/tests
9+
- ./playwright-report:/app/playwright-report
10+
- ./test-results:/app/test-results
11+
- ./.storybook:/app/.storybook
12+
environment:
13+
- CI=true
14+
shm_size: 1gb
15+
16+
test:
17+
extends: playwright
18+
command: yarn test:visual
19+
20+
update-snapshots:
21+
extends: playwright
22+
command: yarn test:visual:update
23+
24+
ui:
25+
extends: playwright
26+
ports:
27+
# NOTE: Match port number of `playwright-docker` script
28+
- "8282:8282"
29+
environment:
30+
- CI=false
31+
command: npx playwright test --ui-host=0.0.0.0 --ui-port=8282

docs/tests/playwright.md

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,34 @@ Use Playwright when you need to:
1111
> [!TIP]
1212
> Use Playwright for rapid local development, (e.g. if you need fast feedback loop) and Chromatic for team reviews and CI/CD.
1313
14+
## Requirements
15+
16+
- [Docker](http://docker.com/)
17+
1418
## Visual regression testing locally
1519

1620
Visual regression tests are operating system dependent.
1721

1822
Screenshots generated on macOS will differ from Linux or Windows due to font rendering, anti-aliasing, and browser engine differences.
1923

24+
To mitigate differences across operating systems, our visual regression tests are Dockerized for consistent visual regression testing.
25+
26+
### Docker (Ubuntu Linux)
27+
28+
All visual tests run in Docker (Ubuntu Linux) by default for consistency with CI:
29+
30+
```sh
31+
yarn test:visual # Run tests
32+
yarn test:visual:update # Update snapshots
33+
yarn test:visual:ui # UI mode (opens at http://localhost:8282)
34+
yarn test:visual:report # View HTML report
35+
```
36+
37+
> [!NOTE]
38+
> The port number is declared in the Docker compose and playwright-docker bash script, which should be in sync.
39+
40+
Snapshots are saved with `-linux` suffix to match CI environments.
41+
2042
For this reason at time of writing, the following snaptshots are ignored:
2143

2244
```sh
@@ -37,7 +59,7 @@ You MUST generate the snapshots you want to compare against. At time of writing,
3759
> If you are reading this document, you should be aware that this provides you with custom control for advanced needs only! It does not provide you with the setup for cross-operating system, e.g. docker linux.
3860
> This workflow does NOT expect you to store your favourite OS image/snapshots in the repository, it's for your own usage, or fast feedback loop only!
3961
40-
To generate snapshots, you'll have to manually checkout/switch to the target commit in history and run the `test:visual` to generate it and return back to your ongoing feature branch. Alternatively, you can store snapshots separatily and place them at your need.
62+
To generate snapshots, you'll have to manually checkout/switch to the target commit in history and run the `test:visual` to generate it and return back to your ongoing feature branch. Alternatively, you can store snapshots separately and place them at your need.
4163

4264
Hypothetically, you could use the following workflow to facilitate:
4365

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -387,10 +387,10 @@
387387
"storybook:serve": "yarn dlx http-server .storybook/out",
388388
"test": "vitest",
389389
"test:chromatic": "yarn dlx chromatic",
390-
"test:visual": "playwright test",
391-
"test:visual:report": "playwright show-report",
392-
"test:visual:ui": "playwright test --ui",
393-
"test:visual:update": "playwright test --update-snapshots",
390+
"test:visual": ".scripts/bash/playwright-docker",
391+
"test:visual:report": ".scripts/bash/playwright-docker report",
392+
"test:visual:ui": ".scripts/bash/playwright-docker ui",
393+
"test:visual:update": ".scripts/bash/playwright-docker update",
394394
"test:watch": "DEBUG_PRINT_LIMIT=100000 vitest --watch",
395395
"typecheck": "tsc --noEmit"
396396
},

src/components/ButtonGroup/ButtonGroup.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,10 @@ export const ButtonGroup = ({
8585

8686
return (
8787
<ButtonGroupWrapper
88+
{...props}
8889
$fillWidth={fillWidth}
8990
$type={type}
90-
{...props}
91+
role="group"
9192
>
9293
{buttons}
9394
</ButtonGroupWrapper>

0 commit comments

Comments
 (0)