Storybook: TypeError: require(...) is not a function in initStoryshots()

Created on 8 Apr 2020  ·  33Comments  ·  Source: storybookjs/storybook

Describe the bug

I'm using storybook/vue and trying to run jest tests and generate snapshots with Storyshots but I'm getting TypeError: require(...) is not a function when initStoryshots() is called.

TypeError: require(...) is not a function

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

      at Object.<anonymous> (node_modules/iconv-lite/lib/index.js:144:29)
      at Object.<anonymous> (node_modules/raw-body/index.js:17:13)
      at Object.<anonymous> (node_modules/body-parser/lib/read.js:15:15)
      at Object.<anonymous> (node_modules/body-parser/lib/types/json.js:19:12)
      at loadParser (node_modules/body-parser/index.js:142:16)
      at Function.get [as json] (node_modules/body-parser/index.js:123:12)
      at Object.<anonymous> (node_modules/express/lib/express.js:78:27)
      at Object.<anonymous> (node_modules/express/index.js:11:18)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/node_modules/@storybook/core/dist/server/build-dev.js:13:39)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/node_modules/@storybook/core/server.js:4:18)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/frameworks/configure.js:8:16)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/frameworks/angular/loader.js:20:35)
      at node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:18:41
          at Array.map (<anonymous>)
      at getLoaders (node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:18:10)
      at Object.loadFramework [as default] (node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:21:19)
      at testStorySnapshots (node_modules/@storybook/addon-storyshots/dist/api/index.js:48:39)
      at Object.<anonymous> (tests/jest/vue/Storyshots.test.js:3:1)

To Reproduce
Follow the instructions on using Storyshots with storybook/vue

Code snippets
This is the jest config that i'm using:

  "jest": {
    "browser": true,
    "globalSetup": "./tests/jest/global-setup.js",
    "testURL": "xxx",
    "testMatch": [
      "**/tests/jest/**/*.test.js"
    ],
    "moduleFileExtensions": [
      "ts",
      "vue",
      "js",
      "jsx",
      "json",
      "node"
    ],
    "moduleNameMapper": {
      "^vue$": "vue/dist/vue.common.js",
      "^vuex$": "vuex/dist/vuex.common.js",
      "^v-runtime-template$": "v-runtime-template/dist/v-runtime-template.js"
    },
    "testPathIgnorePatterns": [
      "/node_modules/",
      "/vendor/"
    ],
    "transform": {
    "^.+\\.tsx?$": "ts-jest",
    "^.+\\.js$": "./node_modules/babel-jest",
    "^.+\\.vue$": "./node_modules/vue-jest"
  },
  "transformIgnorePatterns": [
      "<rootDir>/node_modules/(?!(@storybook/.*\\.vue$))"
    ]
  },

System:

System:
OS: macOS 10.15.4
CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz
Binaries:
Node: 10.15.1 - /usr/local/bin/node
Yarn: 1.13.0 - /usr/local/bin/yarn
npm: 6.4.1 - /usr/local/bin/npm
Browsers:
Chrome: 80.0.3987.163
Firefox: 74.0
Safari: 13.1
npmPackages:
@storybook/addon-actions: ^5.3.14 => 5.3.14
@storybook/addon-docs: ^5.3.14 => 5.3.14
@storybook/addon-knobs: ^5.3.14 => 5.3.14
@storybook/addon-links: ^5.3.14 => 5.3.14
@storybook/addon-storyshots: ^5.3.18 => 5.3.18
@storybook/addon-storysource: ^5.3.14 => 5.3.14
@storybook/vue: ^5.3.14 => 5.3.14

P3 storyshots has workaround question / support

Most helpful comment

@shilman It sure is a great feature GitHub added to help reduce issue noise… which unfortunately is _completely_ undone when people use stale bot, which doesn't notice or care about them at all and forces users to focus on making comments to shoo it away, instead of just using the reactions… 😞

All 33 comments

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!

Same issue. Mine throws a TypeError:

TypeError: require.requireActual is not a function

I am seeing this issue too.

TypeError: initStoryshots is not a function

I was able to fix this on my install. It was happening because I had [email protected]. installed when storybook only supports up to 25.0.0 as pointed out in https://stackoverflow.com/questions/61706963/typeerror-require-requireactual-is-not-a-function.

While this is fixed in #10642 and part of a beta release for now I downgraded my jest — npm install [email protected] --save-dev — and everything is working fine.

Downgrading Jest did not fix this for me. Note that this problem seems to happen in 5.3.x when using babel-plugin-require-context-hook regardless of Jest version; downgrading to 5.2.x fixed it for me.

I've been fighting this all week and it's doing my head in. 😭 I've moved all my stories and components into a brand new Storybook + CRA repo.

Things I've tried/done -

  • Installing the next release of Storyshots as per @prtksxna comment
  • Explicitly installing Jest 25 as per @prtksxna comment
  • Added react-app-rewired; using this config:
module.exports = {

  jest: function (config) {
    config.browser = true;
    config.clearMocks = true;
    config.moduleFileExtensions.push('mdx');
    config.transform = {
      '\\.txt$': 'jest-raw-loader',
      '^.+\\.mdx$': '@storybook/addon-docs/jest-transform-mdx',
       ...config.transform
    }

    return config
  }
}
  • Downgrading to 5.2, which doesn't work given I have 5.3 everywhere else
  • Running with Jest by itself instead of via react-scripts or react-app-rewired

This is blocking me from upgrading to 5.3 and I'm really frustrated at this point, not sure what else to try and I can't even really troubleshoot the error because the stack trace is so vague:

  ● Test suite failed to run

    TypeError: require(...) is not a function

      14 | }));
      15 |
    > 16 | initStoryshots({
         | ^
      17 |   framework: 'react',
      18 |   test: snapshotWithOptions({
      19 |     createNodeMock: el => {

      at Object.<anonymous> (node_modules/iconv-lite/lib/index.js:144:29)
      at Object.<anonymous> (node_modules/raw-body/index.js:17:13)
      at Object.<anonymous> (node_modules/body-parser/lib/read.js:15:15)
      at Object.<anonymous> (node_modules/body-parser/lib/types/json.js:19:12)
      at loadParser (node_modules/body-parser/index.js:142:16)
      at Function.get [as json] (node_modules/body-parser/index.js:123:12)
      at Object.<anonymous> (node_modules/express/lib/express.js:78:27)
      at Object.<anonymous> (node_modules/express/index.js:11:18)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/node_modules/@storybook/core/dist/server/build-dev.js:15:39)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/node_modules/@storybook/core/server.js:4:18)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/frameworks/configure.js:9:16)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/frameworks/angular/loader.js:20:35)
      at node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:18:41
          at Array.map (<anonymous>)
      at getLoaders (node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:18:10)
      at Object.loadFramework [as default] (node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:21:19)
      at testStorySnapshots (node_modules/@storybook/addon-storyshots/dist/api/index.js:60:39)
      at Object.<anonymous> (src/Storyshots.test.js:16:1)

@aendrew i'm on the hook for releasing a 5.3.x that supports Jest 26. I've been slammed so I haven't gotten to it yet, but I'll see what I can do now.

Hmm. I just tried upgrading 5.3 to Jest 26 and everything seems to be broken. My advice is to upgrade to SB6. We're in Beta now and making good progress towards an RC...

Can't you just change require.requireActual to jest.requireActual?
(jest.requireActual is already present in jest@25)

@testerez If somebody wants to create a working PR to master with the required changes, I am willing to merge and release it. I tried cherry-picking the appropriate changes from next to master and that failed, so if you want to have a go please have at it.

FWIW, I upgraded to 6.0.0-beta.23 for all of my Storybook deps (including Storyshots) and I'm still getting this exact error.

It seems to try to configure all the loaders in order before selecting the relevant one, which is why it's failing on the Angular preset. When registerContextHook is called here everything fails.

I initially didn't have anything modifying my Babel config as per this line:

NOTE: if you are using Storybook 5.3's main.js to list story files, this is no longer needed.

I've since tried installing babel-plugin-require-context-hook manually and adding it to Babel config, to no avail.

I'm using create-react-app as my starting point and have installed everything from scratch over the course of trying to troubleshoot this. My config is as bog-standard as one can get, short of trying to add MDX support. I am at literally my wits' end by now.

@Hypnosphi any chance you can help out @aendrew with this? it sounds frustrating, but i don't know enough about this stuff to make a good suggestion

Was having same issue, fixed by downgrading jest@25.
Storybook is 6-beta.29

image

@bannndi I've tried that and npm ls jest lists 25.5.4. Running jest --test shows the version running is indeed 25.5.4. I've also changed from running via react-scripts/react-app-rewired to just running via jest and it results in the same issue.

Currently on 6.0.0-beta.20 but same issue on ^5.3.19 like the rest of my Storybook deps.

I've tried upgrading to @storybook/vue": "^6.0.0-beta.31" but another issue came up:

 /app/node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.ts:2
    import fs from 'fs';
    ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1258:14)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/api/index.js:41:41)

not sure if it's caused by the same problem. Tried both jest 25 and 26.

@AnnaYuS managed to fix that issue by adding the following configuration to jest.config.js:

module.exports = {
  ...
+ transformIgnorePatterns: ['node_modules/(?!(@storybook/addon-storyshots)/)'],
}

Looks like something might be off with the way that addon-storyshots is transpiled? See https://jestjs.io/docs/en/configuration#transformignorepatterns-arraystring

I was getting similar error

.storybook/preview.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest)
{import React from 'react';
 ^^^^^^

    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1258:14)
      at node_modules/@storybook/addon-storyshots/dist/frameworks/configure.js:63:14
          at Array.forEach (<anonymous>)
      at Object.configure [as default] (node_modules/@storybook/addon-storyshots/dist/frameworks/configure.js:62:11)
      at Object.load (node_modules/@storybook/addon-storyshots/dist/frameworks/react/loader.js:24:24)

I had to remove the whole preview.js file to make it work

[edit]
My bad jest.config didn't transform .js files after renaming everything is ok

Rolling back to Jest@25 solved the issue for me.

After rolling back to 25 I see this

 Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    /Users/afournier/Documents/satreg-widgets-react/.storybook/config.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { configure, addParameters, addDecorator } from "@storybook/react";

Ran into the same error with

"@storybook/addon-storyshots": "^5.3.19",
"@storybook/vue": "^6.0.0-rc.3",
"jest": "^26.0.1",

Fixed it by downgrading to "jest": "^25.5.4",

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!

Up

In my jest config, setting "browser": false, resolves the error. Probably not a solution for everybody.

Thanks @calumbutler for this workaround.
I don't arrive to set this property to my jest configuration because I'm in a create-react-app application. Do you have an idea to help me? Thanks.

It finally worked with "@storybook/vue": "^6.0.2", "@storybook/addon-storyshots": "^6.0.10", "jest": "^26.0.1" 🎉
The only problem I had to solve was with importing global less styles in preview.js, had to add a stub for less/css imports in jest config:

"^.+\\.(css|less)$": "<rootDir>/tests/jest/CSSStub.js"

_Hello again!_ I've been fighting this all afternoon. Let me take you on a _j o u r n e y . . ._

  1. The iconv require error happens when using the browser option in Jest. 24 and 25. I get the same error with the following config in package.json:
  "jest": {
    "browser": true,
    "verbose": true,
    "transform": {
      "^.+\\.[tj]sx?$": "babel-jest",
      "^.+\\.mdx?$": "@storybook/addon-docs/jest-transform-mdx"
    }
  },

...Even when not doing anything with Storyshots:

test('something', () => {
  const iconv = require('fs'); // This line throws with browser: true
  console.log(iconv);
  expect(true).toBe(true);
});

// import initStoryshots, { snapshotWithOptions } from '@storybook/addon-storyshots';
// initStoryshots();

In Jest 26, this _passes_, but throws a deprecation error:

● Deprecation Warning:

  Option "browser" has been deprecated. Please install "browser-resolve" and use the "resolver" option in Jest configuration as follows:
  {
    "resolver": "browser-resolve"
  }


  Configuration Documentation:
  https://jestjs.io/docs/configuration.html

However, if I change the require('iconv-lite') statement to requiring one of my dependencies that _needs_ to resolve the browser field, I get a Cannot find module error. This leads me to believe that the "warning" about browser should actually be an _error_ given that anything relying on it will fail.

Carrying on, let's stay with Jest 26 and use the resolver option with browser-resolve:

--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
   "license": "ISC",
   "jest": {
-    "browser": true,
+    "resolver": "browser-resolve",
     "verbose": true,
     "transform": {
@@ -79,27 +79,30 @@
+    "browser-resolve": "^2.0.0",

Well, that didn't work:

● Validation Error:

  Module /Users/andrew.rininsland/Projects/g-components/node_modules/jest-config/node_modules/babel-jest/build/index.js in the transform option was not found.
         <rootDir> is: /Users/andrew.rininsland/Projects/g-components

  Configuration Documentation:
  https://jestjs.io/docs/configuration.html

I'm led to believe this is because the Jest error about browser-resolve is wrong because resolver can't actually use browser-resolve; see this issue: https://github.com/facebook/jest/issues/10074 🤦🏼‍♀️

Lo' and behold, if I create a file called "resolver.js" and set jest.resolver to "./resolver.js", it passes! 🎉 Wicked! Let's try it with Storyshots instead of my stub test!

Er, still no. 😭

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

    TypeError: Cannot read property 'bind' of undefined

      18 | }));
      19 |
    > 20 | initStoryshots({
         | ^
      21 |   framework: 'react',
      22 |   test: snapshotWithOptions({
      23 |     createNodeMock: (el) => {

      at Object.<anonymous> (node_modules/node-fetch/browser.js:19:32)
      at Object.<anonymous> (node_modules/@storybook/core/dist/server/manager/manager-config.js:22:41)
      at Object.<anonymous> (node_modules/@storybook/core/dist/server/build-static.js:27:45)
      at Object.<anonymous> (node_modules/@storybook/core/server.js:3:21)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/frameworks/configure.js:20:16)
      at Object.<anonymous> (node_modules/@storybook/addon-storyshots/dist/frameworks/angular/loader.js:20:35)
      at node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:18:41
          at Array.map (<anonymous>)
      at getLoaders (node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:18:10)
      at Object.loadFramework [as default] (node_modules/@storybook/addon-storyshots/dist/frameworks/frameworkLoader.js:21:19)
      at testStorySnapshots (node_modules/@storybook/addon-storyshots/dist/api/index.js:60:39)
      at Object.<anonymous> (src/Storyshots.test.js:20:1)

Oh bloody hell, now node-fetch is using the browser version?! That's not what we want; that will break node.js because it assumes global.fetch exists. Here are the relevant bits of node-fetch/browser.js:

var getGlobal = function () {
    if (typeof self !== 'undefined') { return self; }
    if (typeof window !== 'undefined') { return window; }
    if (typeof global !== 'undefined') { return global; }
    throw new Error('unable to locate global object');
}

var global = getGlobal();
module.exports = exports = global.fetch;

// Needed for TypeScript and Webpack.
exports.default = global.fetch.bind(global);

To heck with browser-resolve! Let's try using enhanced-resolve-jest as per this issue: https://github.com/facebook/jest/issues/10036

Following what they've done in Marko's config, I've installed enhanced-resolve-jest and changed resolver.js to:

const { create, getDefaultConfig } = require("enhanced-resolve-jest");

module.exports = create(jestConfig => {
    const baseConfig = getDefaultConfig(jestConfig);
    baseConfig.aliasFields = ["browser"];
    baseConfig.mainFields = ["browser", "main"];

    return baseConfig;
  });

...and returned to the basic test instead of Storyshots. Woo! Passes! Let's resurrect Storyshots!


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

    TypeError: Cannot read property 'bind' of undefined

      18 | }));
      19 |
    > 20 | initStoryshots({
         | ^
      21 |   framework: 'react',
      22 |   test: snapshotWithOptions({
      23 |     createNodeMock: (el) => {

      at Object.<anonymous> (node_modules/node-fetch/browser.js:19:32)

Ah damn. Back to this. 😭

What if I alias node-fetch?

    baseConfig.alias = {
      ...(baseConfig.alias || {}),
      'node-fetch': path.resolve(__dirname, 'node_modules', 'node-fetch', 'lib', 'index.js')
    };

Ah-ha! This seems to work, I guess? However, now I'm getting lots of weird warnings like:

  ● Storyshots › Core/Bylines › Examples

    Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

    Check the render method of `storyFn`.

Opening that story in Storybook works _fine_.

I also get a boatload of console.warn output:

  console.warn
    Unexpected error: SyntaxError: Unexpected token '.'

      at Object.warn (node_modules/@storybook/client-logger/dist/index.js:53:73)
      at node_modules/@storybook/core/dist/client/preview/loadCsf.js:149:34
          at Array.forEach (<anonymous>)
      at node_modules/@storybook/core/dist/client/preview/loadCsf.js:142:20
          at Array.forEach (<anonymous>)
      at node_modules/@storybook/core/dist/client/preview/loadCsf.js:141:12
      at ConfigApi.configure (node_modules/@storybook/client-api/dist/config_api.js:26:7)

Also:

  console.warn
    Unexpected error: SyntaxError: Unexpected token ':'

      at Object.warn (node_modules/@storybook/client-logger/dist/index.js:53:73)
      at node_modules/@storybook/core/dist/client/preview/loadCsf.js:149:34
          at Array.forEach (<anonymous>)
      at node_modules/@storybook/core/dist/client/preview/loadCsf.js:142:20
          at Array.forEach (<anonymous>)
      at node_modules/@storybook/core/dist/client/preview/loadCsf.js:141:12
      at ConfigApi.configure (node_modules/@storybook/client-api/dist/config_api.js:26:7)

I am so, so, _so_ lost at this point. I'll try again at this point tomorrow, but I'm besides myself what's going on.

Following versions of everything:

    "@storybook/addon-a11y": "^6.0.16",
    "@storybook/addon-actions": "^6.0.16",
    "@storybook/addon-docs": "^6.0.16",
    "@storybook/addon-knobs": "^6.0.16",
    "@storybook/addon-links": "^6.0.16",
    "@storybook/addon-storyshots": "^6.0.16",
    "@storybook/addon-viewport": "^6.0.16",
    "@storybook/addons": "^6.0.16",
    "@storybook/preset-create-react-app": "^3.1.4",
    "@storybook/react": "^6.0.16",

Update: Okay, I solved it.

@storybook/core/dist/client/preview/loadCsf.js, ln. 149:

          try {
            var fileExports = req(filename);
            currentExports.set(fileExports, // todo discuss: types infer that this is RequireContext; no checks needed?
            // NOTE: turns out `babel-plugin-require-context-hook` doesn't implement this (yet)
            typeof req.resolve === 'function' ? req.resolve(filename) : filename);
          } catch (error) {
             console.error(error)
             //_clientLogger.logger.warn("Unexpected error: ".concat(error));
          }

Once I replaced _clientLogger.logger.warn with a standard console.error, I got a lovely expanded Jest stack trace, showing that it was getting confused by my .scss files. npm install identity-obj-proxy, add following to Jest config:

    "moduleNameMapper": {
      "\\.(css|less|scss|sass)$": "identity-obj-proxy"
    }

Everything works now. I feel very face-palm-y now.

tl;dr — please stop using _clientLogger.logger.warn in places where Jest config exceptions might get thrown. The custom logger ate all the useful information in that stack trace. I could have solved this WAY sooner had I gotten the actual Jest error.

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!

I think it's not stale :(

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!

this is not stale

If you want this fixed, please upvote by adding a 👍 to the issue description. We use this to help prioritize!

@shilman It sure is a great feature GitHub added to help reduce issue noise… which unfortunately is _completely_ undone when people use stale bot, which doesn't notice or care about them at all and forces users to focus on making comments to shoo it away, instead of just using the reactions… 😞

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dnlsandiego picture dnlsandiego  ·  3Comments

zvictor picture zvictor  ·  3Comments

tirli picture tirli  ·  3Comments

MrOrz picture MrOrz  ·  3Comments

rpersaud picture rpersaud  ·  3Comments