const Emittery = require('emittery'); const Task = require('../../../lib/task'); const ARGUMENT_ERROR = 'ArgumentError'; describe('@jsdoc/task-runner/lib/task', () => { it('is a function', () => { expect(Task).toBeFunction(); }); it('inherits from emittery', () => { expect(new Task() instanceof Emittery).toBeTrue(); }); it('can be constructed with no arguments', () => { function factory() { return new Task(); } expect(factory).not.toThrow(); }); it('uses the provided name', () => { const task = new Task({ name: 'foo' }); expect(task.name).toBe('foo'); }); it('uses the provided function', () => { const func = () => Promise.resolve(); const task = new Task({ func }); expect(task.func).toBe(func); }); describe('dependsOn', () => { it('accepts an array of task names as dependencies', () => { const dependsOn = ['bar', 'baz']; const task = new Task({ name: 'foo', func: () => Promise.resolve(), dependsOn, }); expect(task.dependsOn).toEqual(dependsOn); }); it('accepts a single task name as a dependency', () => { const task = new Task({ name: 'foo', func: () => Promise.resolve(), dependsOn: 'bar', }); expect(task.dependsOn).toEqual(['bar']); }); it('fails with non-string, non-array dependencies', () => { function factory() { return new Task({ name: 'foo', func: () => Promise.resolve(), dependsOn: 7, }); } expect(factory).toThrowErrorOfType(ARGUMENT_ERROR); }); it('fails with non-string arrays of dependencies', () => { function factory() { return new Task({ name: 'foo', func: () => Promise.resolve(), dependsOn: [7], }); } expect(factory).toThrowErrorOfType(ARGUMENT_ERROR); }); }); it('uses the provided dependencies', () => { const dependsOn = ['foo', 'bar']; const task = new Task({ dependsOn }); expect(task.dependsOn).toEqual(dependsOn); }); describe('run', () => { it('requires a name', async () => { let error; async function start() { const task = new Task({ func: () => Promise.resolve(), }); await task.run(); } try { await start(); } catch (e) { error = e; } expect(error).toBeDefined(); }); it('requires a function', async () => { let error; async function run() { const task = new Task({ name: 'foo', }); await task.run(); } try { await run(); } catch (e) { error = e; } expect(error).toBeDefined(); }); it('accepts a context object', async () => { const context = {}; const task = new Task({ name: 'foo', func: (c) => { c.foo = 'bar'; return Promise.resolve(); }, }); await task.run(context); expect(context.foo).toBe('bar'); }); describe('events', () => { it('emits a `start` event', async () => { let event; const task = new Task({ name: 'foo', func: () => Promise.resolve(), }); task.on('start', (e) => { event = e; }); await task.run(); expect(event).toBe(task); }); it('emits an `end` event', async () => { let event; const task = new Task({ name: 'foo', func: () => Promise.resolve(), }); task.on('end', (e) => { event = e; }); await task.run(); expect(event).toBe(task); }); it('emits an `error` event if necessary', async () => { let error = new Error('oh no!'); let event; const task = new Task({ name: 'foo', func: () => Promise.reject(error), }); task.on('error', (e) => { event = e; }); try { await task.run(); } catch (e) { // Expected behavior. } expect(event.error).toBe(error); expect(event.task).toBe(task); }); }); }); });