After setting up tests with Jest and getting through the auto-mocking issues described in #264, I'm getting:
TypeError: Cannot read property 'apply' of undefined
at StyledComponent.componentWillMount (decorators/withStyles.js:19:50)
The specific line in the withStyles decorator causing the error is:
this.removeCss = this.context.insertCss.apply(undefined, styles);
insertCss is undefined. How can the context be passed into the decorator for testing?
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
For now, I patched it with
import emptyFunction from '../../node_modules/fbjs/lib/emptyFunction';
...
const insertCss = this.context.insertCss || emptyFunction;
this.removeCss = insertCss.apply(undefined, styles);
I'm also having this issue. I'm trying to use React Storybook with this starter kit
+1
@flysonic10 : Can you please elaborate your answer?
Beside exporting the component with withStyles decorator, we need to export it as a stand alone.This will solve the issue
export class GridView extends Component { ... }
export default withStyles(s)(GridView);
And in test component use standalone one
import GridView from './GridView';
and in other cases use default one
import { GridView } from './GridView';
I think this can be closed.
This worked for me:
describe('Matrix', () => {
it('renders numbers', () => {
const wrapper = render(
<App context={{ insertCss: () => {} }}>
<Matrix values={[[1,2,3,4],[5,6,7,8],[9,10,11,12]]}>
</Matrix>
</App>
);
console.log(wrapper.html())
expect(wrapper.find('div.child').length).to.eq(1);
});
});
@bhargavigundaa your solution seems to be the best one to send the raw component to the Storybook, but I can't make the css work without the insertCss.
Any special configuration I'm missing it?
@bhargavigundaa's approach works for me fine on classes, but I on functional components where I export const GridView = ({ foo, bar }) =>
I still run into the same apply of undefined.
does anyone have a working Storybook example with this boilerplate?
I resolved this in the following way:
I modified package.json in accordance with the jest docs by adding this:
"jest": {
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
"\\.(css|less)$": "identity-obj-proxy",
"isomorphic-style-loader/lib/withStyles": "<rootDir>/tools/mocks/withStyles.js"
}
}
Notice that I've appended a moduleNameMapper for isomorphic-style-loader/lib/withStyles.
I then created the specified file: I created a mocks folder in the same folder as the webpack config (tools). I created a file in that folder called withStyles.js. It has the following content:
module.exports = () => component => component
+1
I get the above error when loading my app not even in test environments
If you want to add storybook to the project:
inside .storybook/ create a new file called ContextProvider.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class ContextProvider extends Component {
static propTypes = {
children: PropTypes.node.isRequired,
context: PropTypes.object.isRequired,
};
static contextTypes = {
insertCss: PropTypes.func,
};
static childContextTypes = {
insertCss: PropTypes.func.isRequired,
};
getChildContext() {
return this.props.context;
}
render() {
return this.props.children;
}
}
update .storybook/webpack.config.js
require('babel-register');
const config = require('../tools/webpack.config.js').default[0];
module.exports = {
plugins: config.plugins.filter(
(plugin) => ['DefinePlugin', 'ProvidePlugin', 'ExtractTextPlugin'].includes(plugin.constructor.name)
),
devtool: 'source-map',
resolve: config.resolve,
module: {
loaders: config.module.loaders,
rules: config.module.rules
}
}
and finally, inside .storybook/config.js
import React from 'react';
import PropTypes from 'prop-types';
import { configure, addDecorator } from '@storybook/react';
import ContextProvider from './ContextProvider';
function loadStories() {
require('../stories');
}
const context = {
insertCss: (...styles) => {
// eslint-disable-next-line no-underscore-dangle
const removeCss = styles.map(x => x._insertCss());
return () => {
removeCss.forEach(f => f());
};
},
};
addDecorator(story =>
<ContextProvider context={context}>
<div>
{story()}
</div>
</ContextProvider>,
);
configure(loadStories, module);
@timhuff very elegant, thank you 馃 +1
Storybook support can be discussed here: https://github.com/kriasoft/react-starter-kit/issues/1538
@timhuff Your approach yields TypeError: withStyles_1.default is not a function for me.
My component is a trivial .tsx file:
import withStyles from 'isomorphic-style-loader/lib/withStyles'
import * as React from 'react'
import * as s from './Logo.css'
export const Logo = () => (
<a href="/">
<svg
className={s.svg}
width="74px"
height="24px"
viewBox="0 0 74 24"
version="1.1"
xmlns="http://www.w3.org/2000/svg"
>
<desc>Created with Sketch.</desc>
...
</svg>
</a>
)
export default withStyles(s)(Logo)
I've tried clearing the jest cache also with the same result.
Update I changed withStyles.js to
export default () => component => component
which fixed it.
Most helpful comment
I resolved this in the following way:
I modified
package.jsonin accordance with the jest docs by adding this:Notice that I've appended a moduleNameMapper for
isomorphic-style-loader/lib/withStyles.I then created the specified file: I created a
mocksfolder in the same folder as the webpack config (tools). I created a file in that folder calledwithStyles.js. It has the following content: