Minimalist Worker mocks in TypeScript
worker-mock is a TypeScript library working in conjunction with worker-facade to easily test Worker
logic.
The package on NPM is:
@giancosta86/worker-mock
which should most often be a dev dependency.
The public API entirely resides in the root package index, so one shouldn't reference specific modules.
Since the WorkerFacade
interface should be referenced by clients in order to be able to plug WorkerMock
when running tests, you'll most often want to add the worker-facade peer library as a non-dev dependency:
@giancosta86/worker-facade
To use the matchers provided by this library, one needs to:
-
Add the following attribute to the object exported by
jest.config.js
:setupFilesAfterEnv: ["@giancosta86/worker-mock/dist/all"],
-
Add this line to a
global.d.ts
file within the project root directory:import "@giancosta86/worker-mock";
-
Add
"./global.d.ts"
to theinclude
array intsconfig.json
After installing worker-facade as a non-dev dependency, you should:
-
Implement the body of the worker as a
RequestListener<TRequest, TResponse>
- a function type provided byworker-facade
:export const yourRequestListener: RequestListener<TRequest, TResponse> = ( request, sendResponse ) => { //Here, process the request and //call sendResponse() for each message //to be sent to the client };
Please, note: this function must NOT reside in the worker script - but in a dedicated module instead.
-
In the worker script, just import
RequestListener
andyourRequestListener
, then add the line:RequestListener.register(self, yourRequestListener);
-
Every software component that needs to exchange messages with the worker should not depend on
Worker
- but on theWorkerFacade<TRequest>
interface, which includes just the subset of methods and events dedicated to message passing:function f(worker: WorkerFacade<TRequest>): void { //Do some stuff, then send a request, //which must be of type TRequest worker.postMessage({ alpha: 90, beta: 100 }); }
-
In tests, the
Worker
logic can be plugged into clients by importingyourRequestListener
and wrapping it into aWorkerMock
:WorkerMock.create(yourRequestListener);
because
WorkerMock
actually implementsWorkerFacade
worker-mock also provides useful extensions to Jest's expect()
:
-
expect(eventListenerFunction).toHaveBeenCalledWithMessageEvents([array of message objects])
:-
the argument of
expect()
must be a mock function created viajest.fn()
and registered via:workerFacade.addListener("message", eventListenerFunction);
-
the argument of the matcher but be an array of message objects - that is, the
data
fields of theMessageEvent
instances actually received by the listener
Please, note: the arrays of actual and expected messages are compared according to deep structural equality - that is, by comparing their JSON strings, so as to support arbitrarily-nested message structures
-
-
expect(eventListenerFunction).toHaveBeenCalledWithErrorEvents([array of error message strings])
:-
the argument of
expect()
must be a mock function created viajest.fn()
and registered via:workerFacade.addListener("error", eventListenerFunction);
-
the argument of the matcher must be an array of error message strings - that is, the
message
fields of theErrorEvent
instances actually received by the listener
-
- worker-facade - Message-passing TypeScript utilities for Worker