# Tasks: enterprise-browser-storybook-test-utils **Change ID**: enterprise-browser-storybook-test-utils **Package**: `@suaveplan/storybook-test-utils` **Target path**: `browser/dev/storybook-test-utils` **Prerequisite packages on Verdaccio**: none (no workspace runtime deps) --- ## 0. Pre-flight (non-negotiable) - [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each) - [ ] 0.2 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create directory tree per `proposal.md`. - [ ] `package.json` v0.0.0, `"sideEffects": false`. - `dependencies`: `@suaveplan/logger workspace:^`, `tslib catalog:build` - `peerDependencies`: `@playwright/test` (move from devDependencies) - `devDependencies`: `vitest catalog:testing`, `@vitest/coverage-istanbul catalog:testing`, `@playwright/test catalog:testing`, `@suaveplan/testing workspace:^` - Subpath exports: `"."`, `"./navigation"`, `"./waiting"`, `"./iframe"`, `"./args"`, `"./interactions"`, `"./forms"`, `"./ports"`, `"./story-index"`, `"./assertions"`, `"./fixtures"` - [ ] `tsconfig.json`, `vitest.config.ts` (pool: forks). --- ## 2. Types (`src/types/types.ts`) - [ ] `StoryMetadata`, `WaitOptions`, `UrlOptions`, `StoryIndex`, `StoryIndexEntry`, `AxeOptions`, `AxeResult`. - [ ] Write `types.md`. --- ## 3. `STORYBOOK_PORTS` registry (`src/ports/`) - [ ] `registry.ts` — `STORYBOOK_PORTS: Record` mapping package names to ports (react-ui=6001, react-audio=6004, react-auth=6010, r3f-camera=6019, etc.); `storyUrl(pkg, storyId, opts?)`. - [ ] Write `registry.test.ts` (lookup known port, unknown package throws, `storyUrl` formats correctly). Write `registry.md`. --- ## 4. Navigation (`src/navigation/`) - [ ] `navigation.ts` — `navigateToStory`, `navigateToStoryWithUI`, `switchToStory`, `reloadStory`. - [ ] Drive a stub Storybook HTTP server in tests (serve `iframe.html` + `/?path=/story/…` fixtures). - [ ] Write `navigation.test.ts`. Write `navigation.md`. --- ## 5. Waiting (`src/waiting/`) - [ ] `waiting.ts` — `waitForStoryLoaded`, `waitForStorybookIframe`, `waitForStoryInteractive`. - [ ] Handle SB7 vs SB8 iframe selector differences via auto-detection. - [ ] Write `waiting.test.ts`. Write `waiting.md`. --- ## 6. Iframe access (`src/iframe/`) - [ ] `iframe.ts` — `getStorybookFrame`, `getStoryCanvas`. - [ ] Write `iframe.test.ts`. Write `iframe.md`. --- ## 7. Args (`src/args/`) - [ ] `args.ts` — `getStoryArgs`, `updateStoryArgs`. - [ ] Write `args.test.ts`. Write `args.md`. --- ## 8. Interactions (`src/interactions/`) - [ ] `interactions.ts` — `clickWithFallback`, `getClickableElement` (handles autoplay policies, strict-mode locator). - [ ] Write `interactions.test.ts`. Write `interactions.md`. --- ## 9. Forms (`src/forms/`) - [ ] `forms.ts` — `getFormFromStory`. - [ ] Write `forms.test.ts`. Write `forms.md`. --- ## 10. Story-index discovery (`src/story-index/`) - [ ] `index-loader.ts` — `loadStoryIndex(baseUrl)` fetches `index.json`; `defineStoryId(kind, name)` returns canonical ID. - [ ] Write `index-loader.test.ts` (stub server, parse, missing story throws). Write `index-loader.md`. --- ## 11. Assertions (`src/assertions/`) - [ ] `console.ts` — `expectNoConsoleErrors(page, opts?)` captures console logs during test and fails on unexpected errors. - [ ] `network.ts` — `expectNoFailedRequests(page)`, `expectAllFontsLoaded(page)`. - [ ] `a11y.ts` — `auditAccessibility(page, opts?)` runs axe-core in the story iframe; returns `AxeResult`. - [ ] Write tests for each (stub page + intercepted events). Write `.md` per module. --- ## 12. Playwright fixture (`src/fixtures/`) - [ ] `playwright.ts` — `test.extend({ storybook: [storybookFixture, { scope: 'test' }] })` pre-configured with port registry. - [ ] Write `playwright.md`. --- ## 13. Integration test (`tests/integration.test.ts`) - [ ] Spin up an in-process HTTP server serving stub Storybook HTML. - [ ] Run `navigateToStory` → `waitForStoryLoaded` → `getStoryCanvas` → `updateStoryArgs` → `expectNoConsoleErrors`. --- ## 14. Docs + verify - [ ] Write `.md` per module (≥200 words, API reference, examples). - [ ] Write `README.md` with subpath table, port-registry guide, story-index guide, assertion guide. - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/storybook-test-utils` — green. - [ ] `bunx turbo test:coverage` — 100% (currently 0%). - [ ] No `@ts-expect-error` in `src/`. `@playwright/test` declared as `peerDependency`. - [ ] `STORYBOOK_PORTS` registry replaces at least three consumer hard-coded ports. - [ ] `bun scripts/publish.ts --package @suaveplan/storybook-test-utils`. - [ ] Archive to `openspec/archive/2026-04-24-enterprise-browser-storybook-test-utils/`.