reatom/reatom/kahraman-storybook-testing

Trust tier 3
  • community
  • ext:[{"type":"hook","description":"Pre/post lifecycle hooks"},{"type":"plugin","description":"Custom plugin integration"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Apply kahraman's recommended style when writing, extending, reviewing, or debugging Storybook interaction tests and portable stories. Use for Storybook `*.stories.ts(x)` tests, accessible actor/locator assertions, user-journey structure, async stabilization, taming noisy Testing Library element-not-found diagnostics, and maintaining a project-local `.storybook/README.md`. Also guides optional MSW state stories and responsive variants when configured.

Install

npx vskill@latest install reatom/reatom/kahraman-storybook-testing

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

Kahraman's Recommended Storybook Testing Style

Use Storybook stories as executable user journeys. A story supplies a reproducible application state; its test documents what a user can perceive and do in that state. Prefer a small number of clear scenarios over one test that branches through unrelated states.

This is a recommended style, not a requirement that every project adopt the same Storybook stack. The actor and accessibility-first locator guidance is the core. MSW state modeling, routing helpers, responsive variants, screenshots, and other Storybook integrations are optional enhancements when their prerequisites exist.

Setup prerequisites

Core prerequisites

This skill extends a configured Storybook project; it does not bootstrap Storybook or choose its story architecture. Before changing interaction tests, confirm that all of these already exist:

  • .storybook/main.* and .storybook/preview.* (or the equivalent configured

Storybook directory), including browser test execution;

  • at least one working *.stories.ts or *.stories.tsx file that establishes

the repository's CSF or preview-factory format; and

  • kahraman exposed to stories and initialized with their Storybook context.
Optional integration prerequisites

Apply an optional recommendation only when its setup is already present:

  • MSW state stories require MSW, the Storybook MSW addon/loader initialized

in preview, and a project convention for registering and overriding handlers.

  • Responsive variants require a project-owned viewport map aligned with the

application's CSS breakpoints, configured Storybook viewport globals, and a browser-test hook that applies the selected global to the real test page. Setting globals.viewport alone may update Storybook state without resizing the browser used by the Storybook/Vitest integration.

  • Route/deep-link stories require the application's Storybook routing or URL

bootstrap and an established parameter/decorator convention.

  • Visual assertions require the project's screenshot or visual-regression

runner and naming convention.

If a prerequisite is missing, say which one is missing. Ask whether to add that integration or omit the optional variant; do not silently bootstrap an opinionated stack. Do not invent preview imports, meta.story() APIs, aliases, test callbacks, handler wiring, viewport names, or routing parameters.

First inspect the project's conventions

Read .storybook/README.md first when it exists. Then verify its claims against .storybook/main.*, .storybook/preview.*, package scripts, an interaction story near the feature, and actor helpers. When optional integrations are relevant, also inspect their existing handlers, decorators, globals, and parameters. Reuse the project's Storybook API (preview.meta(...).story(...) or CSF Meta / StoryObj) rather than mixing patterns.

Maintain a project-local Storybook guide

Recommend keeping .storybook/README.md beside the configuration as the project's self-contained guide for writing and reviewing interaction stories. This local document should preserve the essence of Kahraman's recommended style while replacing generic setup guidance with verified project facts.

Create or update it after inspecting the project, not by blindly copying this skill. Strip prerequisites that the repository already satisfies, generic installation instructions, alternative APIs the project does not use, and examples that conflict with local conventions. Keep a short link to Kahraman as the upstream rationale, but make the local guide sufficient for everyday work.

Capture the conventions a contributor otherwise has to rediscover:

  • the exact story format and actor initialization hook (loaders, beforeEach,

or play), with imports from the project's adapter;

  • where stories, fixtures, page actors, mock handlers, and low-level test helpers

belong, including the boundary between reusable mechanics and domain journeys;

  • accessible locator, scoping, stabilization, retry, and optional-UI agreements;
  • package-manager scripts for Storybook, interaction tests, watch mode, and

focused runs, including unsupported CLI flags or other local gotchas;

  • tag meanings and CI agreements, such as @smoke for gating journeys and

@visual for intentional screenshot contracts;

  • configured viewport names, their source file, breakpoint agreement, and the

preview test-runner resize workaround when responsive testing is enabled;

  • MSW handler registration and override conventions, routing/deep-link

parameters, persisted-state reset behavior, and cleanup hooks when present;

  • screenshot helpers, baseline naming/review policy, diagnostics flags, and

boundaries that legitimately require raw DOM or browser APIs.

Only document conventions supported by code or scripts in the current repository. Use exact local paths and commands. If the guide is stale, update it in the same change when the relevant Storybook agreement changes. Avoid turning it into a copy of all Storybook configuration; explain the contributor-facing contract and point to implementation files for details.

Reference application setups

Use these applications as examples of the recommended style in a working Storybook stack:

— application integration stories with MSW, routing, project breakpoints, and a preview hook that applies viewport globals to the browser test page.

— Reatom Admin's project adapter, preview factory, browser-test setup, viewport configuration, and project-local testing guide.

Read their current configuration and nearby stories when a concrete example is useful. Treat them as references, not templates: copy no alias, command, tag, handler, breakpoint, or lifecycle convention until the target project supports it.

For a project using kahraman, import the page actor and semantic locators:

ts
import preview from '#.storybook/preview'
import { App } from '#app/App'
import { featureActor as I } from '#pages/feature/testing'
import { button, heading, link, role, text } from '#shared/test'
const meta = preview.meta({
title: 'Integration/Feature',
component: App,
parameters: { layout: 'fullscreen', initialPath: 'feature' },
loaders: [(context) => I.init(context)],
})
export default meta

I.init(context) is required before actor calls. It binds the Storybook canvas, userEvent, and a fresh step trace. If the repository uses plain StoryObj, initialize the actor at the beginning of play instead.

Use the actor API before dropping to low-level test calls

Prefer Kahraman's intent-level methods when they express the interaction or assertion. Besides see, dontSee, click, and fill, check for the existing actor operations before reaching for raw userEvent or DOM assertions:

  • field and state assertions: seeInField, seeChecked, seeDisabled,

seeAttribute, and seeNumberOfElements;

  • interactions: clear, selectOption, and press;
  • extraction: grabTextFrom and grabTextFromAll;
  • controlled resilience: tryTo, retryTo, and hopeThat.

Use tryTo only for genuinely optional behavior, not to turn a required outcome into a silent branch. Use hopeThat when several independent assertions should be reported together, and finish with I.hopeThat.noErrors() so collected failures cannot pass unnoticed. Raw Storybook/browser APIs remain appropriate for capabilities the actor does not model, such as focus, history, geometry, or screenshots.

Build reusable page vocabulary with actor extensions

Use I.extend(...) for reusable page-level controls and expectations. Keep an extension narrowly typed to the base actor methods it needs, and name its methods in user/domain language. Extensions should remove repeated mechanics without hiding the causal steps or business outcome of a story. Prefer seeError() or selectCountry() over an opaque completeCheckoutJourney() helper.

Keep environment-specific pacing explicit in actor construction. If manual Storybook playback benefits from visible clicks, configure clickDelay in the project adapter while retaining a zero delay for automation; do not slow every browser test by default.

Address the UI as a user would

Use role, heading, button, link, and text, with accessible names:

ts
await I.see(heading('Billing'))
await I.fill(role('textbox', 'Email'), 'ada@example.com')
await I.click(button('Save'))
await I.see(role('alert'))

This is both a robust selector strategy and an accessibility check. Do not use CSS selectors, test IDs, DOM traversal, or text-content matching when a role and name can express the intent. Use text(...) for genuinely non-semantic visible content.

Use locator modifiers deliberately:

  • locator.wait() waits for an element that will appear.
  • locator.maybe() makes an optional lookup nullable; use it only when an

optional overlay must be acted on.

  • locator.all() asserts or extracts a collection.
  • locator.within(container) limits a query to a region; it accepts a locator,

captured HTMLElement, or 'global' to escape the current actor scope.

  • locator.options(...) supplies Testing Library query options.

Scope feature assertions to the region under test so global chrome and toasts do not produce false matches:

ts
await I.within(role('main'), async () => {
await I.click(link('Quarterly report'))
await I.waitExit(role('status'))
await I.see(heading('Quarterly report'))
})

Capture a stable container once when one panel swaps between states. Assert both sides of a mutually exclusive transition:

ts
const panel = await I.see(role('main'))
await I.see(text('No article selected').within(panel))
await I.dontSee(heading('Quarterly report').within(panel))
await I.click(link('Quarterly report'))
await I.waitExit(role('status', 'Loading article detail').within(panel))
await I.dontSee(text('No article selected').within(panel))
await I.see(heading('Quarterly report').within(panel))

Stabilize on observable lifecycle signals

Do not add arbitrary sleeps. Loaded and async-error stories should normally wait for their loading status to leave the UI:

ts
export const Default = meta.story({
name: 'Default',
play: () => I.waitExit(role('status')),
})

After an action that starts a request, click, wait for the relevant status to exit, then assert the result. Use .wait() only when no stable exit signal exists. A persistent-loading story intentionally keeps its request pending, so it must not use a broad waitExit(role('status')); assert its loading UI instead. If a parent guard settles while a feature request intentionally hangs, wait only for that named parent status.

Use I.retryTo for a documented eventual UI transition that has no better lifecycle signal. Explain why it is needed in a comment. Avoid retries that hide a broken synchronization contract.

Optional recommendation: model server states with MSW

Use this pattern only when the project already satisfies the MSW prerequisites listed in setup. Kahraman does not require MSW, and a project may use another network stub, injected service, fixture, or no network layer at all.

When deterministic server-state mocking is available, separate stories for success, failure, and persistent loading make those states reproducible and remove branching from tests. Reuse the application's handlers and override only the affected handler key:

ts
export const FeatureLoadServerError = meta.story({
name: 'Feature Load Server Error',
parameters: { msw: { handlers: { featureList: featureList.error } } },
play: () => I.waitExit(role('status')),
})

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Extension points

  • hookPre/post lifecycle hooks
  • pluginCustom plugin integration

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/reatom/reatom/kahraman-storybook-testing/badge)](https://verified-skill.com/skills/reatom/reatom/kahraman-storybook-testing)

Something wrong with this skill or its page? Tell us.