Skip to main content

visual-test

Visually verify a component by launching its Storybook story and taking a screenshot with playwright-cli. Use after making visual changes to a component.

ソース情報

リポジトリ
microsoft/fluentui
ソースの最終更新活動
2026年7月21日 16:00
検出された SKILL.md の言語
英語
スター
20,366
フォーク
2,953

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
visual-test
description
Visually verify a component by launching its Storybook story and taking a screenshot with playwright-cli. Use after making visual changes to a component.
disable-model-invocation
true
argument-hint
<ComponentName> [story-name]
allowed-tools
Bash Read Grep Glob
# Visual Test a Component Visually verify **$ARGUMENTS** by launching Storybook and capturing a screenshot with `playwright-cli`. ## Prerequisites Run `playwright-cli` via `npx` so nothing is installed globally on the user's box. The first invocation downloads `@playwright/cli@0.1.1` into the npx cache; subsequent calls are cached. Every command below uses this form: ```bash npx -y @playwright/cli@0.1.1 <command> ``` ## Critical: use the per-component Storybook only Always boot the **per-component stories package** (`react-<component>-stories`) via nx `storybook` target, which only imports its own component's stories and dependencies. ## Steps 1. **Find the component's stories package.** Each v9 component has a dedicated stories package named `react-<component>-stories`: ```bash yarn nx show project react-<lowercase-component-name>-stories --json ``` If nx returns nothing with output of `Could not find project react-<component>-stories`, the component doesn't have its own stories package — check for a preview package (`react-<component>-preview-stories`) or ask before proceeding. 2. **Start the component's Storybook dev server.** Use the `storybook` target on the stories project directly — it's the most portable, since library aliases like `react-<component>:start` were only added in April 2026 and may not exist in older workspace snapshots: ```bash yarn nx run react-<component>-stories:storybook & ``` 3. **Find the storybook port.** Three quirks to know: - Storybook picks a **random high port** on first boot (e.g. `49360`), not the Storybook default `6006`. Don't assume. - The nx wrapper process often exits 0 after delegating to storybook, leaving the actual server running as a child. So the nx PID isn't the storybook PID. - The storybook child opens **two** listening sockets: one for HTTP content, one for the webpack HMR event-stream. They are not ordered — either one can be numerically lower. Picking by port number is unreliable; pick by `Content-Type`. Reliable detection — target the storybook node child (not the yarn wrapper), then probe each listening socket until one returns `text/html`: ```bash # Wait up to 180s for the storybook child to bind an HTTP port. # Pattern matches the node child specifically, not `yarn storybook dev` (the wrapper has no sockets). for i in $(seq 1 180); do SB_CHILD=$(pgrep -f "node.*\.bin/storybook dev" | head -1) if [ -n "$SB_CHILD" ]; then for port in $(lsof -a -p "$SB_CHILD" -i -P -sTCP:LISTEN 2>/dev/null | awk 'NR>1 {print $9}' | sed 's/.*://'); do CT=$(curl -sI --max-time 2 "http://localhost:$port/" 2>/dev/null | grep -i '^content-type:' | grep -i 'text/html') if [ -n "$CT" ]; then SB_PORT=$port; break; fi done if [ -n "$SB_PORT" ]; then break; fi fi sleep 1 done echo "Storybook child PID=$SB_CHILD on port $SB_PORT" ``` Then wait for Storybook to finish compiling stories — the HTTP port answers before `index.json` is populated: ```bash for i in $(seq 1 60); do N=$(curl -s --max-time 2 "http://localhost:$SB_PORT/index.json" 2>/dev/null \ | python3 -c "import json,sys; print(len(json.load(sys.stdin).get('entries', {})))" 2>/dev/null || echo 0) if [ "$N" -gt 0 ]; then break; fi sleep 2 done ``` If no port turns up, or `index.json` never populates — **do not** fall back to the workspace-wide Storybook; read the nx output log and debug the per-component boot. The most common real failure is missing build artifacts for unstable re-export deps (see troubleshooting below). 4. **Open the page with playwright-cli:** ```bash npx -y @playwright/cli@0.1.1 open "http://localhost:$SB_PORT" ``` 5. **Navigate to the specific story iframe** and capture a screenshot. Use the iframe URL for a clean render without Storybook chrome: ```bash npx -y @playwright/cli@0.1.1 goto "http://localhost:$SB_PORT/iframe.html?id=components-<component>--default&viewMode=story" npx -y @playwright/cli@0.1.1 screenshot --filename=/tmp/visual-test-$ARGUMENTS.png ``` 6. **View the screenshot** using the Read tool to visually inspect the rendered component. 7. **Use `snapshot`** to get the accessibility tree and find interactive element refs: ```bash npx -y @playwright/cli@0.1.1 snapshot ``` Then interact with elements by ref (e.g., click, hover) before taking more screenshots. 8. **If the component doesn't look right**, go back to the code, fix the issue, and repeat from step 4 (Storybook hot-reloads changes). 9. **Clean up** when done: ```bash npx -y @playwright/cli@0.1.1 close # Kill storybook — the nx wrapper may already be gone, so target the child [ -n "$SB_CHILD" ] && kill "$SB_CHILD" 2>/dev/null lsof -i :$SB_PORT -t 2>/dev/null | xargs kill 2>/dev/null ``` ## Troubleshooting **`yarn nx run react-<component>-stories:storybook` says the target doesn't exist.** The workspace graph may be stale (recent reparent). Run `yarn nx reset` then retry. If `stroybook` aliases still don't exist, use the direct yarn invocation: ```bash cd packages/react-components/react-<component>/stories && yarn storybook dev --port 0 & # --port 0 asks Storybook to pick a free port; detect it via the pgrep/lsof pattern above ``` ## Story ID Pattern Story IDs follow the pattern `<category>-<component>--<story>`: ``` # Default story for Button components-button--default # Appearance variant components-button--appearance # Default story for Menu components-menu--default ``` To discover exact story IDs, open the Storybook sidebar and use `snapshot` to find navigation links, or check the story file's `export default { title: '...' }` metadata. ## Iframe URL Format ``` # Local storybook (replace $SB_PORT with the actual port) http://localhost:$SB_PORT/iframe.html?id=components-button--default&viewMode=story # Dark theme http://localhost:$SB_PORT/iframe.html?id=components-button--default&viewMode=story&globals=theme:webDarkTheme ``` The `/iframe.html` URL gives a clean render without Storybook chrome — always prefer this for screenshots. ## Tips - Use `npx -y @playwright/cli@0.1.1 snapshot` to get an accessibility tree — useful for verifying ARIA attributes and finding interactive elements. - Use `npx -y @playwright/cli@0.1.1 click <ref>` to interact with the component (test hover states, open menus, etc.) before taking a screenshot. - Use `npx -y @playwright/cli@0.1.1 resize <width> <height>` to test responsive behavior. - For multiple story variants, take a screenshot of each: Default, Appearance, Size, Disabled, etc.
GitHubで見る