Search code examples
javascriptreactjssinonenzymestyled-components

Enzyme wont 'render, mount, or shallow' a component because a dependency is undefined


I am trying to figure out why my test wont run. I have a React functional component that contains a styled-component which uses a custom method to generate a media query which gets imported for a css helper file. I am getting a TypeError: Cannot read property 'medium' of undefined. Here is my code.

css/index.js

export const media = (function(){

  const sizes = {
    large: 996,
    medium: 767,
    small: 656,
  };

  return Object.keys(sizes).reduce((acc, label) => {
    acc[label] = (...args) => css`
      @media (min-width: ${sizes[label] / 16}em) {
        ${css(...args)}
      }
    `;
    return acc;
  }, {});

})();

mycomponent

import { media } from 'css';

const MyComponent = ({ icon, title, description }) => (
  <MyComponentContainer>
    ...
  </MyComponentContainer>
);

export default MyComponent;

const MyComponentContainer = styled.article`
  max-width: 300px;
  width: 100%;
  border: 1px solid #000;
  ${media.medium`
    padding: 0 25px;
  `}
  ${media.large`
    max-width: 350px;
  `}
`;

My Test File

import React from 'react';
import { shallow } from 'enzyme';

import MyComponent from 'components/MyComponent';

describe('<MyComponent />', () => {

  it('should match the snapshot', () => {

    const snap = shallow(<MyComponent />);
    expect(snap).toMatchSnapshot();

  });

});

I am new to react testing and don't really understand how to mock that functionality or tell jest to ignore it.

I am using react 16+ with the required enzyme adapter and the jest-styled-components test plugin.


Solution

  • In case anyone else runs across this, I found the answer, and it explains a lot about the nature of testing.

    When you are testing, you only want to the test the functionality of one component or action at a time (UNIT TESTING). By trying to test a component that was pulling in another dependency, I was actually trying to test two things at once without realizing it.

    The MyComponent component needs to be tested separate from the media tagged template methods.

    In MyComponent, I don't care what was returned from the media tagged template method. I only care what method was called and the parameters of the invocation.

    I can setup another separate test for the media methods to make sure those methods behave as expected and test those individually.

    So in jest you can mock the module import.

    inside My Test File

    import React from 'react';
    import { shallow } from 'enzyme';
    
    import MyComponent from 'components';
    
    jest.mock('css', () => ({
       media: {
          small: jest.fn(),
          medium: jest.fn(),
          large: jest.fn(),
       },
    })
    
    describe('<MyComponent />, () => {
        it('should match snapshot', () => {
            const snap = shallow(<MyComponent />);
            expect(snap).toMatchSnapshot();
        });
    });