/* Copyright 2019 the JSDoc Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ 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); }); }); }); });