Steverino
Steverino

Reputation: 2266

Material-UI custom theme palette property yielding 'undefined' error in Jest

In short, I'm using Jest, React Testing Library, and Material UI createMuiTheme and everything works except for the tests. They break only when I add the custom theme from my compound theme from createMuiTheme.

I'm creating a custom theme for my MUI project as follows:

import { createMuiTheme } from '@material-ui/core/styles';

export const theme = {
  palette: {
    extra: {
      activeButton: '#D4564E',
      black: '#000000',
      darkGrey: '#232323',
      rgbaInvisible: 'rgba(0, 0, 0, 0)',
      success: '#4CAF50',
      white: '#FFFFFF',
    },
  },
};

export default createMuiTheme(theme);

My component styles are defined in JSS like this:

const useStyles = makeStyles((theme) => {
  return {
    ctaCopy: {
      color: theme.extraColors.activeButton,
    },
  };
});

The component itself I don't think is important but it looks like this:

<Link className={classes.ctaCopy} href={ctaUrl}>
  {ctaCopy}
</Link>

This works. The component displays properly when rendered, with the expected colors. However, when I use this component in a Jest test, it fails, saying:

TypeError: Cannot read property 'activeButton' of undefined

Update:

I dug a little further and attempted a few other solutions, including using MuiThemeProvider and ThemeProvider (separately, of course). In order to do this, I used import to pull in my custom theme, which is hosted in an external library. As follows:

import { defaultTheme } from 'my-external-lib';

This, again, works on a rendered page. I went so far as to console.log the defaultTheme and it prints correctly, again, in the rendered page. However, in the tests, if I console.log(defaultTheme) the result is undefined!!

So perhaps the updated question nuance is, why can't I use import in this way with Jest/React Testing Library?

This may warrant a whole new question being posted.

More of what I've tried so far:

// This theme created as above
import { ThemeProvider } from '@material-ui/core';
import { defaultTheme } from '@my-external-lib';
import MyComponent from './MyComponent';

const setupComponent = ({
  ctaCopy,
  ctaUrl,
} = {}) => {
  render(
    <ThemeProvider theme={defaultTheme}>
      <MyComponent
        ctaCopy={ctaCopy}
        ctaUrl={ctaUrl}
      />
    </ThemeProvider>,
  );
};

const testCtaCopy = 'test-cta-copy';
const testCtaUrl = 'https://www.test.com';

describe('My component', () => {
  it('should render', () => {
    expect.assertions(1);

    setupComponent({ ctaCopy: testCtaCopy, ctaUrl: testCtaUrl });

    expect(screen.getByText(testCtaCopy)).toBeInTheDocument();
  });
});

Why am I getting this error in tests only?

Upvotes: 10

Views: 4250

Answers (2)

Dennis Gonzales
Dennis Gonzales

Reputation: 111

I encountered this today, the solution that fixed for me is this

const useStyles = makeStyles((theme) => {
  return {
    ctaCopy: {
      color: theme.extraColors?.activeButton,
    },
  };
});

Upvotes: 2

JattCode113
JattCode113

Reputation: 62

To be honest, I'm very new to JS, React, and Jest, but I was able to fix a similar problem where I got a similar error (related to the new MUI v5 update) so here's my best guess:

Perhaps you receive errors on test and not when running src, because:

  1. the scope of your test and src code is different. The src code understands how theme's are being passed around and utilized in all your different src code files. Or:
  2. Your test code is making assertions that the compiler doesn't care about.

TypeError: Cannot read property 'activeButton' of undefined, Sound's like your theme isn't being picked up and used by makestyles() properly. (although it looks like you followed the docs perfectly fine & displayed your theme, so my guess is this is an issue on the JEST side or a minor bug with MUI)

What I did to fix a similar error was move my theme into the same file as my JSS, and refer to my theme directly in makeStyles(), rather than pass theme as a param.

So something like:


const themeAttr = {
  palette: {
    extra: {
      activeButton: '#D4564E',
      black: '#000000',
      darkGrey: '#232323',
      rgbaInvisible: 'rgba(0, 0, 0, 0)',
      success: '#4CAF50',
      white: '#FFFFFF',
    },
  },
}; 

const theme = createMuiTheme(themeAttr);

const useStyles = makeStyles( => {
  return {
    ctaCopy: {
      color: theme.extraColors.activeButton,
    },
  };
});

I did not use createMUITheme in my project. I only used createTheme(). However this did fix the errors I was receiving during test, so I hope this helps!

Upvotes: 0

Related Questions