storybook: TypeError: require.context is not a function

Hi guys,

Issue details

If you use require.context within a React component the storyshots will fail with TypeError: require.context is not a function.

Steps to reproduce

Just write require.context() in any of the component.

This is mine:

import React from 'react';
import PropTypes from 'prop-types';
import DefaultProps from '../../helpers/default-props';

const lineIcons = require.context('../../assets/icons/Line', true, /.+\.svg$/);
const solidIcons = require.context('../../assets/icons/Solid', true, /.+\.svg$/);
const requireAll = requireContext => requireContext.keys().map(requireContext);
const toObjectNames = (state, icon) => ({ ...state, [icon.default.id]: icon.default.id });
const icons = {
  Line: requireAll(lineIcons).reduce(toObjectNames, {}),
  Solid: requireAll(solidIcons).reduce(toObjectNames, {}),
};

const Icon = ({
  glyph, type = 'Line', width = 14, height = 14, className = 'icon', fill = 'currentColor', ...rest
}) => (
  <svg {...rest} className={className} width={width} fill={fill} height={height}>
    <use xlinkHref={`#${type} ${glyph}`} />
  </svg>
);

Icon.propTypes = {
  ...DefaultProps,
  /** icon name, just exactly how the file is named */
  glyph: PropTypes.string.isRequired,
  /** main folder where lays this file, could be `Line | Solid` */
  type: PropTypes.oneOf(['Line', 'Solid']),
  /** width, which is set to <svg> */
  width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  /** height, which is set to <svg> */
  height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
  /** fill (color), which is set to <svg> */
  fill: PropTypes.string,
};

export default Icon;

export {
  icons,
};

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

  • storybook/react ^3.2.16 (my is 3.2.16)
  • storybook/addon-storyshots ^3.2.16 (my is 3.2.16)

Affected platforms

Any OS any build.

Screenshots / Screencast / Code Snippets (Optional)

http://prntscr.com/hnhw8u

// content of storyshots.test.js

import initStoryshots from '@storybook/addon-storyshots';

global.window = global;
window.addEventListener = () => {};
window.requestAnimationFrame = () => {
  throw new Error('requestAnimationFrame is not supported in Node');
};

initStoryshots({ /* configuration options */ });

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Comments: 29 (12 by maintainers)

Most upvoted comments

I had the same issue. Using CRA v3 (not ejected) with ts and I could not figure a way out to get it to work with the babel plugin or anything. Followed various solutions on different git issues but nothing worked for me, so I hacked it with these 3 lines.

This seems to solve it. No .babelrc or jest.config or setupTest.js or anything. I just add the above to replace the original line in .storybook/config.js

BEFORE

// .storybook.config.js
const req = require.context('../src/components', true, /.stories.tsx$/)

AFTER

// .storybook.config.js
import registerRequireContextHook from 'babel-plugin-require-context-hook/register';
registerRequireContextHook();

const req = global.__requireContext(__dirname, '../src/components', true, /.stories.tsx$/)

require.context is a webpack-specific feature, so it doesn’t work in jest. You can try to mock it somehow

The tutorial at https://storybook.js.org/docs/testing/structural-testing/ helped me.

First run

yarn add --dev babel-plugin-macros

in terminal.

Then add this code in .babelrc

{
  "plugins": ["macros"]
}

In .storybook/config.js, update to

import { configure } from '@storybook/react';
import requireContext from 'require-context.macro'; // <- add this

import '../src/index.css';

const req = requireContext('../src/components', true, /\.stories\.js$/); // <- change to this

function loadStories() {
  req.keys().forEach(filename => req(filename));
}

configure(loadStories, module);

Based on this stackOverflow answer, i created a transformer that add the polyfill only in files that use require.context

https://gist.github.com/ezidio/f64c59d46b19a3fe671a9ded6441de18

It work’s for me

Jest v22.4.2

I stumbled upon require-context.macro a few days after my initial post up. Like @Hongbo-Miao said, that also works, but requires a .babelrc file inside .storybook

BTW you actually add those SVGs to bundle only when you call requireAll

For storyshots you don’t need it because they don’t perform actual browser rendering

The problem is that require.context is not actually a runtime function, it’s rather a hint for webpack that gets replaced by an actual context object.

Did you try the first answer? Maybe combining the separate file approach from it with the stub function from second one https://stackoverflow.com/questions/38332094/how-can-i-mock-webpacks-require-context-in-jest/42439030#42439030