Reactjs тестирование условного рендеринга (снимок)

Я пытаюсь протестировать свое приложение ReactJS, но у меня есть проблема. У меня есть заголовок, который определенным образом отображается для первой страницы приложения, и этот заголовок изменится на всех других страницах. Я управляю изменениями, используя текущее местоположение из react-router-dom, Я не знаю, как проверить, что в зависимости от URL, заголовок меняется. Прямо сейчас я делаю основные вещи в моем тестовом файле:

import React from 'react';
import { shallow } from 'enzyme';
import HeaderSto from './HeaderSto';
import '../../setupTests';

describe("HeaderSto", () => {

    it("should render my component", () => {
        process.env.REACT_APP_MERCHANT = "merchant";
        const wrapper = shallow(<HeaderSto />);
        expect.anything(wrapper);
    });

    it("should render LandingPage header layout", () => {
        process.env.REACT_APP_MERCHANT = "merchant";
        window.location.assign = jest.fn();
        const tree = shallow(<HeaderSto />);
        expect(tree).toMatchSnapshot();
    });
});

И компонент

import React from 'react';
import { Row, Col } from 'antd';

class HeaderSto extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            CurrentRoute: ""
        };
    }

    componentDidMount() {
        this.setState({
            CurrentRoute: this.props.CurrentRoute
        });
    }

    componentWillReceiveProps(nextProps) {
        this.setState({
            CurrentRoute: nextProps["CurrentRoute"]
        });
    }

    renderGeneralHeader() {

        return(<div>Hi</div>);
    }

    renderLandingPageHeader() {

        const logo = require("../../images/" + process.env.REACT_APP_MERCHANT + "/" + process.env.REACT_APP_MERCHANT + "_logo.svg");
        return (
            <div>
                <Row>
                    <Col className="header-merchant-logo-div" xs={{span: 18, offset: 3}} sm={{span: 18, offset: 3}} md={{span: 18, offset: 3}} lg={{span:4, offset: 1}} xl={{span:4, offset: 1}}>
                        <img className="header-merchant-logo" src={logo} alt="MerchantLogo"/>
                    </Col>
                </Row>
            </div>
        );
    }

    render() {
        return (
            <div>
                {this.state.CurrentRoute === "/" ? this.renderLandingPageHeader() : this.renderGeneralHeader()}
            </div>
        );
    }
}

export default HeaderSto;

Я должен смоделировать местоположение (это должно быть легко), но я не понимаю, как я должен указать, чтобы шутить, что снимок не совпадает в зависимости от этого места...

Я думаю, что я все объяснил, не стесняйтесь спрашивать больше деталей, если это необходимо.

Спасибо за помощь. Хорошего дня

2 ответа

Привет, Ульд. Я ценю, если вы изучаете юнит-тестирование согласно своей цели. Помните, что в Jest есть два типа тестирования SnapShot и тестирование поведения компонентов. Мы проводим тестирование моментальных снимков, например, "Как мы структурируем наш компонент". Если вносить какие-либо изменения в структуру jsx, он не должен совпадать с предыдущим снимком, если он есть.

В вашем случае есть две ветви в вашем HeaderSto если вы видите свой отчет о покрытии. Вы должны убедиться, что вы тестируете оба случая, чтобы обеспечить 100% охват. Проходя "/" один раз, а другой раз - другой маршрут, чтобы выполнить оба условия.

Вот как мы проводим тестирование снимков:

import renderer from 'react-test-renderer';

it('renders correctly', () => {
  const tree = renderer.create(
    <HeaderSto />
  ).toJSON();
  expect(tree).toMatchSnapshot();
});

РЕДАКТИРОВАНИЕ Давайте рассмотрим пример, позволяющий отличить стратегию моментальных снимков от тестов с мелкой и монтировкой.

У нас есть компонент приложения:

class App extends Component {
  render() {
    return (
      <div className="App">
        <Header />
        <p className="App-intro" onClick={this.handleClick}>
          {data.appName}.
        </p>
      </div>
    );
  }
}

ТестированиеSnapShot приведет к этому:

exports[`renders without crashing 1`] = `
<div
  className="App"
>
  <Header />
  <p
    className="App-intro"
    onClick={[Function]}
  >
    To get started, edit 
    <code>
      src/App.js
    </code>
     and save to reload.
  </p>
</div>
`;

и мелкий рендеринг расскажет нам, как ведет себя наш компонент: мы будем имитировать data.appName и метод onClick, так как наше приложение ожидает одно свойство appName, а также нам нужно протестировать его дескриптор, поэтому мы имитируем их обоих:

const data = {
 appName: 'My App'
}
describe('HandleClick on P event success', () => {
 it('handleClick click invokes without throwing an error', () => {
    const handleClick = jest.fn();
    const wrapper = shallow(<App
      handleClick={handleClick}
       />);
    wrapper.find('.app').simulate('click');
    expect(handleClick).toHaveBeenCalled();
  });
});

Не стесняйтесь делиться любыми мыслями. Рад помочь вам с этим.

Я не вижу, где вы используете функцию определения местоположения, похоже, CurrentRoute только что прошел через реквизит. Так что просто передайте это в ваших тестах так:

it("should render LandingPage header layout", () => {
    process.env.REACT_APP_MERCHANT = "merchant";
    const tree = shallow(<HeaderSto />);
    expect(tree).toMatchSnapshot();
});

it("should render LandingPage header layout", () => {
    process.env.REACT_APP_MERCHANT = "merchant";
    const tree = shallow(<HeaderSto currentRoute="/some-other-path" />);
    expect(tree).toMatchSnapshot();
});
Другие вопросы по тегам