mthuret / storybook-addon-specifications

:book: Write tests next to your stories and display their results inside storybook interface
457 stars 54 forks source link

How to use in Storybook 5.2 Component Story Format (CSF)? #121

Open JimmyLv opened 5 years ago

JimmyLv commented 5 years ago
export default {
  title: 'MyComponent',
  decorators: [storyFn => <div style={{ backgroundColor: 'yellow' }}>{storyFn()}</div>],
};

https://storybook.js.org/docs/formats/component-story-format/

zachmanring-natgeo commented 5 years ago
import { mount } from 'enzyme'
import expect from 'expect'

...

export const withSampleData = () => {
  const story = (
    <div
      style={{
        position: 'absolute',
        textAlign: 'center',
        top: '50%',
        transform: 'translateY(-50%)',
        width: '100%',
      }}
    >
      <FillButton
        disabled={boolean('disabled', false)}
        fullWidth={boolean('fullWidth', false)}
        icon={object('icon', iconExample)}
        inverse={boolean('inverse', false)}
        label={text('label', 'button')}
        link={object('link', linkExample)}
        loading={boolean('loading', false)}
        size={select('size', ['small', 'large', 'xlarge'], 'large')}
        style={select('style', ['primary', 'secondary', 'outlined', 'disabled'], 'primary')}
        type={select('type (behavior)', ['button', 'link', 'submit'], 'button')}
      />
    </div>
  )

  specs(() =>
    describe('with sample data', () => {
      it('Should have label of `button`', () => {
        const output = mount(story)

        expect(output.text()).toContain('button')
      })
    }),
  )

  return story
}

withSampleData.story = {
  name: 'with sample data',

  parameters: {
    notes: 'A very simple example of addon notes',
  },
}

Example on how I got it to work.

philipbeadle commented 5 years ago

I cant get mount to work. Shallow works fine but mount always says "inst is null"

I've tried a bunch of different react versions but cant figure whats wrong.

My steps

My code

import React from 'react';
import { action } from '@storybook/addon-actions';
import { Button } from '@storybook/react/demo';
import { specs, describe, it } from 'storybook-addon-specifications';
import { shallow, mount } from 'enzyme';
import expect from 'expect';
import { configure as enzymeConfigure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'

enzymeConfigure({ adapter: new Adapter() })

export default {
  title: 'Button'
};

export const text = () => {
  const story = (
    <Button onClick={action('Hello World')}>
      Hello World
    </Button>
  );

  specs(() => describe('Text', function () {
    it('Should have the Hello World label', function () {
      let wrap = shallow(story);
      // let wrap = mount(story);
      expect(wrap.text()).toContain('Hello World');
    });
  }));

  return story;
}

text.story = {
  name: 'Text'
}
philipbeadle commented 5 years ago

Weird works now.

JakeStanger commented 4 years ago

@philipbeadle do you know what caused it to work? I'm having the same problem where mount throws an error but shallow works.

philipbeadle commented 4 years ago

I set up a setupTests.js

import { configure as enzymeConfigure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
enzymeConfigure({ adapter: new Adapter() });

Moved my tests to a separate file

import React from 'react';
import { mount } from 'enzyme';
import { MessageList } from './index';
import { testMessages } from '../../testData/messageList';

export const noMessageListTests = describe('No messages', function () {
  let props = {
    messages: []
  }

  const component = (
    <MessageList {...props}/>
  );
  it('Renders witout crashing', function () {
    mount(component);
  });
  it('Does not show any messages', function () {
    let wrap = mount(component);
    expect(wrap.find('Message').length).toEqual(0)
  });
  it('Shows the no messages message', function () {
    let wrap = mount(component);
    expect(wrap.find('h2').text()).toContain('No Messages Yet');
  });
})

and import the tests

import React from 'react';
import { action } from '@storybook/addon-actions';
import { MessageList } from '../src/components/MessageList/index';
import { specs } from 'storybook-addon-specifications';
import { noMessageListTests } from '../src/components/MessageList/index.test'
import { messageListTests } from '../src/components/MessageList/index.test'
import { testMessages } from '../src/testData/messageList';
export default {
  title: 'Message List'
};

export const noMessages = () => {
  let props = {
    messages: []
  }
  const story = (
    <MessageList {...props} />
  );
  specs(() => noMessageListTests);
  return story;
}

noMessages.story = {
  name: 'No messages'
}

Also added a test.js to the .storybook folder

import { describe, it, beforeEach } from 'storybook-addon-specifications';
import expect from 'expect';
import jest from 'jest-mock';
import { shallow, mount } from 'enzyme';
import { configure as enzymeConfigure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
enzymeConfigure({ adapter: new Adapter() });

window.describe = describe;
window.beforeEach = beforeEach;
window.it = it;
window.expect = expect;
window.jest = jest;
window.shallow = shallow;
window.mount = mount;

and import that in the config.js

import { configure } from '@storybook/react';
import './test'
configure(require.context('../stories', true, /\.stories\.js$/), module);

Now it all works and I can run my tests in jest as well.

rphmee commented 4 years ago

@philipbeadle Just wanted to say thanks, been working through this setup for a few hours and nothing was working until I followed your post. And as an added bonus my story files don't get cluttered with the tests, nice and clean.

andrewcorliss commented 4 years ago

Hello, I am currently trying to get this to work on CSF and am having issues setting up inside with errors coming from other modules.

The project I am working on currently is using the method where we have no config.js but use the main.js file

Any tips or advice?

My main issue is I cannot get the expect function to work. It causes an error in my build

beccasaurus commented 4 years ago

@andrewcorliss Did you ever find a solution? I'm having the same issue with expect.

Edit: I made a brand new React app and added Storybook using these steps from @philipbeadle above and it's working for me now!

I also had problems with mount() (inst is null) until I followed the follow-up example.

neko-neko commented 4 years ago

I'm working on support CSF format and support for storybook 6. Described in #123.