I have a react component that is a basic form in which onSubmit, a function send is called, which checks for a few things before making an API call. The component works fine but I'm having a bit of trouble testing it. The API call itself is wrapped inside grecaptcha.ready and grecaptcha.execute as shown below. I've also made a sandbox here.
async function send(e) {
e.preventDefault();
const to = e.target.elements.to.value;
const message = e.target.elements.message.value;
// Set in a higher level component that wraps our SendEmail component
const grecaptcha = window.grecaptcha;
grecaptcha.ready(() => {
grecaptcha
.execute(process.env.RECAPTCHA_V3_KEY, { action: "action" })
.then(async (token) => {
await sendIt(to, message, token)
.then(() => {
setIsLoading(false);
setTimeout(() => {
history.goBack();
}, 1000);
})
.catch(() => {
setIsLoading(false);
});
});
});
}
My test file looks like the following.
import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import user from "@testing-library/user-event";
import sendIt from "./api";
import SendEmail from "./App";
let token = "test-token";
const originalEnv = process.env;
let history;
beforeEach(() => {
global.grecaptcha = {
ready: jest.fn(),
execute: jest.fn()
};
global.grecaptcha.execute.mockResolvedValueOnce(token);
process.env = {
...originalEnv,
RECAPTCHA_V3_KEY: "fake-key"
};
history = {
goBack: jest.fn(() => "go back")
};
});
afterEach(() => {
process.env = originalEnv;
});
test("successfully sends message", async () => {
sendIt.mockResolvedValueOnce({ data: "data" });
render(<SendEmail history={history} />);
const toInput = screen.getByLabelText("to");
const messageTextArea = screen.getByLabelText("message");
const sendButton = screen.getByRole("button");
user.type(toInput, "me@mail.com");
user.type(messageTextArea, "Hello there!");
user.click(sendButton);
const grecaptcha = global.grecaptcha;
expect(grecaptcha.ready).toHaveBeenCalled();
// Fails at this point here
expect(grecaptcha.execute).toHaveBeenCalled();
await waitFor(() => expect(sendIt).toHaveBeenCalled());
expect(sendIt).toHaveBeenCalledWith("me@mail.com", "Hello there!", token);
await waitFor(() => expect(history.goBack()).toHaveBeenCalled());
});
The expect(grecaptcha.execute).toHaveBeenCalled() assertion fails and the api call doesn't get called. What am I missing? Your help would be greatly appreciated.