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

Storyshots fails with MDX stories via docs addon #7223

Closed
danielknell opened this issue Jun 28, 2019 · 28 comments
Closed

Storyshots fails with MDX stories via docs addon #7223

danielknell opened this issue Jun 28, 2019 · 28 comments

Comments

@danielknell
Copy link

Describe the bug
If you try and use storyshots while using the docs addon, jest will try and import the MDX file, which will result in syntax errors (it not understanding markdown code and all)

To Reproduce
Steps to reproduce the behavior:

  1. Enable docs technical preview
  2. Setup storyshots
  3. Create an based MDX story
  4. Run jest

Expected behavior
Jest should create snapshots based on stories in MDX file like it does for jsx/tsx files or ignore them.

System:

  • OS: ubuntu
  • Device: N/A
  • Browser: N/A
  • Framework: react
  • Addons: docs, storyshots
  • Version: 5.2.0-alpha.29

Additional context

Not really that important as it's in alpha and i'm just poking at what the future might look like, but will probably cause lots of confusion after a stable release, the docs addon is awesome btw, looking forward to the final version.

I am thinking a webpack loader will be needed to transform the MDX a regular JSX file defining the stories?

@shilman
Copy link
Member

shilman commented Jun 28, 2019

This is also blocking this PR #7222 so we'll need to deal with it sooner rather than later.

@shilman
Copy link
Member

shilman commented Jun 29, 2019

@danielknell For now, I just added the mdx file to a list of fileMock files, so it effectively skips the test. Not a very good workaround, but it unbreaks storyshots.

There's already a webpack loader that transforms the stories into JSX. Do you have any interest in trying to get that working for jest? I probably don't have time to look at this much more for awhile, but I'd be happy to answer questions if you want to tackle it. The webpack setup is here: https://github.com/storybookjs/storybook/blob/next/addons/docs/common/preset.js

@rwieruch
Copy link
Contributor

rwieruch commented Jul 3, 2019

Out of curiosity: Will Storyshots still work with MDX files? E.g. for

import { action } from '@storybook/addon-actions';
import { Button } from '@storybook/react/demo';
import { Story, Meta } from '@storybook/addon-docs/blocks';

<Meta title='MDX|Button' />

# Hello Docs

Welcome to the future of Storybook!

<Story name="hello">
  <Button onClick={action('clicked')}>Hello button!</Button>
</Story>

<Story name="with emoji">
  <Button onClick={action('clicked')}>🤘🚀💯</Button>
</Story>

so that both stories get picked up?

@shilman
Copy link
Member

shilman commented Jul 4, 2019

@rwieruch See my comment
#7223 (comment)

  • If we fileMock MDX files they will be ignored and the stories won't be picked up
  • If we write a jest transformation (equivalent to a webpack loader) or figure out how to adapt the webpack loader, these stories will be snapshotted. However, it requires investigation (help wanted!)

@danielknell
Copy link
Author

danielknell commented Jul 4, 2019

const createCompiler = require("@storybook/addon-docs/mdx-compiler-plugin");
const mdx = require("@mdx-js/mdx");
const babel = require("babel-jest");
const deasyncPromise = require("deasync-promise");

const compilers = [createCompiler({})];

module.exports = {
  process(src, filename, config, options) {
    let result = deasyncPromise(
      mdx(src, { compilers: compilers, filepath: filename }),
    );

    result = `/* @jsx mdx */
    import React from 'react'
    import { mdx } from '@mdx-js/react'
    ${result}
    `;

    return babel.process(result, filename, config, options);
  },
};

hacky as fuck but seems to work...?

using the following in jest config

{
  "transform": {
    "^.+\\.[tj]sx?$": "babel-jest",
    "^.+\\.mdx?$": "<rootDir>mdx.loader.js",
  }
}

@shilman
Copy link
Member

shilman commented Jul 4, 2019

Nice @danielknell. Would somebody mind putting that into a PR as @storybook/addon-docs/jest-transform.js or the like?! 🙀

@danielknell
Copy link
Author

@shilman it assumes you are using babel-jest, is that a safe assumption? thats also probably not the right way to chain jest transforms either but i couldn't see any other ways in the docs...

@shilman
Copy link
Member

shilman commented Jul 6, 2019

@danielknell I think we could require users to use babel-jest if that's what's needed to make it work? Obviously the fewer requirements the better tho.

@danielknell
Copy link
Author

i looked into it more and it seems that is how other people chain transforms, and there was some unneeded stuff in there, so i've updated the comment and wrapped it up in a pr

@aendra-rininsland
Copy link

aendra-rininsland commented Sep 18, 2019

Just a note re: the above code snippet if you're using it while waiting for #7330 to drop, you don't need to use deasync-promise, just use mdx.sync instead of mdx.

See: #7330 (comment)

@shilman
Copy link
Member

shilman commented Oct 24, 2019

Ta-da!! I just released https://github.com/storybookjs/storybook/releases/tag/v5.3.0-alpha.27 containing PR #8189 that references this issue. Upgrade today to try it out!

You can find this prerelease on the @next NPM tag.

Closing this issue. Please re-open if you think there's still more to do.

@shilman
Copy link
Member

shilman commented Oct 24, 2019

Finished except for instrumenting vue-kitchen-sink, which I'll follow up with in #8557

@hisapy
Copy link
Contributor

hisapy commented Mar 2, 2020

Hi, I have just installed Storybook 5.3.14, addon-docs and addon-storyshots and tried to run Storyshot.test.js, all of it as given in the instructions for this version, but it fails with

storyshots found 0 stories

I have only one story in src/Home

import { Meta, Story, Preview } from "@storybook/addon-docs/blocks";
import { Home } from "./Home";

<Meta title="Home" component={Home} />

# Home

The Home

<Preview>
  <Story name="Home">
    <Home />
  </Story>
</Preview>

Just for the record, .js format works

import React from "react";
import { Home } from "./Home";

export default {
  component: Home,
  title: "Home"
};

export const base = () => <Home />;

I debugged it a little bit and found that storybook.raw() length is 0 in https://github.com/storybookjs/storybook/blob/next/addons/storyshots/storyshots-core/src/api/index.ts line 51 at the time of this writing, so maybe the culprit is in the loadFramework function.

@Yama-Tomo
Copy link
Contributor

storyshots found 0 stories

I faced a similar problem in CRA.
I tried fix problem. Try the following steps.

  • check jest transform ordering
$ yarn test --showConfig
... snip ...
"transform": [
  [
    "^.+\\.mdx$",   <------ check ordering before `fileTransform`
    "/path/to/project/node_modules/@storybook/addon-docs/jest-transform-mdx.js"
  ],
  [
    "^.+\\.(js|jsx|ts|tsx)$",
    "/path/to/project/node_modules/react-app-rewired/scripts/utils/babelTransform.js"
  ],
  [
    "^.+\\.css$",
    "/path/to/project/node_modules/react-scripts/config/jest/cssTransform.js"
  ],
  [
    "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)",
    /path/to/project/node_modules/react-scripts/config/jest/fileTransform.js"
  ]
],
  • modify node_modules/@storybook/addon-docs/jest-transform-mdx.js
@@ -29,6 +29,6 @@
       import { mdx } from '@mdx-js/react'
       ${mdx.sync(src, { compilers, filepath: filename })}
     `;
-    return getNextTransformer(filename, config).transformSource(filename, result, instrument);
+    return getNextTransformer(filename, config).transformSource(filename + '.jsx', result, instrument);
   },
 };

☝️ I don't know if this is a bug. It might be better to create custom transformer.

  • modify node_modules/@storybook/components/dist/syntaxhighlighter/syntaxhighlighter.js
@@ -51,17 +51,17 @@
 var _memoizerific = _interopRequireDefault(require("memoizerific"));
-var _jsx = _interopRequireDefault(require("react-syntax-highlighter/dist/esm/languages/prism/jsx"));
+var _jsx = _interopRequireDefault(require("react-syntax-highlighter/dist/cjs/languages/prism/jsx"));
-var _bash = _interopRequireDefault(require("react-syntax-highlighter/dist/esm/languages/prism/bash"));
+var _bash = _interopRequireDefault(require("react-syntax-highlighter/dist/cjs/languages/prism/bash"));
-var _css = _interopRequireDefault(require("react-syntax-highlighter/dist/esm/languages/prism/css"));
+var _css = _interopRequireDefault(require("react-syntax-highlighter/dist/cjs/languages/prism/css"));
-var _markup = _interopRequireDefault(require("react-syntax-highlighter/dist/esm/languages/prism/markup"));
+var _markup = _interopRequireDefault(require("react-syntax-highlighter/dist/cjs/languages/prism/markup"));
-var _tsx = _interopRequireDefault(require("react-syntax-highlighter/dist/esm/languages/prism/tsx"));
+var _tsx = _interopRequireDefault(require("react-syntax-highlighter/dist/cjs/languages/prism/tsx"));
-var _typescript = _interopRequireDefault(require("react-syntax-highlighter/dist/esm/languages/prism/typescript"));
+var _typescript = _interopRequireDefault(require("react-syntax-highlighter/dist/cjs/languages/prism/typescript"));
 var _reactSyntaxHighlighter = require("react-syntax-highlighter");

fixed in v6.0.0-alpha.7 (#9780)

@CjChoiNZ
Copy link

@Yama-Tomo Do you mean the mdx ordering should be moved to top from transform?

@Yama-Tomo
Copy link
Contributor

@CjChoiNZ Yes. (no problem anywhere before fileTransform.js

@lauthieb
Copy link
Contributor

Same error. "storyshots found 0 stories" :-(

@CjChoiNZ
Copy link

@Yama-Tomo
hmm...I modified the node_modules/@storybook/addon-docs/jest-transform-mdx.js as your suggest.

...
return getNextTransformer(filename, config).transformSource(filename + '.jsx', result, instrument);

And confirmed use this path dist/cjs but it doesn't work for me.

I defined the jest from my package.json as below.

 "jest": {
    "transform": {
      "^.+\\.[tj]sx?$": "babel-jest",
      "^.+\\.mdx$": "@storybook/addon-docs/jest-transform-mdx"
    },
    "transformIgnorePatterns": [
      "/node_modules/"
    ]
  },

And the result of transform still displays mdx is bottom.

...
 "transform": [
        [
          "^.+\\.(js|jsx|ts|tsx)$",
          "C:\\Users\\CjChoi\\Workspace\\product-core\\node_modules\\react-scripts\\config\\jest\\babelTransform.js"
        ],
        [
          "^.+\\.css$",
          "C:\\Users\\CjChoi\\Workspace\\product-core\\node_modules\\react-scripts\\config\\jest\\cssTransform.js"
        ],
        [
          "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)",
          "C:\\Users\\CjChoi\\Workspace\\product-core\\node_modules\\react-scripts\\config\\jest\\fileTransform.js"
        ],
        [
          "^.+\\.[tj]sx?$",
          "C:\\Users\\CjChoi\\Workspace\\product-core\\node_modules\\babel-jest\\build\\index.js"
        ],
        [
          "^.+\\.mdx$",
          "C:\\Users\\CjChoi\\Workspace\\product-core\\node_modules\\@storybook\\addon-docs\\jest-transform-mdx.js"
        ]
      ],
...

Did I miss something?

@Yama-Tomo
Copy link
Contributor

@CjChoiNZ You need to customize the order of transform with the react-app-rewired

  • config-overrides.js
module.exports = {
  ...
  jest: function (config) {
    ...
    config.transform = {
      '^.+\\.mdx$': '/path/to/transformer(e.g. @storybook/addon-docs/jest-transform-mdx)',
       ...config.transform
    }

    return config
  }
}

@CjChoiNZ
Copy link

@Yama-Tomo
Cool, I removed the jest configuration from package.json and created a config-overrides.js and then it does work for me. Cheers bro!!

@jorisw
Copy link
Contributor

jorisw commented Apr 8, 2020

I've tried the config-overrides.js and react-rewire solutions proposed above, and I've tried upgrading to v6.0.0-alpha.31. I'm still getting:

 FAIL  src/tests/storyshots.test.js
  ● Test suite failed to run

    storyshots found 0 stories

      1 | import initStoryshots from "@storybook/addon-storyshots";
      2 | import { imageSnapshot } from "@storybook/addon-storyshots-puppeteer";
      3 | 
    > 4 | initStoryshots({ suite: "Image storyshots", test: imageSnapshot() });
        | ^
      5 | 

      at testStorySnapshots (node_modules/@storybook/addon-storyshots/dist/api/index.js:96:15)
      at Object.<anonymous> (src/components/tests/storyshots.test.js:4:1)

I've got a button.stories.mdx sitting in the same folder as button.js:

import { Meta, Story, Preview } from "@storybook/addon-docs/blocks";
import { action } from "@storybook/addon-actions";
import { Button } from "./button";

<Meta title="Components/Button" component={Button} />

# Button

This is a demo of a button documentation page.

- This is a text button:

  <Button onClick={action("clicked")}>Hello Button</Button>

- This is a button with emojis:
  <Button onClick={action("clicked")}>
    <span role="img" aria-label="so cool">
      😀 😎 👍
    </span>
  </Button>

My package.json:

{
  "name": "storybook",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "react-scripts test",
    "storybook": "start-storybook -p 6006",
    "build-storybook": "build-storybook"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "styled-components": "^5.1.0"
  },
  "devDependencies": {
    "@storybook/addon-actions": "^6.0.0-alpha.31",
    "@storybook/addon-docs": "^6.0.0-alpha.31",
    "@storybook/addon-links": "^6.0.0-alpha.31",
    "@storybook/addon-storyshots": "^6.0.0-alpha.31",
    "@storybook/addon-storyshots-puppeteer": "^6.0.0-alpha.31",
    "@storybook/addons": "^6.0.0-alpha.31",
    "@storybook/preset-create-react-app": "^2.1.1",
    "@storybook/react": "^6.0.0-alpha.31",
    "jest-image-snapshot": "^3.0.1",
    "puppeteer": "^2.1.1",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "^3.4.1",
    "react-test-renderer": "^16.13.1"
  }
}

My .storybook/main.js:

module.exports = {
  stories: ["../src/**/*.stories.(js|mdx)"],
  addons: [
    "@storybook/preset-create-react-app",
    "@storybook/addon-actions",
    "@storybook/addon-links",
    {
      name: "@storybook/addon-docs",
      options: {
        configureJSX: true
      }
    }
  ]
};

My jest.config.js:

modules.exports = {
  transform: {
    "^.+\\.[tj]sx?$": "babel-jest",
    "^.+\\.mdx?$": "@storybook/addon-docs/jest-transform-mdx"
  }
};

Non-MDX stories are picked up and test just fine.

@ajkl2533
Copy link
Contributor

For me also no MDX stories are not picked up but I'm using ts-jest instead of babel-jest not sure if that can be the issue

@sashapawcloud
Copy link

Faced the same issue recently. Solved by the following trick it package.json:

"scripts": {
  "test": "cross-env NODE_PATH=src react-scripts test --transform='{\"^.+\\\\\\.[tj]sx?$\":\"ts-jest\",\"^.+\\\\\\.mdx?$\":\"@storybook/addon-docs/jest-transform-mdx\"}'",
},

@jorgegir
Copy link

Just faced this same issue with Storybook v6:

 FAIL  src/Storyshots.test.js
  ● Test suite failed to run

    storyshots found 0 stories

      1 | import initStoryshots from '@storybook/addon-storyshots'
      2 | 
    > 3 | initStoryshots()
        | ^
      4 | 

      at testStorySnapshots (node_modules/@storybook/addon-storyshots/dist/api/index.js:104:15)
      at Object.<anonymous> (src/Storyshots.test.js:3:1)

@latviancoder
Copy link

We've encountered the same issue, but it had nothing to do with storybook. In our case the files weren't getting recognised by jest.

Adding this line to jest storyshots config fixed the problem:

moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'mdx'],

https://jestjs.io/docs/en/configuration#modulefileextensions-arraystring

@MR-Neto
Copy link

MR-Neto commented Jan 18, 2021

As pointed by @Yama-Tomo the order of the transform is important. I am using craco and I had to create an overridePlugin to the jest config.

module.exports = {
  overrideJestConfig: ({ jestConfig }) => {
    jestConfig.transform = {
      ".+\.mdx": `${resolveApp()}/node_modules/@storybook/addon-docs/jest-transform-mdx`,
      ...jestConfig.transform,
    }
    return jestConfig;
  }
};

@bhoomij
Copy link

bhoomij commented Mar 4, 2021

@shilman is this fixed now ?
I still get issue with storybook 6.1.X

jest.config.js

module.exports = {
  transform: {
    '^.+\\.jsx?$': 'babel-jest',
    '^.+\\.mdx?$': '@storybook/addon-docs/jest-transform-mdx',
  },
  moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node', 'mdx'],
}

@AlexandraNicolau10x
Copy link

AlexandraNicolau10x commented Mar 23, 2021

A solution for me was just to simply remove the mock below from our JestSetup file, and just move it in the test which was failing because of storybook.

jest.mock('@storybook/react-native', () => ({
getStorybookUI: jest.fn(),
addDecorator: jest.fn(),
configure: jest.fn(),
}));

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