extend-chrome/jest-chrome

Export mock factory functions for Chrome types

p00ya opened this issue · 0 comments

p00ya commented

Is your feature request related to a problem? Please describe.

Provide a factory for chrome.runtime.Port.

Consider trying to test code that calls chrome.runtime.connect:

const mockConnect = (extensionId?: string, connectInfo?: object) => {
  const port: chrome.runtime.Port = {
    name: connectionInfo?.name ?? 'name',
    postMessage: jest.fn() as jest.MockedFunction<(message: any) => void>,
    disconnect: jest.fn() as jest.MockedFunction<() => void>,
    onDisconnect,  // Event is non-trivial to fake!
    onMessage,  // another Event :(
  };
  return port;
};

chrome.runtime.connect.mockImplementation(mockConnect);

Creating a suitable mock implementation is quite arduous in typescript (Port itself has onMessage and onDisconnect events, and they in turn have a bunch of their own methods that need to be mocked).

jest-chrome already mocks a bunch of things like this, but only for the static functions in the Chrome API. It has the necessary machinery to make mocking events (and even schema-driven mocking) easy, but it neither applies that to things like Port, nor does it expose functions like createEvent.

Describe the solution you'd like

jest-chrome should export a chromeMocks like:

import { chromeMocks } from 'jest-chrome';

const port = new chromeMocks.runtime.Port();
chrome.runtime.connect.mockReturnValue(port);

codeUnderTest();

// Events on the Port mock are just as easy to use as `chrome.runtime.onMessage`.
const listenerSpy = jest.fn();
port.onMessage.addListener(listenerSpy);

Describe alternatives you've considered

Manually mock

i.e. try and finish the code in the mockConnect code in the first section. It's very tedious.

Call-oriented API

A slightly different API than above, instead of factories that return Chrome types like Port, use factories that correspond directly to the synchronous functions that would otherwise return types like Port.

Expose internal helpers

Instead of exposing a factory, jest-chrome could just expose its helpers like createEvent. However, then you'd be exporting APIs that didn't just come from Chrome, and it would make the implementation brittle (since you'd have to support these functions for compatibility going-forwards).

TBH though, just exporting the Event fakes would help a lot with users being able to mock things like Port.

Other mocking packages

I think something like jest-mock-extended would make mocking these types much less tedious. It can already do a lot of what jest-chrome does (but not the Event fakes).

Additional context