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

default component args missing from importing named export stories in unit tests #14278

Open
Tracked by #25875
dptoot opened this issue Mar 19, 2021 · 10 comments
Open
Tracked by #25875

Comments

@dptoot
Copy link

dptoot commented Mar 19, 2021

When importing named export stories into unit tests as described in the docs any defaulted component args are not retained

To Reproduce
Steps to reproduce the behavior:

My story file is as follows

export default {
    component: Button,
    title: 'Button',
    args: {
        label: 'My Button',
        href: 'https://www.foo.com',
    },
};

const Template = args => (<Button {...args} />);

export const OffsiteButton = Template.bind({});
OffsiteButton.args = {
    offsite: true,
};

and then I import it into my unit as described in the docs like so:

import { OffsiteButton } from './Button.stories';

it('renders offsite button', () => {
    const wrapper = shallow(<OffsiteButton { ...OffsiteButton.args } />);
});

The resulting rendered element has the offsite arg assigned but is missing the label and href args assigned in the default export. This is not the case when storybook renders the story.

Expected behavior
I would have expected the default export args and the component args to be merged. But the args defined in the default export are missing.

System

 System:
    OS: Windows 10 10.0.19042
    CPU: (8) x64 Intel(R) Core(TM) i5-8400H CPU @ 2.50GHz
  Binaries:
    Node: 12.16.3 - C:\Program Files\nodejs\node.EXE
    npm: 6.14.4 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Chrome: 89.0.4389.90
    Edge: Spartan (44.19041.423.0), Chromium (89.0.774.48)
  npmPackages:
    @storybook/addon-essentials: ^6.2.0-rc.0 => 6.2.0-rc.0
    @storybook/addon-links: ^6.2.0-rc.0 => 6.2.0-rc.0
    @storybook/builder-webpack5: ^6.2.0-rc.0 => 6.2.0-rc.0
    @storybook/preset-scss: ^1.0.3 => 1.0.3
    @storybook/react: ^6.2.0-rc.0 => 6.2.0-rc.0

Temp solution:
I can manually merge the named and default export args manually and assign them but that seems to default the purpose of the default args in storybook.

import ButtonDefaults, { OffsiteButton } from './Button.stories';
it('renders offsite button', () => {
    const wrapper = shallow(<OffsiteButton {...{ ...ButtonDefaults.args, ...OffsiteButton .args }} />);
});
@shilman
Copy link
Member

shilman commented Mar 20, 2021

@tmeasday @yannbf we've addressed this in https://github.com/storybookjs/testing-react -- looks like this is also a problem inside storybook itself ... any thoughts?

@dptoot
Copy link
Author

dptoot commented Mar 20, 2021

Thanks! That utility looks like a good solution to what I was seeing! Looks like I will be getting us in on the ground floor. :)

looks like this is also a problem inside storybook itself ... any thoughts?

I personally don't see similar issues within storybook itself at this time so I wanted to make sure this wasn't based off something I said.

Thanks for the quick response!

@shilman
Copy link
Member

shilman commented Mar 20, 2021

Those utilities are meant for using stories inside jest where you are lacking the storybook runtime. In your case, the problem you're describing is happening inside storybook itself. Which makes me wonder whether we should be providing at least part of that utility inside Storybook core rather than as a standalone library.

In the short term you can def use that library--it's great!

@dptoot
Copy link
Author

dptoot commented Mar 20, 2021

Forgive me if I am misunderstanding... I just want to make sure I am not sending you down the wrong path.

My issue was indeed that I was re-using stories in separate Jest unit tests and the defaults we not being applied... which it seems like this great utility provides... as far as usage in the storybook runtime environment I am seeing everything work as expected. I know there are addons that provide the ability to run tests within storybook runtime and that maybe what you are referring to but that isn't my scenario, yet :)

Thanks again for the help and the great storybook work!

@shilman
Copy link
Member

shilman commented Mar 20, 2021

Aha, thanks for the clarification -- I misunderstood. In that case, @storybook/testing-react is exactly designed to solve your problem!

@dptoot
Copy link
Author

dptoot commented Mar 20, 2021

@shilman
@tmeasday
@yannbf

I am afraid I may have to take back what I said... It does look like I am seeing some similar issue within the storybook runtime if I reused predefined story components within other storybook stories. It does look like the default values are being removed. Take the following example:

export default {
    title: 'AdSlot',
    component: AdSlot,
    args: {
        size: [[300, 250], [728, 90]],
    },
};

const Template = args => <AdSlot {...args} />;

export const BasicAd = Template.bind({});
BasicAd.args = {
    // size: [[300, 250], [728, 90]],
    slotId: 'ad-num-1',
};

export const MountedAd = args => (
    <DFPProvider>
                  <BasicAd {...BasicAd.args} />
    </DFPProvider>
);

MountedAd story will not have the default args.size applied and only if they are specifically defined in the BasicAd.args component props (which I have commented out in the example). Unless I am mistaken I would have expected any usage of BasicAd to have inherited the default args upon its reuse in storybook. I reserve this may not be the 100% correct pattern and that my MountedAd story should perhaps be using a decorator but I will need a story with multiple BasicAds so I would have thought this would work as desired? Thoughts?

@tmeasday
Copy link
Member

tmeasday commented Mar 21, 2021

@shilman we should update our documentation to (at least in the react case) encourage the use of @storybook/testing-react, WDYT?

@dptoot -- there isn't really much SB can do about this one, you are literally just calling the BasicAd "component" in React with BasicAd.args, which of course doesn't automatically inherit, only when passed through the SB runtime. So what you are seeing is what I would expect (although it clearly isn't ideal!)

This does seem like another argument against the Template.bind({}) approach and for a version where we do the arg-inheritance/decorator binding at story definition time, something like:

import { createTemplate } from '@storybook/react';

const componentMeta = {
  title: 'AdSlot',
  // ...
}
export default componentMeta;

// This template knows about `componentMeta`, and also possible the global stuff too, somehow
const Template = createTemplate(componentMeta);
export const BasicAd = Template.clone();

@shilman
Copy link
Member

shilman commented Mar 22, 2021

@tmeasday perhaps this is something we can take care of as part of #12654

I agree about the documentation update. I also wonder whether we can migrate the react-independent bits to core.

@dptoot
Copy link
Author

dptoot commented Mar 26, 2021

Thanks for the help all. Seems like there might be a plan in place to provide this functionality and I look forward to using it :)

@adamdiestelkamp
Copy link

Hey! I'm running into this issue with Storybook when trying to group my Doc stories into a single snapshot for Chromatic.

I'm importing the stories for a particular component and then displaying them all together on a single page
import * as stories from './docs.stories';

But running into the same issue of if the story was using Template.bind({}) it doesn't display correctly which makes the visual test for that case useless.

Using the composeStories() worked great though. Would have been nice if this had been default or available within Storybook directly but glad you all had this thread, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants