Skip to content

CSF: Fix Canvas and userEvent types under Yarn PnP#34986

Merged
valentinpalkovic merged 3 commits into
storybookjs:nextfrom
yatishgoel:fix/30763-canvas-types-pnp
Jun 3, 2026
Merged

CSF: Fix Canvas and userEvent types under Yarn PnP#34986
valentinpalkovic merged 3 commits into
storybookjs:nextfrom
yatishgoel:fix/30763-canvas-types-pnp

Conversation

@yatishgoel

@yatishgoel yatishgoel commented May 30, 2026

Copy link
Copy Markdown
Contributor

Closes #30763

What I did

Fixes Canvas and StoryContext.userEvent types not resolving in play functions under Yarn PnP (and other strict TS setups).

Root cause. code/core/src/test/index.ts was contributing those types via a declare module 'storybook/internal/csf' augmentation. Module augmentations only take effect when TypeScript actually loads the augmenting module into its program. Under Yarn PnP, that load doesn't happen automatically, so consumers got the empty interface Canvas {} shipped in dist/csf/index.d.ts and a StoryContext with no userEvent field — manifesting as Property 'findByRole' does not exist on type 'Canvas' and similar errors.

The workarounds that circulated on the issue (import 'storybook/test' in every story, "types": ["storybook/test"] in tsconfig.json, adding @storybook/core to user deps, .yarnrc.yml packageExtensions) all worked but pushed the burden onto every user.

Fix. Declare the real types directly on the base interfaces in code/core/src/csf/story.ts instead of augmenting them from outside:

  • interface Canvas extends BoundFunctions<typeof queries> {}
  • StoryContext gains userEvent: ReturnType<typeof userEvent.setup>

…and remove the now-redundant declare module block (plus its supporting imports/aliases) from code/core/src/test/index.ts.

Why this is safe.

  • Both new imports are import type only — zero runtime impact.
  • @testing-library/dom and @testing-library/user-event are already direct runtime dependencies of storybook (see code/core/package.json), so no new dependency is added.
  • No public API change: consumers continue to get Canvas and StoryContext.userEvent exactly as documented; they just now resolve correctly regardless of package manager or tsconfig.
  • Net change is +5 / −12 lines across two files.

Checklist for Contributors

Testing

The changes in this PR are covered in the following automated tests:

  • stories
  • unit tests
  • integration tests
  • end-to-end tests

This is a type-only change to interface declarations in code/core/src/csf/story.ts. There is no runtime behavior to test, and the existing yarn nx check core (run as part of CI) exercises the new declarations against the rest of the type graph in the monorepo — that target passes locally.

Manual testing

Caution

This section is mandatory for all contributions. If you believe no manual test is necessary, please state so explicitly. Thanks!

Reproduction steps for the original bug (current next, before this fix):

  1. Create a fresh project with Yarn Berry and PnP linker:
    mkdir repro && cd repro
    yarn init -2 -y
    echo "nodeLinker: pnp" > .yarnrc.yml
  2. Install Storybook:
    yarn add storybook@10.5.0-alpha.3 typescript
  3. Add a tsconfig.json with "moduleResolution": "Bundler" and a story-like file using canvas inside a play function:
    import type { StoryContext, Renderer } from 'storybook/internal/csf';
    
    type R = Renderer & { canvasElement: HTMLElement };
    
    export async function play({ canvas, userEvent }: StoryContext<R, {}>) {
      const el = await canvas.findByRole('button');
      await userEvent.click(el);
    }
  4. Run yarn tsc --noEmit.

Before this PR:

error TS2339: Property 'findByRole' does not exist on type 'Canvas'.

After this PR (using a tarball packed from this branch via yarn nx compile core -c production && yarn workspace storybook pack):

EXIT=0

Documentation

  • Add or update documentation reflecting your changes
  • If you are deprecating/removing a feature, make sure to update
    MIGRATION.MD

No docs update required — the public types remain Canvas and StoryContext.userEvent exactly as documented. This PR makes them resolve in the cases where they previously didn't.

Checklist for Maintainers

  • When this PR is ready for testing, make sure to add ci:normal, ci:merged or ci:daily GH label to it to run a specific set of sandboxes. The particular set of sandboxes can be found in code/lib/cli-storybook/src/sandbox-templates.ts

  • Make sure this PR contains one of the labels below:

    Available labels
    • bug: Internal changes that fixes incorrect behavior.
    • maintenance: User-facing maintenance tasks.
    • dependencies: Upgrading (sometimes downgrading) dependencies.
    • build: Internal-facing build tooling & test updates. Will not show up in release changelog.
    • cleanup: Minor cleanup style change. Will not show up in release changelog.
    • documentation: Documentation only changes. Will not show up in release changelog.
    • feature request: Introducing a new feature.
    • BREAKING CHANGE: Changes that break compatibility in some way with current major version.
    • other: Changes that don't fit in the above categories.

Suggested label: bug.

🦋 Canary release

This PR does not have a canary release associated. You can request a canary release of this pull request by mentioning the @storybookjs/core team here.

core team members can create a canary release here or locally with gh workflow run --repo storybookjs/storybook publish.yml --field pr=<PR_NUMBER>

Summary by CodeRabbit

Release Notes

  • New Features
    • Story context now includes Testing Library query functions for enhanced testing capabilities within stories.
    • Added user event utilities directly accessible in the story environment for interactive testing workflows.

Review Change Stack

yatishgoel and others added 2 commits May 30, 2026 10:30
…oundFunctions from testing-library. This improves integration with user interactions in tests.
@coderabbitai

coderabbitai Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a7c2f681-b0a7-4588-81e6-1a0bacfe55bf

📥 Commits

Reviewing files that changed from the base of the PR and between d6ce689 and 099c701.

📒 Files selected for processing (2)
  • code/core/src/csf/story.ts
  • code/core/src/test/index.ts
💤 Files with no reviewable changes (1)
  • code/core/src/test/index.ts

📝 Walkthrough

Walkthrough

This PR consolidates testing-library type definitions by moving Canvas and StoryContext.userEvent types from a module augmentation pattern in test/index.ts to direct interface definitions in story.ts, reducing indirection and centralizing type contracts in the canonical CSF module.

Changes

Testing-Library Type Integration

Layer / File(s) Summary
Canvas and StoryContext typing in story.ts
code/core/src/csf/story.ts
Adds type-only imports from @testing-library/dom and @testing-library/user-event. Canvas interface is updated to extend BoundFunctions<typeof queries>. StoryContext interface gains a userEvent field typed as the return type of userEvent.setup().
Remove module augmentation from test index
code/core/src/test/index.ts
Module augmentation that previously extended Canvas and merged userEvent into StoryContext is removed, since those types are now defined directly in story.ts. Remaining exports and UserEventObject type remain unchanged.

🎯 2 (Simple) | ⏱️ ~12 minutes


Comment @coderabbitai help to get the list of available commands and usage tips.

@yatishgoel yatishgoel added the bug label May 30, 2026
@yatishgoel yatishgoel changed the title Enhance StoryContext and Canvas interfaces to include userEvent and BoundFunctions from testing-library CSF: Fix Canvas and userEvent types under Yarn PnP May 30, 2026
@yatishgoel yatishgoel added the ci:normal Run our default set of CI jobs (choose this for most PRs). label May 30, 2026
@valentinpalkovic valentinpalkovic moved this to Empathy Queue (prioritized) in Core Team Projects Jun 1, 2026
@valentinpalkovic valentinpalkovic added the qa:needed Pull Requests that will need manual QA prior to release. label Jun 3, 2026
@valentinpalkovic valentinpalkovic merged commit 23f3fb2 into storybookjs:next Jun 3, 2026
135 checks passed
@github-project-automation github-project-automation Bot moved this from Empathy Queue (prioritized) to Done in Core Team Projects Jun 3, 2026
@github-actions github-actions Bot mentioned this pull request Jun 3, 2026
20 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent-scan:human bug ci:normal Run our default set of CI jobs (choose this for most PRs). csf qa:needed Pull Requests that will need manual QA prior to release. typescript

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

[Bug]: Canvas types in the play function stopped working with Yarn PnP.

2 participants