Reputation: 406
How do I test input.focus()
in enzyme. I am writing the script with react. My code is below:
public inputBox: any;
componentDidUpdate = () => {
setTimeout(() => {
this.inputBox.focus();
}, 200);
}
render() {
return (
<div>
<input
type = 'number'
ref = {element => this.inputBox = element } />
</div>
);
}
Upvotes: 25
Views: 48215
Reputation: 1426
This should work
const wrapper = mount(<MyComponent />);
const input = wrapper.find('input');
expect(input).toHaveFocus();
Upvotes: 0
Reputation: 21
Focus on the particular element can be checked using selectors.
const wrapper = mount(<MyComponent />);
const input = wrapper.find('input');
expect(input.is(':focus')).toBe(true);
Upvotes: 2
Reputation: 96
Selecting by data-test
attribute or something similar was the most straight forward solution I could come up with.
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')
})
Upvotes: 0
Reputation: 5055
This worked for me when using mount
and useRef
hook:
expect(wrapper.find('input').get(0).ref.current).toEqual(document.activeElement)
Upvotes: 2
Reputation: 3546
Per React 16.3 updates... using createRef
for anyone visiting this post today, if you rearrange the original component to use the new 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}
/>
);
}
}
Then in your test spec
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);
});
Notice the use of the inputRef.current
attribute which references the currently assigned DOM node.
Upvotes: 11
Reputation: 164
Other approach is to test if element gains focus, i.e. focus()
is called on node element. To achieve this, focused element need to be referenced via ref
tag like it takes place in your example – reference was assigned to this.inputBox
. Consider example below:
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);
This example uses Jasmine's spyOn, though you can use any spy you like.
Upvotes: 10
Reputation: 367
I just had the same issue and solved using the following approach:
My setup is Jest (react-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
)
})
Upvotes: 4
Reputation: 303
You can use mount
instead of shallow.
Then you can compare document.activeElement
and the input DOM node for equality.
const output = mount(<MyFocusingComponent/>);
assert(output.find('input').node === document.activeElement);
See https://github.com/airbnb/enzyme/issues/316 for more details.
Upvotes: 24