-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
stories.add calls story function twice #707
Comments
UPDATE: judging from the stack: CALL 1:
CALL 2:
It's because the component is rendered twice due to multiple redux dispatches: function _renderMain(loaders) {
if (loaders) loaders();
var stories = this._storyStore.dumpStoryBook();
// send to the parent frame.
this._channel.emit('setStories', { stories: stories });
// clear the error if exists.
this._reduxStore.dispatch((0, _actions.clearError)()); // CALL 1
this._reduxStore.dispatch((0, _actions.setInitialStory)(stories)); // CALL 2
} But does the user's code really need to be re-rendered twice. Perhaps I know React StoryBook wasn't initially for redux usage, but it makes a damn good tool for working on your whole application--from tests to redux and more--if you know how to get the most use out of it. I don't see why it can't evolve into a tool that expects many users to be using Redux. In fact, it's a lot of throwaway work if this is just for designing components, and eventually you stop using the tool. Because the thing is as your app becomes real, half your components become connected redux containers. So if Storybook components aren't wrapped in a redux provider, you are left maintaining 2 codebases: your real app, and raw components, which expect a different set of props. It's way more efficient to be thinking in terms of the same set of connected container components. That way Storybook is more than just a designer's tool. Combine first-class redux support/usage with tests, and you have a way to bring up any focal point of your app and get down to business with ease. You basically can setup key areas you work on, and have a consistent state to expect once you get there--with passing/failing tests further informing you on what the "state" of the given area is. Storybook lets you "bookmark" that state if you're using Redux. And not just the pretend raw component version of your app, but your real app. I don't see why anyone wouldn't want that. So tests just make it even more important things are reliably rendering. But it's not just limited to tests. Of course a test should be able to re-run and not be dependent on how many times it ran, but because of the unique nature of Storybook and the Specifications plugin, it's useful to think of each A redux dispatch batching package would easily solve this as well. It's generally more efficient too. Another reason why to fix/enhance this: if you're putting any logging in your story, you're going to see 2 logs and wonder why. This sort of thing, as small as it is, does not breed confidence. It's a bad signal to developers that leaves them scratching their head. |
In addition to double rendering your component,
and possibly this one:
This is specifically when you wrap your components in a provider without using The reason I'm doing it outside of describe('AnimatedTransitionGroup 1', () => {
it('blue', () => {
console.log('RENDER')
const { story, store } = setupStory()
store.dispatch({ type: 'CHANGE', payload: 'blue' })
store.dispatch({ type: 'BLUR', payload: 'blue' })
const { color } = store.getState()
expect(color).toEqual('blue')
const component = renderer.create(story)
expect(component).toMatchSnapshot()
return story // when run in Storybook, this will become the return of `stories.add()`
})
it('red', () => {
const { story, store } = setupStory()
store.dispatch({ type: 'CHANGE', payload: 'red' })
store.dispatch({ type: 'BLUR', payload: 'red' })
const { color } = store.getState()
expect(color).toEqual('red')
const component = renderer.create(story)
expect(component).toMatchSnapshot()
return story // when run in Storybook, this will become the return of `stories.add()`
})
it('just tests, no story returned', () => {
expect(1).toEqual(1)
expect(2).toEqual(2)
expect(3).toEqual(3)
expect(1).toEqual(1)
// notice no story is returned
})
it('more equal tests', () => {
expect(66).toEqual(66)
expect(55).toEqual(55)
// notice no story is returned
})
}) What I got going is extremely slick. Here's why: it lets you write tests as normal, and not worry that you're possibly messing it up by mixing in storybook calls will mess up your tests. Your tests are the same as before, with the very minor option of returning a It means your Storybook code is way more likely to stay maintained throughout the life of the project. For the importance of mixed snapshot testing, the real win is that you only need to setup components once and it is re-used between both Storybook and your tests. That is the win here. I got it working extremely nicely for me right now. Give it a quick try to see what I'm talking about:
If you're using Wallaby, the tests will run very nicely there, and your snapshots will appear there, diffed when failing. Wallaby + Storybook are perfect companions. The files worth looking at are: THE TESTS: THE FACADE FOR STORYBOOK: THE FACADE FOR JEST: So anyway, just look at the above test code. It's clearly an elegant interface to just be able to return your story component from your |
...what it does break is hot reloading on the store. This is more related to the issue of using a redux The marketing idea here is big for Storybook. It's: Apply Storybook to your tests overnight. And boom Storybook is 10 times more useful. Any code that is already testing components, taking snapshots of them, etc, but not using Storybook can instantly make use of Storybook just by returning the |
Voicing desire for the same: this is a really good use-case and am keen to work on it as well, though not only through the lens of Redux. |
This sounds amazing 😍 ! I'm hoping someone will be willing to experiment further and possible create a PR? |
@adamellsworth @ndelangen here it is: https://github.com/faceyspacey/jest-storybook-facade Turn your tests into react storybooks in minutes by applying that and returning your components from tests. Let me know how it works out for you. |
So I've also done some experimentation with jest & storybook & browsers and experienced it was just not feasible to run real jest in the browser or to rewrite jest for the browser. Jest has a pretty large API surface and is extendable. This will be used, and expected to work. I love you're using But if we could find a reliable way, that'd be amazing! |
check the code, I mocked a lot more of Jest. The API surface isn't that big. We can totally get it up to par. Here are my notes from the readme on further improving the mocks: https://github.com/faceyspacey/jest-storybook-facade#help-us-improve-storybook-facadejs here's the the most valuable thing is that |
Hey @faceyspacey think you could open a PR fixing this? |
I've been meaning to get to this and invest serious time. I have quite a serious agenda in this area. But I'm a month off Id say. |
HI guys, I face same issue here, is there any progress? or any workaround? thanks a lots!! |
Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 60 days. Thanks! |
Hey there, it's me again! I am going close this issue to help our maintainers focus on the current development roadmap instead. If the issue mentioned is still a concern, please open a new ticket and mention this old one. Cheers and thanks for using Storybook! |
I had this error message too. Apparently, I was missing my import statement in |
Is there any reason why
func
instories.add('name', func)
is called twice?I'm working on furthering the capabilities of
storybook-addon-specifications
and I'd like to guarantee the tests contained infunc
are not called more than once.Is this the normal behavior and is there any way to guarantee its called only once?
The text was updated successfully, but these errors were encountered: