question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using enzyme/shallow/mount and a theme with custom variables in a sub component

See original GitHub issue
  • This is a v1.x issue (v0.x is no longer maintained).
  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

Component that leverages theme + withStyles with custom variable doesn’t fail. I have a component that I wrap with withStyles. I only wrap the top level index with withRoot (where the theme is added to context). How to easily use shallow, mount, etc. to test a sub-component? I.e. how do I get the theme into the context? I feel like this should be an easy fix, but I can’t find a good example for this. See the test results in the codesandbox link.

Current Behavior

Test fails

Steps to Reproduce (for bugs)

See test results in https://codesandbox.io/s/wwkjkxzxj8

  1. in withRoot I added a custom theme variable success.main:
const theme = createMuiTheme({
  palette: {
    primary: {
      light: purple[300],
      main: purple[500],
      dark: purple[700]
    },
    secondary: {
      light: green[300],
      main: green[500],
      dark: green[700]
    }
  },
  success: {
    main: "pink"
  }
});
  1. Created sub-component Component which uses the theme variable:
import React from "react";
import { withStyles } from "@material-ui/core/styles";

const styles = theme => ({
  customClass: {
    color: theme.success.main
  }
});

class Component extends React.Component {
  render() {
    const { classes } = this.props;
    return <div className={classes.customClass}>Dude</div>;
  }
}

export default withStyles(styles)(Component);
  1. Although app runs fine in browser due to withRoot at the top level, if you run the tests, they barf because theme.success is undefined
Cannot read property 'main' of undefined

TypeError: Cannot read property 'main' of undefined
    at styles (https://ymv6ow7021.codesandbox.io/src/components/Component.js:26:28)
    at Object.create (https://ymv6ow7021.codesandbox.io/node_modules/@material-ui/core/styles/getStylesCreator.js:26:35)
    at WithStyles.attach (https://ymv6ow7021.codesandbox.io/node_modules/@material-ui/core/styles/withStyles.js:269:45)
    at new WithStyles (https://ymv6ow7021.codesandbox.io/node_modules/@material-ui/core/styles/withStyles.js:143:15)
    at ReactShallowRenderer.render (https://ymv6ow7021.codesandbox.io/node_modules/react-test-renderer/cjs/react-test-renderer-shallow.development.js:131:26)
    at eval (https://ymv6ow7021.codesandbox.io/node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:287:35)
    at withSetStateAllowed (https://ymv6ow7021.codesandbox.io/node_modules/enzyme-adapter-utils/build/Utils.js:94:16)
    at Object.render (https://ymv6ow7021.codesandbox.io/node_modules/enzyme-adapter-react-16/build/ReactSixteenAdapter.js:286:68)
    at new ShallowWrapper (https://ymv6ow7021.codesandbox.io/node_modules/enzyme/build/ShallowWrapper.js:119:22)
    at shallow (https://ymv6ow7021.codesandbox.io/node_modules/enzyme/build/shallow.js:19:10)
    at shallowWithContext (https://ymv6ow7021.codesandbox.io/node_modules/@material-ui/core/test-utils/createShallow.js:35:19)
    at Object.eval (https://ymv6ow7021.codesandbox.io/src/components/Component.test.js:29:19)
  1. How to inject custom theme easily? Thanks!

Context

Easily test sub components without wrapping in too many HOC.

Your Environment

I used codesandbox provided link with latest create-react-app, enzyme, etc.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:23
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

24reactions
oliviertassinaricommented, Jul 2, 2018

I think that it would be a good opportunity to add such in the documentation:

Component.js

import React from "react";
import { withStyles } from "@material-ui/core/styles";

const styles = theme => ({
  root: {
    color: theme.success.main
  }
});

class Component extends React.Component {
  render() {
    const { classes } = this.props;

    return <div className={classes.root}>Dude</div>;
  }
}

export default withStyles(styles)(Component);

Component.test.js

import React from "react";
import { shallow, mount } from "enzyme";
import { unwrap } from "@material-ui/core/test-utils";
import MuiThemeProvider from "@material-ui/core/styles/MuiThemeProvider";
import Component from "./Component";

const ComponentNaked = unwrap(Component);

describe("<Component />", () => {
  it("with shallow", () => {
    const wrapper = shallow(<ComponentNaked classes={{}} />);
    console.log("shallow", wrapper.debug());
  });

  it("with mount", () => {
    const wrapper = mount(
      <MuiThemeProvider
        theme={{
          success: {
            main: "#fff"
          }
        }}
      >
        <Component />
      </MuiThemeProvider>
    );
    console.log("mount", wrapper.debug());
  });
});

6reactions
mynameistechnocommented, Aug 15, 2018

Have you tried using dive()? http://airbnb.io/enzyme/docs/api/ShallowWrapper/dive.html

MUI also has some test utils to help: https://material-ui.com/guides/testing/#api

They wrap enzyme’s shallow with some helpful options like untilSelector: “Recursively shallow renders the children until it can find the provided selector. It’s useful to drill down higher-order components.”. There’s examples in the actual codebase. But I think you would use it like so:

E.g.

import * as React from 'react';
import {createShallow} from '@material-ui/core/test-utils';
import Foo from './Foo';

describe('<Foo />', () => {
  let shallow;

  beforeEach(() => {
    shallow = createShallow({untilSelector: 'Foo'});
  });

  it('should render', () => {
    const wrapper = shallow(<Foo />);
    console.log(wrapper.debug());
  });
});

Read more comments on GitHub >

github_iconTop Results From Across the Web

Using enzyme/shallow/mount and a theme with custom ...
Created sub-component Component which uses the theme variable: import React from "react"; import { withStyles } ...
Read more >
Add custom theme variable in createTheme() - Stack Overflow
myOwnComponent}> Here is my own component using a custom portion of the theme ... You can add custom variables in your MUI theme...
Read more >
Theming and Theme Switching with React and styled ...
We create a Container component using the CSS styles and styled component. We declare the state variables and look out for the changes....
Read more >
Theming - Material UI - MUI
Customize MUI with your theme. You can change the colors, the typography and much more. The theme specifies the color of the components,...
Read more >
Material UI Tutorial #6 - Custom Themes - YouTube
Hey gang, in this material UI tutorial we'll take a look at how to create custom themes (colours, spacing, typography, etc) for your ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found