Как использовать фермент ShallowWrapper, чтобы найти компонент React, хранящийся в качестве опоры в другом компоненте React?

У меня есть тест шутки / фермента, который создает ShallowWrapper вокруг компонента, находит указанную кнопку semantic-ui-react (по идентификатору), имитирует щелчок по кнопке, а затем проверяет, переключил ли щелчок определенный контент.

Пример JSX:

<Popup
  trigger={<Button onClick={this.toggleShowThing} id="special-btn">a button</Button>}
  content="Popup Words"
/>
{this.state.showThing &&
  <div className="special-thing">The Thing's Words</div>
}

Образец теста:

it('shows the thing when the button is clicked', () => {
  const wrapper = shallow(<MyComponent />);
  wrapper.find('#special-btn').simulate('click', { preventDefault() {} });
  expect(wrapper.find('.special-thing').exists()).toBe(true);
});

Этот тест работал, когда у меня был только Button. Когда я добавил всплывающее окно и кнопка была помещена в опору триггера, я получил сообщение об ошибке, потому что не удалось найти # special-btn.

Ошибка: метод «props» предназначен для запуска только на одном узле. 0 нашел взамен.

Снимок фермента компонента показывает, что всплывающее окно выглядит следующим образом:

<Popup 
  content="Popup Words"
  on="hover"
  position="top left"
  trigger={
    <Button
      id="special-btn"
      onClick={[Function]}
    >
      a button
    </Button>
  }
/>

Мне нужен мой тест, чтобы снова работать. Как мне снова получить доступ к # special-btn в тесте, чтобы я мог вызвать .simulate ('щелкнуть') по нему?


person FrostyFox    schedule 23.08.2017    source источник


Ответы (3)


Предполагая, что Popup - это какой-то сторонний компонент, который уже был протестирован, я бы подошел к тестированию следующим образом:

(1) Найдите всплывающее окно и проверьте, является ли свойство onClick для кнопки trigger prop componentWrapper.instance().toggleShowThing

(2) Отдельно установите this.state.showThing в false и убедитесь, что div с className не отображается; установите this.state.showThing в значение true и убедитесь, что он отображается.

(*) this.toggleShowThing также следует протестировать самостоятельно.

person nbkhope    schedule 23.08.2017

Вот что у меня сработало, хотя документации для этого нет:

import {shallow, ShallowWrapper} from "enzyme";

it('shows the thing when the button is clicked', () => {
  const wrapper = shallow(<MyComponent />);
  const button = new ShallowWrapper(
    wrapper.find('Popup').prop('trigger'), wrapper
  );
  button.simulate('click', { preventDefault() {} });
  expect(wrapper.find('.special-thing').exists()).toBe(true);
});

Другими словами:

  1. Найдите компонент Popup.
  2. Получите компонент, визуализированный в его trigger prop. Обратите внимание, что это еще не мелкая обертка, так что никаких модных API пока нет.
  3. Вручную создайте оболочку, используя ShallowWrapper (важно передать второй аргумент).
  4. Теперь вы можете получить доступ ко всем API-интерфейсам ферментов для взаимодействия с кнопкой.

Обратите внимание: похоже, вы можете избежать использования конструктора и использовать wrap () служебный метод (также не документированный):

  const button = wrapper.wrap(wrapper.find('Popup').prop('trigger'));
person Piotr Ćwiek    schedule 18.03.2020

Проблема в том, что вы не можете этого сделать. Вам нужно переписать свой тест. Теперь ваша кнопка обернута Popup компонентом, поэтому у вас нет к нему доступа. Но вы можете переместить свой селектор на Popup и проверить, требует ли изменение щелчка по всплывающему окну. Другого пути нет.

// JSX
<Popup
  trigger={<Button onClick={this.toggleShowThing} id="special-btn">a button</Button>}
  content="Popup Words"
  id="popup"
/>
{this.state.showThing &&
  <div className="special-thing">The Thing's Words</div>
}

// test
it('shows the thing when the button is clicked', () => {
  const wrapper = shallow(<MyComponent />);
  wrapper.find('#popup').simulate('click', { preventDefault() {} });
  expect(wrapper.find('.special-thing').exists()).toBe(true);
});
person lukaleli    schedule 23.08.2017
comment
Проверил вашу рекомендацию, к сожалению, не работает. ShallowWrapper может найти всплывающее окно, но имитируемое событие щелчка может не распространяться на фактическую кнопку и поэтому не вызывает this.toggleShowThing (). Полагаю, это из-за мелкого рендеринга? - person FrostyFox; 24.08.2017
comment
@FrostyFox, возможно, вам стоит попробовать смонтировать компонент вместо мелкого рендеринга. неглубокий рендеринг не распространяет события по компоненту. - person lukaleli; 24.08.2017