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

addon-backgrounds doesn't play nice with Enzyme #3112

Closed
mrlubos opened this issue Feb 28, 2018 · 7 comments
Closed

addon-backgrounds doesn't play nice with Enzyme #3112

mrlubos opened this issue Feb 28, 2018 · 7 comments

Comments

@mrlubos
Copy link

mrlubos commented Feb 28, 2018

Issue details

I am using backgrounds as a decorator and adding specifications for tests. I want to be able to preview tests in Storybook and change component backgrounds at the same time. Currently I cannot have my cake and eat it, only one or the other works. Specifications use Enzyme to run tests, and that's where the issue occurs with the mount() method before I even write any tests.

Steps to reproduce

See code below.

Please specify which version of Storybook and optionally any affected addons that you're running

  • "@storybook/react": "^3.3.14"
  • "@storybook/addon-backgrounds": "^3.3.14"
  • "storybook-addon-specifications": "^2.1.1"
  • "enzyme": "^3.3.0"
  • "enzyme-adapter-react-16": "^1.1.1"

Screenshots / Screencast / Code Snippets (Optional)

life-is-good.js

import React, { Component } from 'react';
import { storiesOf } from '@storybook/react';
import { mount } from 'enzyme';

storiesOf('life-is-good', module)
  .add('life-is-good', () => {
    const story = (
      <div id="life-is-good">
        Life is good
      </div>
    );
    const mounted = mount(story);
    console.log(mounted.props()); // <- { id: "life-is-good", children: "Life is good" }
    // write fun tests...
    return story;
  });
please-fix.js

import React, { Component } from 'react';
import { storiesOf } from '@storybook/react';
import backgrounds from '@storybook/addon-backgrounds';
import { mount } from 'enzyme';

storiesOf('please-fix', module)
  .addDecorator(backgrounds([
    { name: 'twitter', value: '#00aced', default: true },
    { name: 'facebook', value: '#3b5998' },
  ]))
  .add('please-fix', () => {
    const story = (
      <div id="please-fix">
        Please fix
      </div>
    );
    const mounted = mount(story);
    console.log(mounted.props()); // <- {}
    // no props, no fun :(
    return story;
  });
@mrlubos
Copy link
Author

mrlubos commented Feb 28, 2018

While I am here, backgrounds doesn't mention anything about the requirement to use unique name property for colour names. It's logical, but not mentioned they are used for React keys.

@mrlubos
Copy link
Author

mrlubos commented Feb 28, 2018

Update: By sheer luck I managed to get my use case working, but I can't identify why. Strangely enough, the reported issue still persists. Both of these are executed in the same module, so the imports match. So the more complex wrapper now executes correctly, this simple use case returns empty object.

@Hypnosphi
Copy link
Member

Is the issue present in @3.4.0-alpha.9? We changed the way of adding backgrounds in #2807, now they should be less invasive

@mrlubos
Copy link
Author

mrlubos commented Feb 28, 2018

You know what @Hypnosphi I wonder if that could be it because I didn't really modify the affected module. I did upgrade dependencies between my first message and now, maybe that's what fixed it, I'll check.

EDIT: I am still running the same dependencies listed in the issue.

@mrlubos
Copy link
Author

mrlubos commented Feb 28, 2018

OK I managed to narrow it further down. Before I write the case, note I have upgraded to @3.4.0-alpha.9 so it's actual as of the latest release. In this reproduction I split every module separately and the files are as follows.

Let's look into my config first.

addons.js

import '@storybook/addon-backgrounds/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-options/register';
import 'storybook-addon-specifications/register';

config.js

import { configure } from '@storybook/react';
import { setOptions } from '@storybook/addon-options';
import { configure as Enzyme } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

const adapter = new Adapter();
const req = require.context('../../src', true, /.issue.(js|jsx)$/);
const loadStories = () => req.keys().forEach(filename => req(filename));

setOptions({
  name: 'Lalala',
  url: 'https://example.com',
  hierarchySeparator: /\//,
});

Enzyme({ adapter });

configure(loadStories, module);

Now the modules.

breaks.issue.js

import React from 'react';
import { storiesOf } from '@storybook/react';
import backgrounds from '@storybook/addon-backgrounds';
import { mount } from 'enzyme';

storiesOf('please-fix', module)
  .addDecorator(backgrounds([
    { name: 'twitter', value: '#00aced', default: true },
    { name: 'facebook', value: '#3b5998' },
  ]))
  .add('please-fix', () => {
    const story = (
      <div id="please-fix">
        Please fix
      </div>
    );
    const mounted = mount(story);
    console.log(mounted.props()); // <- {}
    // no props, no fun :(
    return story;
  });

wrapper.issue.js (works)

import { storiesOf } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs/react';
import backgrounds from '@storybook/addon-backgrounds';
import { specs, describe } from 'storybook-addon-specifications';
import { mount } from 'enzyme';

const bgs = [
  { name: 'red', value: 'red' },
  { name: 'blue', value: 'blue' },
];

export default (name, story) => {
  const stories = storiesOf('Wrapper works', module)
    .addDecorator(withKnobs)
    .addDecorator(backgrounds(bgs));

  const { render, tests } = story;

  stories.add(name, () => {
    const node = render();
    specs(() => describe(name, () => tests(mount(node))));
    return node;
  });
};

works.issue.js

import React from 'react';
import chapter from 'index.issue';

chapter('life-is-good', {
  render() {
    return (
      <div id="life-is-good">
        Works!
      </div>
    );
  },
  tests(mounted) {
    console.log(mounted.props()); // <- { id: "life-is-good", children: "Works!" }
  },
});

wrapper.issue.js (breaks)

import { storiesOf } from '@storybook/react';
import backgrounds from '@storybook/addon-backgrounds';
import { specs, describe } from 'storybook-addon-specifications';
import { mount } from 'enzyme';

const bgs = [
  { name: 'red', value: 'red' },
  { name: 'blue', value: 'blue' },
];

export default (name, story) => {
  const stories = storiesOf('Wrapper breaks', module)
    .addDecorator(backgrounds(bgs));

  const { render, tests } = story;

  stories.add(name, () => {
    const node = render();
    specs(() => describe(name, () => tests(mount(node))));
    return node;
  });
};

Conclusion.

What makes it all work is the knobs addon. Specifically, if backgrounds is used, knobs has to be added BEFORE backgrounds. Including it after backgrounds breaks it again. Not including it breaks it as well.

Another observation I made is having both decorators causes the component to run the tests() function twice. On the first run it's always {} regardless of the config, it's the second time it returns the correct props. That is, if knobs was placed before backgrounds. If it's behind it, we receive {} in both runs.

Lastly, having only backgrounds triggers only a single render. This makes me wonder if I could trigger another render from backgrounds, I could possibly receive the correct values without having to use this knobs hack. It doesn't matter in my case since I want knobs, but if I had a component without knobs this would break.

@stale
Copy link

stale bot commented Mar 24, 2018

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 30 days. Thanks!

@stale stale bot added the inactive label Mar 24, 2018
@stale
Copy link

stale bot commented Apr 23, 2018

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!

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

3 participants