9

I am using jest tests to test my React project written in #typescript created with Create React App. I'm using react-testing-library. I have a form component which shows an alert if the form is submitted empty. I wanted to test this feature (maybe) by spying/mocking the window.alert but it doesn't work.

I tried using jest.fn() as suggested in many SO answers but that's not working too.

window.alert = jest.fn();
expect(window.alert).toHaveBeenCalledTimes(1);

Here's how I implemented it: Form.tsx

async handleSubmit(event: React.FormEvent<HTMLFormElement>) {
   // check for errors
    if (errors) {
        window.alert('Some Error occurred');
        return;
    }
}

Here's how I built the React+Jest+react-testing-library test: Form.test.tsx

it('alerts on submit click', async () => {
  const alertMock = jest.spyOn(window,'alert'); 
  const { getByText, getByTestId } = render(<Form />)
  fireEvent.click(getByText('Submit'))
  expect(alertMock).toHaveBeenCalledTimes(1)
})
Mayur Dhurpate
  • 1,112
  • 4
  • 16
  • 34
  • 1
    I see `handleSubmit` is async. Are you doing any `await` before calling `alert`? – Gio Polvara May 07 '19 at 22:45
  • Yes, I call await `await saveImagetoStorage()` which saves an image to FirebaseStorage, as well as call `await activityObject.createActivity();` which saves a document to Firebase-Firestore. Is that an issue? – Mayur Dhurpate May 08 '19 at 09:55
  • Oh, do I need to [use](https://www.leighhalliday.com/async-axios-react-testing-library) `await waitForElement(() => getByText(/_______/i));` before expecting `alertMock`? – Mayur Dhurpate May 08 '19 at 09:57

2 Answers2

11

I think you might need to tweak your test ever so slightly by adding .mockImplementation() to your spyOn like so:

it('alerts on submit click', async () => {
  const alertMock = jest.spyOn(window,'alert').mockImplementation(); 
  const { getByText, getByTestId } = render(<Form />)
  fireEvent.click(getByText('Submit'))
  expect(alertMock).toHaveBeenCalledTimes(1)
})
George
  • 147
  • 2
  • 12
5

You could try to use global instead of window:

global.alert = jest.fn();
expect(global.alert).toHaveBeenCalledTimes(1);

Alternatively, try to Object.assign

const alert = jest.fn()
Object.defineProperty(window, 'alert', alert);