chore(tests): add tests for worker-executor

This commit is contained in:
Valeriy
2019-03-19 00:59:13 +03:00
committed by mrugesh mohapatra
parent 845b966bda
commit 80eaccc467

View File

@@ -0,0 +1,237 @@
/* global expect, jest */
import createWorker from './worker-executor';
function mockWorker({ init, postMessage, terminate } = {}) {
global.Worker = jest.fn(function() {
setImmediate(
(init && init(this)) ||
(() =>
this.onmessage && this.onmessage({ data: { type: 'contentLoaded' } }))
);
this.onmessage = null;
this.postMessage =
postMessage ||
function(data) {
setImmediate(
() => this.onmessage && this.onmessage({ data: `${data} processed` })
);
};
this.terminate = terminate || (() => {});
return this;
});
}
afterEach(() => {
delete global.Worker;
});
it('Worker executor should successfully execute one task', async () => {
const terminateHandler = jest.fn();
mockWorker({ terminate: terminateHandler });
const testWorker = createWorker('test');
expect(testWorker).not.toBeUndefined();
const task = testWorker.execute('test');
expect(task).not.toBeUndefined();
expect(task.done).not.toBeUndefined();
const handler = jest.fn();
task.on('done', handler);
const errorHandler = jest.fn();
task.on('error', errorHandler);
await expect(task.done).resolves.toBe('test processed');
expect(handler).toBeCalledTimes(1);
expect(handler).toBeCalledWith('test processed');
expect(errorHandler).not.toBeCalled();
expect(terminateHandler).not.toBeCalled();
expect(global.Worker).toBeCalledTimes(1);
expect(global.Worker).toBeCalledWith('/js/test.js');
});
// eslint-disable-next-line max-len
it('Worker executor should successfully execute two tasks in parallel', async () => {
const terminateHandler = jest.fn();
mockWorker({ terminate: terminateHandler });
const testWorker = createWorker('test');
const task1 = testWorker.execute('test1');
const handler1 = jest.fn();
task1.on('done', handler1);
const errorHandler1 = jest.fn();
task1.on('error', errorHandler1);
const task2 = testWorker.execute('test2');
const handler2 = jest.fn();
task2.on('done', handler2);
const errorHandler2 = jest.fn();
task2.on('error', errorHandler2);
await expect(Promise.all([task1.done, task2.done])).resolves.toEqual([
'test1 processed',
'test2 processed'
]);
expect(handler1).toBeCalledTimes(1);
expect(handler1).toBeCalledWith('test1 processed');
expect(errorHandler1).not.toBeCalled();
expect(handler2).toBeCalledTimes(1);
expect(handler2).toBeCalledWith('test2 processed');
expect(errorHandler2).not.toBeCalled();
expect(terminateHandler).not.toBeCalled();
expect(global.Worker).toBeCalledTimes(2);
});
// eslint-disable-next-line max-len
it('Worker executor should successfully execute 3 tasks in parallel and use two workers', async () => {
mockWorker();
const testWorker = createWorker('test');
const task1 = testWorker.execute('test1');
const task2 = testWorker.execute('test2');
const task3 = testWorker.execute('test3');
await expect(
Promise.all([task1.done, task2.done, task3.done])
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
expect(global.Worker).toBeCalledTimes(2);
});
// eslint-disable-next-line max-len
it('Worker executor should successfully execute 3 tasks, use 3 workers and terminate each worker', async () => {
const terminateHandler = jest.fn();
mockWorker({ terminate: terminateHandler });
const testWorker = createWorker('test', { terminateWorker: true });
const task1 = testWorker.execute('test1');
const task2 = testWorker.execute('test2');
const task3 = testWorker.execute('test3');
await expect(
Promise.all([task1.done, task2.done, task3.done])
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
expect(terminateHandler).toBeCalledTimes(3);
expect(global.Worker).toBeCalledTimes(3);
});
// eslint-disable-next-line max-len
it('Worker executor should successfully execute 3 tasks in parallel and use 3 workers', async () => {
mockWorker();
const testWorker = createWorker('test', { concurrency: 3 });
const task1 = testWorker.execute('test1');
const task2 = testWorker.execute('test2');
const task3 = testWorker.execute('test3');
await expect(
Promise.all([task1.done, task2.done, task3.done])
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
expect(global.Worker).toBeCalledTimes(3);
});
// eslint-disable-next-line max-len
it('Worker executor should successfully execute 3 tasks and use 1 worker', async () => {
mockWorker();
const testWorker = createWorker('test', { concurrency: 1 });
const task1 = testWorker.execute('test1');
const task2 = testWorker.execute('test2');
const task3 = testWorker.execute('test3');
await expect(
Promise.all([task1.done, task2.done, task3.done])
).resolves.toEqual(['test1 processed', 'test2 processed', 'test3 processed']);
expect(global.Worker).toBeCalledTimes(1);
});
it('Worker executor should reject task', async () => {
const error = { message: 'Error on init worker' };
mockWorker({
init: () => {
throw error;
}
});
const testWorker = createWorker('test');
const task = testWorker.execute('test');
const errorHandler = jest.fn();
task.on('error', errorHandler);
await expect(task.done).rejects.toBe(error.message);
expect(errorHandler).toBeCalledTimes(1);
expect(errorHandler).toBeCalledWith(error);
});
it('Worker executor should emit LOG events', async () => {
mockWorker({
postMessage: function(data) {
setImmediate(() => {
for (let i = 0; i < 3; i++) {
// eslint-disable-next-line no-unused-expressions
this.onmessage && this.onmessage({ data: { type: 'LOG', data: i } });
}
// eslint-disable-next-line no-unused-expressions
this.onmessage && this.onmessage({ data: `${data} processed` });
setImmediate(
() =>
this.onmessage && this.onmessage({ data: { type: 'LOG', data: 3 } })
);
});
}
});
const testWorker = createWorker('test');
const task = testWorker.execute('test');
const handler = jest.fn();
task.on('done', handler);
const errorHandler = jest.fn();
task.on('error', errorHandler);
const logHandler = jest.fn();
task.on('LOG', logHandler);
await expect(task.done).resolves.toBe('test processed');
expect(handler).toBeCalledTimes(1);
expect(handler).toBeCalledWith('test processed');
expect(errorHandler).not.toBeCalled();
expect(logHandler).toBeCalledTimes(3);
for (let i = 0; i < 3; i++) {
expect(logHandler.mock.calls[i][0]).toBe(i);
}
});
it('Worker executor should reject task on timeout', async () => {
const terminateHandler = jest.fn();
mockWorker({
postMessage: () => {},
terminate: terminateHandler
});
const testWorker = createWorker('test');
const task = testWorker.execute('test', 0);
const errorHandler = jest.fn();
task.on('error', errorHandler);
await expect(task.done).rejects.toBe('timeout');
expect(errorHandler).toBeCalledTimes(1);
expect(errorHandler.mock.calls[0][0]).toEqual({ message: 'timeout' });
expect(terminateHandler).toBeCalledTimes(1);
});
it('Worker executor should get worker from specified location', async () => {
mockWorker();
const testWorker = createWorker('test', { location: '/other/location/' });
const task = testWorker.execute('test');
await expect(task.done).resolves.toBe('test processed');
expect(global.Worker).toBeCalledTimes(1);
expect(global.Worker).toBeCalledWith('/other/location/test.js');
});