Jest Enzyme setСостояние памятиЗависит от маршрутизатора

У меня есть задача протестировать компонент React, который зависит от компонента BrowserRouter где-то на верхнем уровне. Насколько я знаю, BrowserRouter передает объект маршрута в реквизиты любого ребенка, внука и т. д.

Составная часть:

import React, { Component } from 'react';
import Program from './Program';

export default class Programs extends Component {
  constructor() {
    super();
    this.state = {
      programs: [
        /** example */
        { id: 10, name: 'Golden Knights' },
        { id: 20, name: 'Silver Lords' },
        { id: 30, name: 'Wooden Kings' },
      ],
    };
  }

  render() {
    const { programs } = this.state;
    return (
      <ul className="programs">{/*<-- add class "att-programs"*/}
        {
          programs.map(
            program => <Program
              key={program.id}
              program_id={program.id}
              program_name={program.name}
            />,
          )
        }
      </ul>
    );
  }
}

Когда я пытаюсь протестировать этот компонент самостоятельно, я получаю сообщение об ошибке: Cannot read property 'route' of undefined. Чтобы обойти эту проблему, я заключаю свой элемент в компонент MemoryRouter, и мой тест выглядит следующим образом:

import React from 'react';
import renderer from 'react-test-renderer';
import { mount, shallow } from 'enzyme';
import { MemoryRouter } from 'react-router-dom';

import Programs from '../../src/components/Programs';

describe('<Programs />', () => {
  it('Renders list for any child from state', () => {

    const wrapper = mount(<MemoryRouter><Programs /></MemoryRouter>);
    const programs = wrapper.find(Programs);
    expect(programs.length).toBe(1);
    programs.setState({
      programs: [
        { id: 1, name: 'qwe' },
        { id: 2, name: 'asd' },
        { id: 3, name: 'zxc' },
      ],
    });

    expect(wrapper.find('li').length).toBe(3);
    expect(wrapper.find('a[href="/player/1"]').length).toBe(1);
  });
});

Теперь у меня другая проблема: ReactWrapper::setState() can only be called on the root

Пожалуйста, помогите мне понять, как мне имитировать маршрутизатор, но при этом сохранить возможность определить setState на тестовом компоненте?


person zelibobla    schedule 11.08.2017    source источник
comment
Думали ли вы о сохранении этого состояния в другом месте (например, в Redux)? Таким образом, состояние будет передано в ваш компонент как свойства -> 100% тестируемость.   -  person luboskrnac    schedule 11.08.2017


Ответы (1)


Я бы предложил не обновлять внутреннее состояние компонента напрямую. У вас есть способы каким-то образом манипулировать этим состоянием (или вы планируете это делать). Так что используйте эти механизмы во время тестирования. Например. вы можете рассмотреть возможность нажатия на кнопки через wrapper.simulate("click") и таким образом изменить состояние. После этого вы можете убедиться, что переход состояния был правильным.

person luboskrnac    schedule 11.08.2017
comment
Переход на props из состояния помог! Благодарю вас! - person zelibobla; 14.08.2017