Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

React: Add testing utilities #12959

Closed
wants to merge 18 commits into from
Closed

React: Add testing utilities #12959

wants to merge 18 commits into from

Conversation

yannbf
Copy link
Member

@yannbf yannbf commented Oct 30, 2020

Issue: #10145

What I did

Add a testing utility to @storybook/react to compose a story with decorators and parameters so that it can be easily reused in tests with tools like testing library.

This allow for codes in test files that would otherwise have quite some boilerplate to be as simple as:

1 - with composeStories, composing all stories

import { render } from '@testing-library/react';
import { composeStories } from '@storybook/react';
import * as stories from './Button.stories';

// Every component that is returned maps 1:1 with the stories, but they already contain all decorators from story level, meta level and global level.
const { Primary, Secondary } = composeStories(stories);

test('renders primary button with Hello World', () => {
  const { getByText } = render(<Primary>Hello world</Primary>); // You get props with autocompletion and you can override them, otherwise it will use the default values from the Story's args
  expect(getByText(/Hello world/i)).not.toBeNull();
});

2 - with composeStory, if you wish to do so for a single story

import { render } from '@testing-library/react';
import { composeStory } from '@storybook/react';
import Meta, { Primary as PrimaryStory } from './Button.stories';

// Returns a component that already contain all decorators from story level, meta level and global level.
const Primary = composeStory(PrimaryStory, Meta);

test('renders primary button with Hello World', () => {
  const { getByText } = render(<Primary>Hello world</Primary>); // You get props with autocompletion and you can override them, otherwise it will use the default values from the Story's args
  expect(getByText(/Hello world/i)).not.toBeNull();
});

Global config

If you have global decorators/parameters/etc and want them applied to your stories you need to first set it up. You can either do it in a setup file that should run once, before composeStory(ies) will be used, for instance:

// setupFile.js <-- this will run before tests in jest.
import { setGlobalConfig } from '@storybook/react';
import * as globalStorybookConfig from './.storybook/preview';

setGlobalConfig(globalStorybookConfig);

Or you're free to use either API and pass a global config directly as a parameter, though I won't recommend because it requires more effort:

import * as globalConfig from '../.storybook/preview';

const { Primary } = composeStories(stories, globalConfig);
const Primary = composeStory(PrimaryStory, Meta, globalConfig);

How to test

1 - yarn bootstrap or yarn build addons react --watch if you prefer (addons just for the types, because react uses base types from addons)
2 - go to examples/cra-ts-essentials
3 - run SKIP_PREFLIGHT_CHECK=true yarn test (there's a compatibility problem with jest versions in the monorepo and the project, so just skip it for now and the tests should work)

  • Is this testable with Jest or Chromatic screenshots?
    Yes
  • Does this need a new example in the kitchen sink apps?
    Yes, added in examples/cra-ts-essentials project
  • Does this need an update to the documentation?
    Added, but I need feedback

Further work

It's quite interesting to bring this to other major frameworks like Vue and Angular, but the way the tests are written is quite different (every framework with their specific peculiarities) and it would require further research and specific setup to allow them to take advantage of a testing utility like this one. I believe we should release this for React only first, get some feedback and then start working on other frameworks.

lib/addons/src/types.ts Outdated Show resolved Hide resolved
@yannbf yannbf changed the title Feature/testing utilities React: add testing utilities Dec 24, 2020
@yannbf yannbf self-assigned this Dec 30, 2020
@yannbf yannbf force-pushed the feature/testing-utilities branch from 72294ab to ddd4520 Compare December 30, 2020 15:46
@yannbf yannbf marked this pull request as ready for review December 30, 2020 15:47
@yannbf yannbf force-pushed the feature/testing-utilities branch from ddd4520 to 2e2b507 Compare January 2, 2021 09:16
@yannbf
Copy link
Member Author

yannbf commented Jan 2, 2021

Hey @shilman @tmeasday I think this is finally ready. Would you like to give this a spin? 😎

@kylegach would be nice to get your feedback too!

@shilman shilman changed the title React: add testing utilities React: Add testing utilities Jan 2, 2021
@shilman shilman added the react label Jan 2, 2021
@tmeasday
Copy link
Member

tmeasday commented Jan 4, 2021

@yannbf I have this on my TODO list to take a proper look. I was a bit slammed at the end of the year and am away for another week but I should get a chance to look at it after that!

Copy link
Contributor

@kylegach kylegach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't check out the branch and run it locally, but I did copy/paste the composeStory function into my project (along with some of the new/updated types) and it worked as expected.

Thanks, Yann!

@yannbf
Copy link
Member Author

yannbf commented Jan 4, 2021

I didn't check out the branch and run it locally, but I did copy/paste the composeStory function into my project (along with some of the new/updated types) and it worked as expected.

Thanks, Yann!

Thanks for doing this! and thanks for the feedback :))
The only challenge I was not able to solve, and I think it might not even be possible with the typings that I did.. was to return components of type Story<Partial<Args>> rather than Story<Args> in the composeStories function. The types are correct for composeStory though!

Copy link
Member

@tmeasday tmeasday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, this is great! One question

Comment on lines +38 to +63
if (!passArgsFirst) {
throw new Error(
'composeStory does not support legacy style stories (with passArgsFirst = false).'
);
}
return story(context.args as GenericArgs, context);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (!passArgsFirst) {
throw new Error(
'composeStory does not support legacy style stories (with passArgsFirst = false).'
);
}
return story(context.args as GenericArgs, context);
return passArgsFirst ? story(context.args as GenericArgs, context) : story(context);

Was there a reason not to just do this? I'm not sure if it is a big deal to support non-passArgsFirst but this is simple enough?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO we shouldn't support legacy CSF on new features. if you want to use it, migrate!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if we should resolve this conversation :D
I'm happy to do either way

@mracette
Copy link

Thanks for writing this PR, it's going to really help me out.

@yannbf
Copy link
Member Author

yannbf commented Jan 12, 2021

Thanks for writing this PR, it's going to really help me out.

Thanks for commenting! It's because of people like you that open source is worth doing 😄

@yannbf yannbf force-pushed the feature/testing-utilities branch 2 times, most recently from 90003dd to 1330558 Compare January 20, 2021 07:44
@mracette
Copy link

Just wanted to check in here, is the plan still to get this released soon? I've been holding out on writing some unit tests because I wanted to try this out, but I'm not sure how much longer I can wait 😅

@yannbf
Copy link
Member Author

yannbf commented Mar 15, 2021

Just wanted to check in here, is the plan still to get this released soon? I've been holding out on writing some unit tests because I wanted to try this out, but I'm not sure how much longer I can wait 😅

Hey Mark, thanks for this message! Currently we are discussing wether this feature would go in the repo or in a separate package. You will hear some news soon, thanks for your patience 🙏

@shilman
Copy link
Member

shilman commented Mar 18, 2021

this has been released as a standalone addon. closing!

https://github.com/storybookjs/testing-react

@shilman shilman closed this Mar 18, 2021
@theinterned theinterned removed their request for review January 31, 2022 17:40
@stof stof deleted the feature/testing-utilities branch May 25, 2022 09:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants