Тестирование input.focus() в ферменте

Может ли кто-нибудь помочь мне протестировать input.focus() в ферменте. Я пишу скрипт с реакцией. Мой код ниже.

public inputBox: any;

componentDidUpdate = () => {
    setTimeout(() => {
        this.inputBox.focus();
    }, 200);
}

render() {
    return (
        <div>
            <input
                type = 'number'
                ref = {element => this.inputBox = element } />
        </div>
    );
}

Ответ 1

Другой подход состоит в том, чтобы проверить, фокусируется ли элемент, т. focus() вызывается в элементе узла. Чтобы достичь этого, сфокусированный элемент нужно ссылаться с помощью тега ref как это происходит в вашем примере - this.inputBox ссылка была назначена this.inputBox. Рассмотрим пример ниже:

const wrapper = mount(<FocusingInput />);
const element = wrapper.instance().inputBox; // This is your input ref

spyOn(element, 'focus');

wrapper.simulate('mouseEnter', eventStub());

setTimeout(() => expect(element.focus).toHaveBeenCalled(), 250);

В этом примере используется Jasmine spyOn, хотя вы можете использовать любой шпион, который вам нравится.

Ответ 2

Вы можете использовать mount вместо мелкой. Затем вы можете сравнить document.activeElement и входной узел DOM для равенства.

const output = mount(<MyFocusingComponent/>);

assert(output.find('input').node === document.activeElement);

Дополнительную информацию см. В https://github.com/airbnb/enzyme/issues/316.

Ответ 3

Для реагировать 16,3 обновлений... используя createRef для тех, кто посещает этот пост сегодня, если вы переставляете оригинальный компонент для использования нового ref api

class InputBox extends PureComponent {
    constructor(props) {
        super(props);
        this.inputRef = React.createRef();
    }
    componentDidMount() {
        this.inputRef.current.focus();
    }
    render() {
        return (
            <input
                ref={this.inputRef}
            />
        );
    }
}

Тогда в твоих тестовых спецификациях

it("Gives immediate focus on to name field on load", () => {
    const wrapper = mount(<InputBox />);
    const { inputRef } = wrapper.instance();

    jest.spyOn(inputRef.current, "focus");

    wrapper.instance().componentDidMount();
    expect(inputRef.current.focus).toHaveBeenCalledTimes(1);
});

Обратите внимание на использование атрибута inputRef.current, который ссылается на назначенный в данный момент узел DOM.

Ответ 4

У меня была одна и та же проблема и решена с использованием следующего подхода:

Моя настройка - Jest (action-create-app) + Enzyme:

    it('should set the focus after render', () => {
      // If you don't create this element you can not access the 
      // document.activeElement or simply returns <body/>
      document.body.innerHTML = '<div></div>'

      // You have to tell Enzyme to attach the component to this
      // newly created element
      wrapper = mount(<MyTextFieldComponent />, {
        attachTo: document.getElementsByName('div')[0]
      })

      // In my case was easy to compare using id 
      // than using the whole element
      expect(wrapper.find('input').props().id).toEqual(
        document.activeElement.id
      )
    })

Ответ 5

Это сработало для меня при использовании mount и useRef hook:

expect(wrapper.find('input').get(0).ref.current).toEqual(document.activeElement)

Ответ 6

Фокус на конкретном элементе можно проверить с помощью селекторов.

const wrapper = mount(<MyComponent />);

const input = wrapper.find('input');
expect(input.is(':focus')).toBe(true);

Ответ 7

Выбор из атрибута data-test или чего-то подобного был самым простым решением, которое я мог придумать.

import React, { Component } from 'react'
import { mount } from 'enzyme'

class MyComponent extends Component {
  componentDidMount() {
    if (this.inputRef) {
      this.inputRef.focus()
    }
  }

  render() {
    return (
      <input data-test="my-data-test" ref={input => { this.inputRef = input } } />
    )
  }
}

it('should set focus on mount', () => {
  mount(<MyComponent />)
  expect(document.activeElement.dataset.test).toBe('my-data-test')
})