web-dev-qa-db-ja.com

確認方法React JestおよびEnzymeの小道具?

だから私はReactでテストについて学びたいと思っていました、そして私はこれを持っています:Button.jsおよびButton.test.js

質問には、以下のコードとともにコメントが付けられています。

// Button.js
import React from 'react';
import { string, bool, func } from 'prop-types';
import { StyledButton } from './styled'

const Button = ({
  size,
  text,
}) => (
  <StyledButton
    size={size}
    // the test will alway fail with result:
    // Expected value to be: "Join us"
    // Received: undefined
    // Unless I add add this line below
    text={text}
  >
    {text} // but the text props is here. That is my current practice of passing the props to the children, am I missing anything?
  </StyledButton>
);

Button.propTypes = {
  size: string,
  text: string,
};

Button.defaultProps = {
  size: '',
  text: '',
};

export default Button;

// Button.test.js
import React from 'react';
import { shallow } from 'enzyme';

import Button from '../../components/Button/Button';

describe('Component: Button', () => {
  const minProps = {
    text: '',
    size: '',
  };  

  it('renders a button in size of "small" with text in it', () => {
    const wrapper = shallow(
      <Button {...minProps} size="small" text="Join us" />
    );

    expect(wrapper.prop('size')).toBe('small');
    expect(wrapper.prop('text')).toBe('Join us');
  });
});


// StyledButton
import Button from 'antd/lib/button';

const StyledButton = styled(Button)`
  &.ant-btn {
    padding: 0 24px;

    ${({ size }) => {
      if (size === 'small') {
        return css`
          font-size: 14px;
          line-height: 32px;
        `;
      }
      return null;
    }};
`;

export { StyledButton };

小道具をStyledButtonに渡さないとテストが失敗する理由を誰かが知っていますか?

11
vizFlux

この投稿は少し古いですが、予想されるプロップタイプとその値をテストするためのより良い方法があります。

ここに私が持っているものがあり、それはうまくいきます:

Accordion.js

import React from "react";
import PropTypes from "prop-types";
import { Icon } from "../Icon";
import styled from "styled-components";

const AccordionContainer = styled.div`
  display: flex;
  flex-direction: column;
  flex: 1;
  justify-content: ${props => props.justifyContent};
  background-color: ${props => props.theme.color[props.color]};
  ${props => props.theme.fontSize(14)};
`;

const ChildrenContainer = styled.div`
  display: flex;
  flex-direction: column;
`;

const LabelWrapper = styled.div`
  padding: 10px;
`;

/**
 * Accordion is nearly a Higher Order Component (HOC) in the fact that it encapsulates an Icon and when that
 * Icon is clicked an onClick callback provided should toggle the closed state.
 */
export class Accordion extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      closed: props.closed
    };
  }

  render() {
    let {
      props: {
        children,
        hasIcon,
        iconColor,
        iconFlexDirection,
        iconExpand,
        iconName,
        iconSize,
        label,
        color,
        justifyContent
      },
      state: { closed }
    } = this;

    return (
      <AccordionContainer color={color} justifyContent={justifyContent}>
        <div onClick={() => this.setState({ closed: !closed })}>
          {hasIcon ? (
            <>
              <LabelWrapper>
                <Icon
                  fontSize={iconSize}
                  name={iconName}
                  color={iconColor}
                  flexDirection={iconFlexDirection}
                  expand={iconExpand}
                />
              </LabelWrapper>
              {!closed && <ChildrenContainer>{children}</ChildrenContainer>}
            </>
          ) : (
            <>
              <LabelWrapper>
                <div>{label}</div>
              </LabelWrapper>
              {!closed && <ChildrenContainer>{children}</ChildrenContainer>}
            </>
          )}
        </div>
      </AccordionContainer>
    );
  }
}

Accordion.propTypes = {
  color: PropTypes.string,
  closed: PropTypes.bool,
  justifyContent: PropTypes.string,
  hasIcon: PropTypes.bool,
  iconName: PropTypes.string,
  iconColor: PropTypes.string,
  iconExpand: PropTypes.bool,
  iconSize: PropTypes.number,
  label: PropTypes.string
};

Accordion.defaultProps = {
  closed: true,
  hasIcon: false,
  iconExpand: false,
  justifyContent: "flex-start"
};

Accordion.spec.js

import React from "react";
import { shallow, mount, render } from "enzyme";
import styled, { ThemeProvider } from "styled-components";
import theme from "../../styles/theme";
import { Accordion } from "./Accordion";
import sinon from "sinon";

describe("Accordion", () => {

  const AccordionJSX = (
    <ThemeProvider theme={theme}>
      <Accordion
        iconName="home"
        iconColor="#777"
        iconSize={14}
        hasIcon={true}
      >
        HELLO ACCORDION
      </Accordion>
    </ThemeProvider>
  );

  it("Should render without throwing an error", () => {
    expect(shallow(
      AccordionJSX
    )).not.toBeNull();
  });

  const AccordionComponent = mount(AccordionJSX);

  it("Should have a styled-components theme", () => {
    expect(AccordionComponent.props().theme).not.toBeNull();
  });

  it('check props passed in', () => {
    console.log(AccordionComponent.props().children);
    expect(AccordionComponent.props().children.props).toEqual({
      iconName: 'home',
      iconColor: '#777',
      iconSize: 14,
      hasIcon: true,
      children: 'HELLO ACCORDION',
      closed: true,
      iconExpand: false,
      justifyContent: 'flex-start'
    });
  });

  it('check state after opened', () => {
    expect(AccordionComponent.props().theme).not.toBeNull();
  })


});
1
Jason Rice