Как проверить функцию, которая изменяет состояние моего компонента? - PullRequest
0 голосов
/ 23 января 2019

У меня есть этот компонент:

// imports

class FiltersModal extends React.Component {
  state = {
    status: '',
    carrier: '',
  };

  applyFilters = () => {
    const { applyFilters } = this.props;
    const {
      status,
      carrier,
    } = this.state;

    applyFilters({
      status,
      carrier,
    });
  };

  handleChange = field => ev => {
    this.setState({ [field]: ev.target.value });
  };

  render() {
    const { t, isFiltersModalOpened, toggleFiltersModal } = this.props;
    const { shippedDate } = this.state;

    return (
      <Modal
        open={isFiltersModalOpened}
        onRequestClose={toggleFiltersModal}
        onRequestSubmit={this.applyFilters}
      >
        <Form>

          <StatusesSelect handleStatus={this.handleChange('status')} />
          <GetAllCouriers handleCouriers={this.handleChange('carrier')} />

        </Form>
      </Modal>
    );
  }
}

FiltersModal.propTypes = {
  t: PropTypes.func.isRequired,
  isFiltersModalOpened: PropTypes.bool.isRequired,
  toggleFiltersModal: PropTypes.func.isRequired,
  applyFilters: PropTypes.func.isRequired,
};

export default translate()(FiltersModal);

И этот тест:

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

jest.mock('react-i18next', () => ({
  // this mock makes sure any components using the translate HoC receive the t function as a prop
  translate: () => Component => {
    Component.defaultProps = { ...Component.defaultProps, t: key => key }; // eslint-disable-line
    return Component;
  },
}));

describe('FiltersModal component test', () => {
  let props;

  beforeEach(() => {
    props = {
      t: k => k,
      isFiltersModalOpened: false,
      toggleFiltersModal: jest.fn(() => k => k),
      removeFilter: jest.fn(() => k => k),
      applyFilters: jest.fn(() => k => k),
      softlayerAccountId: '232279',
      filters: {
        carrier: 'UPS',
        shipmentId: '1234',
        shipmentType: '',
        shippedDate: '',
        shippedFrom: '',
        shippedTo: '',
        status: '',
      },
    };
  });

  it('should render without errors', () => {
    const wrapper = shallow(<FiltersModal {...props} />);

    expect(wrapper.find('Modal')).toHaveLength(1);
    expect(wrapper.find('Form')).toHaveLength(1);
  });

  it('should change state', () => {
    const wrapper = shallow(<FiltersModal {...props} />);

    wrapper.setState({ carrier: 'UPS' });

    wrapper.instance().applyFilters();
    wrapper.instance().handleChange('status');

    expect(props.applyFilters).toHaveBeenCalledTimes(1);
    expect(wrapper.instance().handleChange).toHaveBeenCalledTimes(1);
  });
});

Мне нужно вызвать функцию handleChange, но я получаю эту ошибку:

 FAIL  src/client/pages/Shipments/__tests__/components/FiltersModal-test.js
  FiltersModal component test
    ✓ should render without errors (15ms)
    ✕ should change state (12ms)

  ● FiltersModal component test › should change state

    expect(jest.fn())[.not].toHaveBeenCalledTimes()

    jest.fn() value must be a mock function or spy.
    Received:
      function: [Function anonymous]

      51 | 
      52 |     expect(props.applyFilters).toHaveBeenCalledTimes(1);
    > 53 |     expect(wrapper.instance().handleChange).toHaveBeenCalledTimes(1);
         |                                             ^
      54 |   });
      55 | });
      56 | 

Чего мне не хватает?

Ответы [ 3 ]

0 голосов
/ 23 января 2019

handleChange является действительной функцией, а не ложным или шпионским (как указано в ошибке).

Если вы не хотите издеваться над функцией, вы можете использовать шпион , чтобы проверить, был ли он вызван:

const spy = jest.spyOn(wrapper.instance(), "handleChange");

wrapper.instance().handleChange("status");

expect(spy).toHaveBeenCalledTimes(1);
0 голосов
/ 23 января 2019

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

Поэтому я предлагаю вам убедиться, что измененные значения выходят за пределы applyFilters:

it('should change state', () => {
  const applyFiltersMock = jest.fn();
  const wrapper = shallow(<FiltersModal {...props} applyFilters={applyFiltersMock} />);
  wrapper.find(StatusesSelect).props().handleStatus({ target: {value: '2'} });
  wrapper.find(GetAllCouriers ).props().handleCouriers({ target: {value: '3'} });

  wrapper.find(Modal).props().onRequestSubmit();
  expect(applyFiltersMock).toHaveBeenCalledTimes(1);
  expect(applyFiltersMock).toHaveBeenCalledWith({status: '2', carrier: '3'});
});
0 голосов
/ 23 января 2019

Вы можете проверить состояние компонента, используя state .После запуска handleChange проверьте состояние компонента, если состояние изменяется на желаемое, оно должно пройти тест

...