Функции React / Enzyme Component не обновляют состояние - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть компонент, который работает на localhost. Если вы вводите букву чемпиона, onInputHandler (input) изменяет состояние компонента на действительное имя чемпиона. К сожалению, когда я тестирую с энзимом, состояние компонента никогда не меняется (остается по умолчанию). Буду рад любым советам. Когда я устанавливаю this.statechampionsList с массивом, результат такой же. Обычно массив заполняется методом getChampionsList () после componentDidMount ().

        export class ChooseChampion extends React.Component {
    constructor() {
        super();
        this.state = {
            championSelected: "Choose champion",
            championsList: []
        };

        this.onInputHandler = this.onInputHandler.bind(this);
        this.getFilteredChampion = this.getFilteredChampion.bind(this);
    }

    componentDidMount() {
        this.getChampionsList();
    }

    getChampionsList = () => {
        fetch('/champions-list')
            .then(res => res.json())
            .then(champions => this.setState({ championsList: champions }))
    }

    onInputHandler(event) {
        if (event.target.value === "") {
            this.setState({
                championSelected: "Choose champion"
            });
        } else {
            const input = event.currentTarget.value;
            const filteredChampion = this.getFilteredChampion(input)
            this.setState({
                championSelected: filteredChampion
            });
        }
    }

    getFilteredChampion(input) {
        let oneFilteredChampion = this.state.championsList.find(champion => champion.toLowerCase().includes(input.toLowerCase()))
        if (oneFilteredChampion) {
            return oneFilteredChampion;
        } else {
            return "Wrong name!"
        }
    }

    render() {
        return (
            <div className="choose-champion-container">

                <div className="role-and-caption inactive">
                    <img className="role-icon" src={require(`../assets/images/${this.props.lane}_icon.png`)} alt={this.props.lane} />
                    <span className="role-caption">{this.props.lane}</span>
                </div>

                <div className="champion-avatar-and-caption">
                    <ChampionAvatar currentChampion={this.state.championSelected} championsList={this.state.championsList} />
                    <ChampionCaption currentChampion={this.state.championSelected} championsList={this.state.championsList} />
                </div>

                <div className="search-container">
                    <button type="submit" className="search-button"><img src={SearchIcon} className="search-icon" alt="Search" /></button>
                    <input type="text" placeholder="Find champion..." name="search" onInput={this.onInputHandler} />
                </div>
            </div>
        )
    };
}

Вот мое утверждение тестирования:

const lanes = ["Top", "Jungle", "Middle", "Bottom", "Support"]
const app = <ChooseChampion lane={lanes[Math.floor(Math.random() * (5))]} />;

it('Should change the state after change the input value', () => {
  const newValue = 'Ahri';
  const wrapper = mount(app);
  const input = wrapper.find('input');

  input.value = newValue;

  wrapper.update();
  expect(input.value).toEqual(newValue);
  expect(wrapper.state('championSelected')).toEqual(newValue);
});

1 Ответ

1 голос
/ 29 апреля 2020

Попробуйте заменить

input.value = newValue;

на

input.simulate('change', {target: {value: newValue}});

или

input.simulate('input', {target: {value: newValue}});

Чтобы вызвать событие (onChange или onInput), вам необходимо смоделировать событие DOM. Простое изменение значения на входе не вызывает слушателей React.

Другое дело, вы делаете выборку в componentDidMount. Это асин c вызов. Сразу после mount список чемпионов не будет заполнен. Есть несколько способов подождать, пока это произойдет. Вы можете использовать ожидание ожидания или написать аналогичную функцию самостоятельно. Итак, наконец, тест должен выглядеть примерно так:

it('Should change the state after change the input value', () => {
  const newValue = 'Ahri';
  const wrapper = mount(app);

  await waitForExpect(() => {
    expect(wrapper.state('championsList')).to.be.not.empty;
  });

  const input = wrapper.find('input');

  input.simulate('change', {target: {value: newValue}});

  wrapper.update();
  expect(input.value).toEqual(newValue);
  expect(wrapper.state('championSelected')).toEqual(newValue);
});

Примечание : вы можете предпочесть использовать такой инструмент, как nock , чтобы высмеивать бэкэнд вместо вызова фактическая конечная точка в тестах.

...