Error trying to test Styled Components with Theme

Viewed 1155

I am having trouble getting the unit tests to pass for Styled Components that use a theme. What am I doing wrong?

FAIL src/components/Button/spec.js ● Console

console.error Error: Uncaught [TypeError: Cannot read property 'primary1' of undefined]

Header.js


import React from "react";
import { Container, Wrap, Logo, Image } from "./HeaderStyles";
import logo from "../../assets/graphics/logo.png";
const Header = () => {
  return (
    <Container data-test="headerComponent">
      <Wrap>
        <Logo>
          <Image data-test="logoImg" src={logo} />
        </Logo>
      </Wrap>
    </Container>
  );
};

export default Header;

HeaderStyles.js

import styled from "styled-components";

export const Container = styled.header`
  display: block;
  width: 100%;
  max-height: 85px;
  margin: 0 auto;
  padding: 0 10px;
  background: ${(props) => props.theme.colors.primary1}; ;
`;

export const Wrap = styled.div`
  display: relative;
  width: 100%;
  height: 100%;
  margin: 0 auto;
  max-width: 980px;
`;
export const Logo = styled.div`
  display: block;
  max-width: 120px;
  left: 10px;
  top: 50%;
  -webkit-transform: translateY(-50%);
  --moz-transform: translateY(-50%);
  transform: translateY(-50%);
`;
export const Image = styled.img`
  max-width: 70%;
  margin-top: 9rem;
`;

export const Title = styled.h1`
  color: ${(props) => props.theme.colors.primary1};
`;

default.js

const theme = {
  // Temp fonts
  fonts: {
    title: "Space Grotesk, sans-serif",
    main: "Space Grotesk, sans-serif",
  },
  // Colors for layout
  colors: {
    primary1: "#606060FF",
    background1: "#D6ED17FF",
    accent1: "hsl(34.9,98.6%,72.9%)",
    button: "hsl(205.1,100%,36.1%)",
    background2: "hsl(232.7,27.3%,23.7%)",
  },
  // Breakpoints for responsive design
  breakpoints: {
    sm: "screen and (max-width: 640px)",
    md: "screen and (max-width: 768px)",
    lg: "screen and (max-width: 1024px)",
    xl: "screen and (max-width: 1280px)",
  },
};

export default theme;


spec.js


import "jest-styled-components";
import React from "react";
import Adapter from "enzyme-adapter-react-16";
import { shallow, configure } from "enzyme";
import Header from "./Header";
import toJson from "enzyme-to-json";
import theme from "../../themes/default";
import { findByTestAtrr, renderWithTheme } from "../../../utils/utils";
import { Container, Image, Logo, Wrap } from "./HeaderStyles";
configure({ adapter: new Adapter() });

const setUp = (props = {}) => {
  const component = shallow(<Header theme={theme} {...props}></Header>);

  return component;
};

describe("Header Component", () => {
  let component;

  beforeEach(() => {
    component = setUp();
  });

  describe("Container Block", () => {
    it("renders correctly with theme", () => {
      const tree = renderWithTheme(<Container></Container>).toJSON();
      expect(tree).toMatchSnapshot();
    });
  });
});

spec.js.snap


exports[`Header Component Container Block renders correctly with theme 1`] = `
.c0 {
  display: block;
  width: 100%;
  max-height: 85px;
  margin: 0 auto;
  padding: 0 10px;
  background: #606060FF;
}

<header
  className="c0"
/>
`;

utils.js


import React from "react";
import theme from "../src/themes/default";
import TestRenderer from "react-test-renderer";
import { ThemeProvider } from "styled-components";

export const findByTestAtrr = (component, attr) => {
  const wrapper = component.find(`[data-test='${attr}']`);
  return wrapper;
};

export const checkProps = (component, expectedProps) => {
  const propsErr = checkPropTypes(
    component.propTypes,
    expectedProps,
    "props",
    component.name
  );

  return propsErr;
};

export const renderWithTheme = (component) => {
  return TestRenderer.create(
    <ThemeProvider theme={theme}>{component}</ThemeProvider>
  );
};


theme.js


import React from "react";
import { ThemeProvider } from "styled-components";
import PropTypes from "prop-types";
import theme from "../themes/default";
import GlobalStyles from "./globals";

const Theme = ({ children }) => (
  <ThemeProvider theme={theme}>
    <GlobalStyles />
    {children}
  </ThemeProvider>
);

Theme.propTypes = {
  children: PropTypes.element.isRequired,
};

export default Theme;



index.js


import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { store } from "./redux/store";
import { Provider } from "react-redux";
import Theme from "./styles/theme";

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <Theme>
        <App />
      </Theme>
    </Provider>
  </React.StrictMode>,
  document.getElementById("root")
);




1 Answers

Header should pass props on through to specific components that need them, like the Container.

const Header = ({ theme, ...props }) => {
  return (
    <Container theme={theme} data-test="headerComponent">
      <Wrap>
        <Logo>
          <Image data-test="logoImg" src={logo} />
        </Logo>
      </Wrap>
    </Container>
  );
};

According to the error though

FAIL src/components/Button/spec.js ● Console

console.error Error: Uncaught [TypeError: Cannot read property 'primary1' of undefined]

it seems like the issue is in your Button component. Probably a similar issue.

Related