尝试使用主题测试样式化组件时出错

Posted

技术标签:

【中文标题】尝试使用主题测试样式化组件时出错【英文标题】:Error trying to test Styled Components with Theme 【发布时间】:2021-11-16 15:06:31 【问题描述】:

对于使用主题的样式化组件,我无法通过单元测试。我做错了什么?

失败 src/components/Button/spec.js ● 控制台

控制台错误 错误:未捕获 [TypeError:无法读取未定义的属性“primary1”]

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】:

Header 应该将 props 传递给需要它们的特定组件,例如 Container

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

虽然根据错误

失败 src/components/Button/spec.js ● 控制台

控制台错误 错误:未捕获 [TypeError:无法读取未定义的属性“primary1”]

似乎问题出在您的Button 组件中。可能是类似的问题。

【讨论】:

以上是关于尝试使用主题测试样式化组件时出错的主要内容,如果未能解决你的问题,请参考以下文章

无法让 Jest 使用包含主题的样式化组件

在 gatsby 构建期间无法读取样式化组件的主题属性

样式化组件中的动态主题

带有主题的酶渲染样式组件

测试期间未为子样式组件提供正确的主题

无法使用 @emotion/styled 访问样式化组件中的主题