How to mock Notifications API with JEST?
Asked Answered
P

1

6

I test redux-actions with jest. Particular redux-action uses Notifications API as a side-effect. How can i mock Notifications API?

Now, i simply mock it this way:

global.Notification = {...};

It works, but i think there is more elegant solution to solve this problem. Any ideas?

I have this module to handle Notifications API:

export const requestNotifyPermission = () => {
    try {
        return Notification.requestPermission().then(function(result) {
            return result;
        });
    } catch(err) {
        console.warn('NotificationsAPI error: ' + err);
    }
};

export const getCurrentNotifyPermission = () => {
    // Possible values = default, granted, denied
    try {
      return Notification.permission;
    } catch {
      return 'denied';
    }
};

export const createNotify = (title, body)  => {
  try {
    if (getCurrentNotifyPermission() === 'granted') {
      var options = {
          body: body
      };
      return new Notification(title, options);  
    }
  } catch(err) {
    console.warn('NotificationsAPI error: ' + err);
  }
}
Pressroom answered 9/5, 2019 at 17:0 Comment(2)
I'm afraid there is no way. the best you can do is encapsulating mocked code in separate file to avoid repeating that from test to test.Roscoe
What do you expected? Is there any error in your unit test?Fawkes
H
6

One way to prevent mocking Notification API at every test file, is by configuring Jest setupFiles.

jest.config.js

module.exports = {
  setupFiles: ["<rootDir>config.ts"],
};

config.ts

globalThis.Notification = ({
  requestPermission: jest.fn(),
  permission: "granted",
} as unknown) as jest.Mocked<typeof Notification>;

Note: globalThis is the most modern way to access the Global scope. If you don't have the required Node version (v12+), just stick with using global object.

This example is also showcasing the use with Typescript, which is a little more tricky.

If you want to mock different permission states, you can do that in the test case:

// Notification.permission
jest
  .spyOn(window.Notification, "permission", "get")
  .mockReturnValue("denied");


// Notification.requestPermission (which is a Promise)
jest
  .spyOn(window.Notification, "requestPermission")
  .mockResolvedValueOnce("granted");

Holtorf answered 14/8, 2020 at 16:0 Comment(2)
The spyOn logic gives Cannot spyOn on a primitive value; undefined given errorPicul
@Picul Are you using any JS framework? In your case, the Notification API seems to be missing in the Jest environment. You can expect slight API differences for each browser depending on your setup (like here and here), but AFAIK that's not the case for the Jest environment.Holtorf

© 2022 - 2024 — McMap. All rights reserved.