Reputation: 259
I am trying to test a specific component that is nested within two other components:
<Router>
<Provider store={store}>
<Howitworks />
</Provider>
</Router>
However when I try to run my test:
test("should call onTaskerClick", () => {
const spy = jest.spyOn(Howitworks.prototype, "onTaskerClick");
const wrapper = mount(
<Router>
<Provider store={store}>
<Howitworks />
</Provider>
</Router>
);
wrapper.find("#pills-tasker-tab.nav-link.tasklink").at(0).simulate("click");
expect(spy).toHaveBeenCalled();
});
I get a "spyOn on a primitive value; undefined given" error. I have tried different variations of mocking this "onTaskerClick" function when simulating a click on the link that invokes it but always get a variation of the error that the function is undefined or function was not called.
The link that invokes onTaskerClick:
<a className='nav-link tasklink' id='pills-tasker-tab' data-toggle='pill' onClick={this.onTaskerClick} role='tab' aria-controls='pills-tasker' aria-selected='false'>LINK<span></span></a>
Here is how the Howitworks component is currently being exported:
export default connect(mapStateToProps, { onNotifyClick })(Howitworks);
Unfortunately there's very limited documentation on accessing functions within a nested component in a test environment so any help would be great.
EDIT:
Updated test suite:
test("should call onTaskerClick", () => {
const wrapper = mount(
<Router>
<Provider store={store}>
<Howitworks />
</Provider>
</Router>
);
const spy =
jest.spyOn(wrapper.find(Howitworks.WrappedComponent).instance(), "onTaskerClick");
wrapper.find("#pills-tasker-tab.nav-link.tasklink").at(0).simulate("click");
expect(spy).toHaveBeenCalled();
});
mapStateToProps function and export:
let mapStateToProps = (state) => ({});
export default connect(mapStateToProps, { onNotifyClick })(Howitworks);
Upvotes: 1
Views: 1009
Reputation: 222319
connect
returns a higher-order component that doesn't inherit from original component, which is common in React.
In order for onTaskerClick
to be spyable on a prototype, it should be prototype and not instance (arrow) method. Original component class can be either separate named export:
export class Howitworks {
onTaskerClick() {...}
...
}
export default connect(...)(Howitworks);
Or it can be accessed on connected component as WrappedComponent
property.
Since onTaskerClick
isn't called on component instantiation, there's no need to spy on a prototype, it's easier to do this on an instance, this doesn't limit a spy to prototype methods:
const wrapper = mount(...);
const origComp = wrapper.find(Howitworks.WrappedComponent).instance();
const spy = jest.spyOn(origComp, "onTaskerClick");
origComp.forceUpdate();
// trigger click
Upvotes: 1