I struggled with this and couldn't find anything on Salesforce StackExchange or Google covering this kind of scenario in an LWC-specific context. So I'm going to post something Q&A-style.
I have a parent LWC with a child component and button like this:
<c-child></c-child>
<lightning-button label="Click me" onclick={handleClick}>
</lightning-button>
On button click, the parent component calls an @api
-decorated function on the child, like this:
handleClick(event) {
this.template.querySelector("c-child").sayHello(event.target.label);
}
For this example, I want to write a Jest test that asserts that the child component's @api
-decorated sayHello
function was called with a single argument: "Click me".
I initially expected the following to work, but it failed:
it("sends stuff to the child component", () => {
const element = createElement("c-parent", {
is: parent
});
document.body.appendChild(element);
// Set up an event listener on the child
const child = element.shadowRoot.querySelector("c-child");
const sayHelloHandler = jest.fn();
child.addEventListener("sayHello", sayHelloHandler);
// Simulate the user clicking the lightning-button
const button = element.shadowRoot.querySelector("lightning-button");
button.dispatchEvent(new Event("click"));
// THIS FAILS -- sayHelloHandler shows 0 calls
expect(sayHelloHandler).toHaveBeenCalledWith("Click me");
});
Best Answer
I was able to introspect calls to the child component's function using
jest.spyOn()
, like this:See Jest docs