storybook-addon-specifications icon indicating copy to clipboard operation
storybook-addon-specifications copied to clipboard

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

Open JimmyLv opened this issue 4 years ago • 9 comments

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

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

JimmyLv avatar Oct 22 '19 10:10 JimmyLv

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.

zachmanring-natgeo avatar Oct 28 '19 18:10 zachmanring-natgeo

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

  • [ ] Install React npx create-react-app . & Storybook npx -p @storybook/cli sb init --type react in the ui-src folder
  • [ ] Check they both work yarn start & yarn storybook
  • [ ] Install Enzyme yarn add -D enzyme enzyme-adapter-react-16
  • [ ] Install the Storybook addon yarn add -D storybook-addon-specifications
  • [ ] Add this line to your addons.js import 'storybook-addon-specifications/register';

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 avatar Dec 03 '19 04:12 philipbeadle

Weird works now.

philipbeadle avatar Dec 04 '19 00:12 philipbeadle

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

JakeStanger avatar Dec 09 '19 11:12 JakeStanger

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.

philipbeadle avatar Dec 12 '19 01:12 philipbeadle

@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.

rphmee avatar Jan 13 '20 02:01 rphmee

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

andrewcorliss avatar Jun 01 '20 07:06 andrewcorliss

@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.

beccasaurus avatar Jun 13 '20 00:06 beccasaurus

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

neko-neko avatar Aug 23 '20 11:08 neko-neko