extend-chrome / jest-chrome

A complete mock of the Chrome API for Chrome extensions for use with Jest.
MIT License
125 stars 24 forks source link

How to make jest-chrome work with webextension-polyfill #7

Open AmySteam opened 3 years ago

AmySteam commented 3 years ago

Google search terms

Jest-chrome mozilla/webextension-polyfill jest.setup

Describe the bug

When using jest-chrome with webextension-polyfill, the browser namespace property returns undefined (For example: browser.runtime.sendMessage). What's strange is that browser is defined and even browser.runtime, but then I look for sendMessage and it returns undefined.

I've already added browser to the global object in my jest.setup file, but I didn't know what else to do to get the namespace to be defined

How do we reproduce?

See a repo here

Expected behavior

I expect the browser namespace properties to be defined.

Actual behavior

The browser namespace property is undefined.

Screenshots

Jest-chrome-browser-pollyfill

Please complete the following information:

jacksteamdev commented 3 years ago

@AmySteam @belykh This is a bug we should fix, but there is a workaround:

Access the Chrome API property first

Make sure that you set the mock implementation for the Chrome API method you intend to use. In your Jest setup file, do something like this:

const { chrome } = require('jest-chrome')
Object.assign(global, { chrome })

chrome.runtime.sendMessage.mockImplementation((...args) => {
  const callback = args[args.length-1] // the last argument is always the callback
  callback() // call the callback with your expected callback args
})

You can do this in the actual test file, whatever works for you. The point is to access the Chrome API property before trying to use it in the Browser API.

Help wanted

This is a bug we need to fix! Both jest-chrome and webextension-polyfill use a Proxy, and they don't always play well together. We need to make the jest-chrome Proxy trick the webextension-polyfill Proxy into thinking the property exists, even if it hasn't been accessed before.