Reputation: 1487
I want to test if an element is focused to when the component updated.
componentDidUpdate() {
this.button.focus();
}
I have a render function which gets the component(s)
function render(args) {
const component = shallow(<MyComponent {...args} />);
return {
component,
button: () => component.find("button"),
};
}
My assertion is as follows
describe("When component did update", () => {
it("Should focus to the button", () => {
const { component, button } = render(args);
expect(button().focus).toHaveBeenCalled();
});
});
With just this I get the error
Matcher error: received value must be a mock or spy function
So I thought I needed to add a mock of focus
which I've now done in my beforeEach
, and test that instead, which removes the error but my test asserts 0 calls
instead of 1 call
:
describe("When component did update", () => {
it("Should focus to the button", () => {
const { component, button } = render(defaultArgs);
expect(backButtonElement.focus).toHaveBeenCalled();
});
});
So I must be missing something else
Upvotes: 4
Views: 9735
Reputation: 1426
This worked for me
const wrapper = mount(<MyComponent />);
const input = wrapper.find('input');
expect(input).toHaveFocus();
Upvotes: 5
Reputation: 4773
The reason your test asserts 0 calls
instead of the expected 1 call
is because componentDidUpdate
does not trigger when the component mounts, only on subsequent updates. You need to trigger an update.
describe("When component did update", () => {
it("Should focus to the button", () => {
const { component, button } = render(defaultArgs);
/*
setting some random props to force an update,
ideally you should simulate a real update/user behaviour
when you want the focus triggered
*/
component.setProps({ forceUpdate: true });
component.update();
expect(backButtonElement.focus).toHaveBeenCalled();
});
});
However, in order to avoid testing internal implementation details, I would suggest to assert the expected side-effects that the user should perceive. So, rather than checking if a function was called or not, checking that the button is focused when certain conditions occur:
describe("When component did update", () => {
it("Should focus to the button", () => {
const { component, button } = render(defaultArgs);
// trigger an update, ideally via user interaction
// e.g.
// component.simulate('click')
// check which element is focused in the document
const focusedElement = document.activeElement;
expect(button().node.matchesElement(focusedElement)).toBe(true);
});
});
Upvotes: 0