UNPKG

@applicaster/zapplicaster-cli

Version:

CLI Tool for the zapp app and Quick Brick project

264 lines (215 loc) • 6.16 kB
const { taskRunner } = require("../index"); const logger = require("../../logger"); const welcomeSpy = jest.spyOn(logger, "welcome"); const logSpy = jest.spyOn(logger, "log").mockImplementation(jest.fn()); const errorSpy = jest.spyOn(logger, "error").mockImplementation(jest.fn()); jest.spyOn(console, "log").mockImplementation(jest.fn()); jest.mock("ramda", () => ({ ...jest.requireActual("ramda"), T: jest.fn(), })); const R = require("ramda"); const mock_PREREQUISITES_CHECKER_ERROR = new Error( "error in prerequisites checker" ); const mock_CONFIGURATOR_ERROR = new Error("error in configurator"); const name = "task_name"; const startMessage = "start_message"; const prerequisitesChecker = jest.fn(() => Promise.resolve(true)); const FAIL_prerequisitesChecker = jest.fn(() => Promise.resolve(false)); const THROW_prerequisitesChecker = jest.fn(() => { throw mock_PREREQUISITES_CHECKER_ERROR; }); const configurator = jest.fn(); const FAIL_configurator = jest.fn(() => { throw mock_CONFIGURATOR_ERROR; }); const step1Sstart = "step1_start"; const step1Action = jest.fn(); const step1Error = "step1_error"; const step1Completion = "step1_completion"; const step2Start = "step2_start"; const step2Action = jest.fn(); const step2Error = "step2_error"; const step2Completion = "step2_completion"; const cleanUp = jest.fn(); const steps = [ { start: step1Sstart, run: step1Action, error: step1Error, completion: step1Completion, }, { start: step2Start, run: step2Action, error: step2Error, completion: step2Completion, }, ]; const FAILING_STEP_ERROR = new Error("FAILING_STEP"); const failing_step_with_no_error = { start: "failing step", run: () => { throw FAILING_STEP_ERROR; }, completion: "done", }; const failing_step = { ...failing_step_with_no_error, error: "failing_step_error", }; const task = { name, startMessage, prerequisitesChecker, configurator, steps, cleanUp, }; describe("taskRunner", () => { afterEach(() => { logSpy.mockClear(); errorSpy.mockClear(); }); describe("when all goes well", () => { beforeAll(async () => { await taskRunner(task)({}); }); it("returns a function", () => { expect(taskRunner(task)).toBeFunction(); }); it("invokes the logger's welcome message", () => { expect(welcomeSpy).toHaveBeenCalledWith(name, startMessage); }); it("invokes the prerequisite checker if provided", () => { expect(prerequisitesChecker).toHaveBeenCalled(); }); it("invokes the configurator if provided", () => { expect(configurator).toHaveBeenCalled(); }); it("runs each step", () => { expect(step1Action).toHaveBeenCalled(); expect(step2Action).toHaveBeenCalled(); }); it("it invokes the cleanup function if provided", () => { expect(cleanUp).toHaveBeenCalled(); }); }); describe("when prerequisitesChecker fails", () => { beforeAll(async () => { await taskRunner({ ...task, prerequisitesChecker: FAIL_prerequisitesChecker, })({}); }); afterEach(() => { errorSpy.mockClear(); }); it("invokes the logger error", () => { expect(errorSpy).toHaveBeenCalledWith( "Prerequisites are not satisfied", expect.any(Error) ); }); }); describe("when prerequisitesChecker throws", () => { beforeAll(async () => { await taskRunner({ ...task, prerequisitesChecker: THROW_prerequisitesChecker, })({}); }); afterEach(() => { errorSpy.mockClear(); }); it("invokes the logger error", () => { expect(errorSpy).toHaveBeenCalledWith( "error in prerequisites checker", mock_PREREQUISITES_CHECKER_ERROR ); }); }); describe("when no prerequisites checker is invoked", () => { beforeAll(async () => { await taskRunner({ ...task, prerequisitesChecker: undefined })({}); }); it("uses Ramda's True function", () => { expect(R.T).toHaveBeenCalled(); }); }); describe("when the configurator fails", () => { beforeAll(async () => { await taskRunner({ ...task, configurator: FAIL_configurator })({}); }); afterEach(() => { logSpy.mockClear(); errorSpy.mockClear(); }); it("invokes the logger error", () => { expect(errorSpy).toHaveBeenCalledWith( "error in configurator", mock_CONFIGURATOR_ERROR ); }); }); describe("when using the verbose option", () => { beforeAll(async () => { await taskRunner(task)("", { verbose: true, }); }); afterEach(() => { logSpy.mockClear(); errorSpy.mockClear(); }); it("prints verbose output", () => { expect(logSpy).toHaveBeenCalled(); }); }); describe("when no configurator is provided", () => { beforeAll(async () => { await taskRunner({ ...task, configurator: undefined })({}); }); it("uses the default function ", () => {}); }); describe("when no cleanup is provided", () => { beforeAll(async () => { await taskRunner({ ...task, cleanUp: undefined })({}); }); afterEach(() => { logSpy.mockClear(); }); it("skips the cleanup step", () => { expect(logSpy).not.toHaveBeenCalledWith("cleaning up..."); }); }); describe("when a step fails", () => { beforeAll(async () => { await taskRunner({ ...task, steps: [failing_step] })({}); }); afterEach(() => { errorSpy.mockClear(); }); it("catches the error", () => { expect(errorSpy).toHaveBeenCalledWith( failing_step.error, FAILING_STEP_ERROR ); }); }); describe("when a step fails and has no default error message", () => { beforeAll(async () => { await taskRunner({ ...task, steps: [failing_step_with_no_error] })({}); }); afterEach(() => { errorSpy.mockClear(); }); it("catches the error", () => { expect(errorSpy).toHaveBeenCalledWith( FAILING_STEP_ERROR.message, FAILING_STEP_ERROR ); }); }); });