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

2

10

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?

Cowey answered 1/5, 2021 at 3:27 Comment(3)
Are you using maybe these libraries? "@testing-library/jest-dom", "@testing-library/react", "@testing-library/user-event". Is the render function from testing-library, or from react? I have similar test environment and it works for me.Air
Hi, would like to see if there's any update on this? I'm having the same issue.Accomplice
@Accomplice and others who may find this SO question in the future, this was for a project at work and I no longer work there, so can't confirm or deny any fixes work in this environment. :( Sorry. Also MUI has moved on from the version I was using, so that may also complicate matters (not sure the effect on themes over major versions).Cowey
M
2

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

const useStyles = makeStyles((theme) => {
  return {
    ctaCopy: {
      color: theme.extraColors?.activeButton,
    },
  };
});
Magnuson answered 11/2, 2022 at 11:22 Comment(0)
N
0

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!

Newcomer answered 10/12, 2021 at 19:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.