UNPKG

@codecovevienna/gittt-cli

Version:

Tracking time with CLI into a git repository

1,586 lines (1,228 loc) 211 kB
import { assert, expect } from "chai"; import commander, { Command, CommanderStatic } from "commander"; import proxyquire from "proxyquire"; import sinon from "sinon"; import { App } from "../../app"; import { LogHelper } from "../../helper/index"; import { IJiraLink, IJiraPublishResult, IProject, IRecord, IMultipieInputLink, IMultipiePublishResult, IMultipieStoreLink } from "../../interfaces"; import { RECORD_TYPES } from "../../types"; import { emptyHelper } from "../helper"; import { DefaultLogFields } from "simple-git"; LogHelper.DEBUG = true; LogHelper.silence = false; // TODO this needs a complete refactoring due to // massive changes in commander 8 describe.skip("App", function () { before(function () { proxyquire.noCallThru(); }); describe("General", function () { it("should create instance", async function () { const app: App = new App(); expect(app).to.be.instanceOf(App); }); it("should start app", async function () { const parseStub = sinon.spy(); const proxy: any = proxyquire("../../app", { commander: { parse: parseStub, }, }); process.argv = [ "ts-node", "app.ts", "list", ]; const app: App = new proxy.App(); app.start(); assert.isTrue(parseStub.calledOnce); }); it("should start app and show help [unknown command]", async function () { const helpStub = sinon.spy(); const proxy: any = proxyquire("../../app", { commander: { help: helpStub, }, }); process.argv = [ "mocked", "unknownCommand", ]; const app: App = new proxy.App(); app.start(); assert.isTrue(helpStub.calledOnce); }); it("should exit without error", async function () { const exitStub = sinon.stub(process, "exit"); const warnStub = sinon.stub(LogHelper, "warn"); const proxy: any = proxyquire("../../app", {}); const app: App = new proxy.App(); app.exit("Mock", 0); assert.isTrue(exitStub.calledWith(0)); assert.isTrue(warnStub.calledWith("Mock")); exitStub.restore(); warnStub.restore(); }); it("should exit with error", async function () { const exitStub = sinon.stub(process, "exit"); const errorStub = sinon.stub(LogHelper, "error"); const proxy: any = proxyquire("../../app", {}); const app: App = new proxy.App(); app.exit("Mock", 1337); assert.isTrue(exitStub.calledWith(1337)); assert.isTrue(errorStub.calledWith("Mock")); exitStub.restore(); errorStub.restore(); }); }); describe("Setup", function () { it("should setup app", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper }); const app: App = new proxy.App(); sinon.stub(app, "initCommander").resolves(); await app.setup(); }); it("should setup app without config directory", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(false); } mockedHelper.QuestionHelper = class { public static confirmSetup = sinon.stub().resolves(true) } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const app: App = new proxy.App(); sinon.stub(app, "initCommander").resolves(); const initConfigDirStub = sinon.stub(app, "initConfigDir").resolves(); await app.setup(); assert.isTrue(initConfigDirStub.calledOnce); }); it("should exit app due to no setup config directory", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const exitStub = sinon.stub(process, "exit"); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(false); } mockedHelper.QuestionHelper = class { public static confirmSetup = sinon.stub().resolves(false) } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const app: App = new proxy.App(); sinon.stub(app, "initCommander").resolves(); await app.setup(); assert.isTrue(exitStub.calledWith(0)); exitStub.restore(); }); it("should pull repo due to already set up config directory", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const pullStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public configDirExists = sinon.stub().resolves(true); public isConfigFileValid = sinon.stub().resolves(true); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.QuestionHelper = class { public static confirmSetup = sinon.stub().resolves(false) } mockedHelper.GitHelper = class { public pullRepo = pullStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const app: App = new proxy.App(); // Has to be called to have all helper instantiated await app.setup(); await app.initConfigDir(); assert.isTrue(pullStub.calledOnce); }); it("should exit app due to invalid config file", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const exitStub = sinon.stub(process, "exit"); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public configDirExists = sinon.stub().resolves(true) public isConfigFileValid = sinon.stub().resolves(false) } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const app: App = new proxy.App(); // Has to be called to have all helper instantiated await app.setup(); await app.initConfigDir(); assert.isTrue(exitStub.calledWith(1)); exitStub.restore(); }); it("should initialize config directory from scratch", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const initRepoStub = sinon.stub().resolves(); const pullRepoStub = sinon.stub().resolves(); const createDirStub = sinon.stub().resolves(); const initConfigFileStub = sinon.stub().resolves(); const commitChangesStub = sinon.stub().resolves(); const pushChangesStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public configDirExists = sinon.stub().resolves(false) public isConfigFileValid = sinon.stub().resolves(false) public createConfigDir = createDirStub public initConfigFile = initConfigFileStub } mockedHelper.GitHelper = class { public commitChanges = commitChangesStub public initRepo = initRepoStub public pullRepo = pullRepoStub public pushChanges = pushChangesStub } mockedHelper.QuestionHelper = class { public static askGitUrl = sinon.stub().resolves("ssh://git@mocked.git.com/mock/test.git") } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const app: App = new proxy.App(); // Has to be called to have all helper instantiated await app.setup(); await app.initConfigDir(); assert.isTrue(createDirStub.calledOnce); assert.isTrue(initRepoStub.calledOnce); assert.isTrue(pullRepoStub.calledOnce); assert.isTrue(initConfigFileStub.calledOnce); assert.isTrue(commitChangesStub.calledOnce); assert.isTrue(pushChangesStub.calledOnce); }); it("should initialize config directory and pull", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const pullStub = sinon.stub().resolves(); const createDirStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public configDirExists = sinon.stub().resolves(false) public isConfigFileValid = sinon.stub().resolves(true); public createConfigDir = createDirStub } mockedHelper.GitHelper = class { public pullRepo = pullStub } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const app: App = new proxy.App(); // Has to be called to have all helper instantiated await app.setup(); await app.initConfigDir(); assert.isTrue(createDirStub.calledOnce); assert.isTrue(pullStub.calledOnce); }); }); describe("Init", function () { it("should init current git repository", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const initProjectStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ProjectHelper = class { public initProject = initProjectStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.QuestionHelper = class { public static confirmInit = sinon.stub().resolves(true) } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); await mockedApp.initAction(); assert.isTrue(initProjectStub.calledOnce); }) it("should fail to init current git repository [canceled]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const initProjectStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public initProject = initProjectStub; } mockedHelper.QuestionHelper = class { public static confirmInit = sinon.stub().resolves(false) } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit"); await mockedApp.setup(); await mockedApp.initAction(); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }) it("should fail to init current git repository [initProject throws]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const initProjectStub = sinon.stub().throws(new Error("mocked")); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public initProject = initProjectStub; } mockedHelper.QuestionHelper = class { public static confirmInit = sinon.stub().resolves(true) } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit"); await mockedApp.setup(); await mockedApp.initAction(); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }) }) describe("Edit records", function () { it("should edit specific record", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getOrAskForProjectFromGitStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", requiresRoles: true, } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", requiresRoles: true, records: mockedRecords, } as IProject); const commitChangesStub = sinon.stub().resolves(); const saveProjectObjectStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; public saveProjectObject = saveProjectObjectStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.RecordHelper = class { public static filterRecordsByYear = sinon.stub().resolves(mockedRecords) public static filterRecordsByMonth = sinon.stub().resolves(mockedRecords) public static filterRecordsByDay = sinon.stub().resolves(mockedRecords) } mockedHelper.GitHelper = class { public commitChanges = commitChangesStub; } mockedHelper.ProjectHelper = class { public getOrAskForProjectFromGit = getOrAskForProjectFromGitStub; } mockedHelper.QuestionHelper = class { public static askAmount = sinon.stub().resolves(69); public static askDay = sinon.stub().resolves(24); public static askHour = sinon.stub().resolves(13); public static askMessage = sinon.stub().resolves("Mocked message"); public static askMinute = sinon.stub().resolves(37); public static askMonth = sinon.stub().resolves(24); public static askYear = sinon.stub().resolves(2019); public static chooseRecord = sinon.stub().resolves(mockedRecords[0]); public static chooseType = sinon.stub().resolves("Time"); public static chooseRole = sinon.stub().resolves("?"); } mockedHelper.MultipieHelper = class { public getValidRoles = sinon.stub().resolves([{ name: '?', value: '?' }]); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); // Mock arguments array to enable interactive mode process.argv = ["1", "2", "3"]; await mockedApp.editAction(mockedCommand); assert.isTrue(getOrAskForProjectFromGitStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(saveProjectObjectStub.calledOnce); expect(saveProjectObjectStub.args[0][0].records[0].amount).to.eq(69); expect(saveProjectObjectStub.args[0][0].records[0].role).to.eq('?'); expect(saveProjectObjectStub.args[0][0].records[0].message).to.eq("Mocked message"); expect(saveProjectObjectStub.args[0][0].records[0].type).to.eq("Time"); assert.isTrue(commitChangesStub.calledOnce); }); it("should fail to edit specific record [unable to get project from git]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const getProjectByNameStub = sinon.stub().resolves(undefined); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit").returns(); await mockedApp.setup(); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(new Command()); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should fail to edit specific record [unable to get project from filesystem]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const getProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves(undefined); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit").returns(); await mockedApp.setup(); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(new Command()); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should fail to edit specific record [no records]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: [], }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; public getProjectFromGit = getProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit").returns(); await mockedApp.setup(); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(new Command()); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should edit specific record with arguments", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); const commitChangesStub = sinon.stub().resolves(); const saveProjectObjectStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; public saveProjectObject = saveProjectObjectStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.GitHelper = class { public commitChanges = commitChangesStub; } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } mockedHelper.ValidationHelper = class { public static validateNumber = sinon.stub().returns(true); } mockedHelper.MultipieHelper = class { public getValidRoles = sinon.stub().resolves([{ name: '?', value: '?' }]); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const mockedCommand = new Command(); sinon.stub(mockedCommand, "opts").returns({ amount: 69, guid: "mocked-guid", message: "mocked-message", type: RECORD_TYPES.Time, role: '?', }); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); const opts = mockedCommand.opts() assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(saveProjectObjectStub.calledOnce); expect(saveProjectObjectStub.args[0][0].records[0].amount).to.eq(opts.amount); expect(saveProjectObjectStub.args[0][0].records[0].role).to.eq(opts.role); expect(saveProjectObjectStub.args[0][0].records[0].type).to.eq(opts.type); expect(saveProjectObjectStub.args[0][0].records[0].guid).to.eq(opts.guid); expect(saveProjectObjectStub.args[0][0].records[0].message).to.eq(opts.message); assert.isTrue(commitChangesStub.calledOnce); }); it("should fail to edit specific record with arguments [unknown guid]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit").resolves(); await mockedApp.setup(); const mockedCommand = new Command(); sinon.stub(mockedCommand, "opts").returns({ amount: 69, guid: "unknown-guid", type: RECORD_TYPES.Time, }); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should fail to edit specific record with arguments [no guid]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); mockedCommand.amount = 3; mockedCommand.type = RECORD_TYPES.Time; const helpStub = sinon.stub(mockedCommand, "help"); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(helpStub.calledOnce); }); it("should fail to edit specific record with arguments [no amount]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } mockedHelper.ValidationHelper = class { public static validateNumber = sinon.stub().returns(false); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); mockedCommand.guid = "mocked-guid"; mockedCommand.type = RECORD_TYPES.Time; const helpStub = sinon.stub(mockedCommand, "help"); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(helpStub.calledOnce); }); it("should fail to edit specific record with arguments [no type]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); mockedCommand.amount = 420; mockedCommand.guid = "mocked-guid"; const helpStub = sinon.stub(mockedCommand, "help"); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(helpStub.calledOnce); }); it("should fail to edit specific record with arguments [no role]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", requiresRoles: true, } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ValidationHelper = class { public static validateNumber = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); mockedCommand.amount = 420; mockedCommand.guid = "mocked-guid"; mockedCommand.type = "Time"; const helpStub = sinon.stub(mockedCommand, "help"); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(helpStub.calledOnce); }); it("should fail to edit specific record with arguments [wrong role]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", requiresRoles: true, } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ValidationHelper = class { public static validateNumber = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } mockedHelper.MultipieHelper = class { public getValidRoles = sinon.stub().resolves([{ name: '?', value: '?' }]); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); mockedCommand.amount = 420; mockedCommand.guid = "mocked-guid"; mockedCommand.type = "Time"; mockedCommand.role = "Not found"; // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; const exitStub = sinon.stub(process, "exit"); await mockedApp.editAction(mockedCommand); exitStub.restore(); }); it("should fail to edit specific record with arguments [throws]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const getProjectByNameStub = sinon.stub().throws(new Error("Mocked")); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit").resolves(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); // Mock arguments array to disable interactive mode process.argv = ["1", "2", "3", "4"]; await mockedApp.editAction(mockedCommand); assert.isTrue(exitStub.calledOnce); }); }); describe("Remove records", function () { it("should remove specific record", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getOrAskForProjectFromGitStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); const commitChangesStub = sinon.stub().resolves(); const saveProjectObjectStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; public saveProjectObject = saveProjectObjectStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.RecordHelper = class { public static filterRecordsByYear = sinon.stub().resolves(mockedRecords) public static filterRecordsByMonth = sinon.stub().resolves(mockedRecords) public static filterRecordsByDay = sinon.stub().resolves(mockedRecords) } mockedHelper.GitHelper = class { public commitChanges = commitChangesStub; } mockedHelper.ProjectHelper = class { public getOrAskForProjectFromGit = getOrAskForProjectFromGitStub; } mockedHelper.QuestionHelper = class { public static chooseRecord = sinon.stub().resolves(mockedRecords[0]); } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); // Mock arguments array to enable interactive mode process.argv = ["1", "2", "3"]; await mockedApp.removeAction(mockedCommand); assert.isTrue(getOrAskForProjectFromGitStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(saveProjectObjectStub.calledOnce); expect(saveProjectObjectStub.args[0][0].records.length).to.eq(0); assert.isTrue(commitChangesStub.calledOnce); }); it("should fail to remove specific record [unable to get project from git]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const getOrAskForProjectFromGitStub = sinon.stub().throws(new Error("Mocked Error")); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getOrAskForProjectFromGit = getOrAskForProjectFromGitStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit"); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); // Mock arguments array to enable interactive mode process.argv = ["1", "2", "3"]; await mockedApp.removeAction(mockedCommand); assert.isTrue(getOrAskForProjectFromGitStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should fail to remove specific record [unable to get project from filesystem]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const getOrAskForProjectFromGitStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves(undefined); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getOrAskForProjectFromGit = getOrAskForProjectFromGitStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit"); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); // Mock arguments array to enable interactive mode process.argv = ["1", "2", "3"]; await mockedApp.removeAction(mockedCommand); assert.isTrue(getOrAskForProjectFromGitStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should fail to remove specific record [no records]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = []; const getOrAskForProjectFromGitStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.ProjectHelper = class { public getOrAskForProjectFromGit = getOrAskForProjectFromGitStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); const exitStub = sinon.stub(mockedApp, "exit"); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); // Mock arguments array to enable interactive mode process.argv = ["1", "2", "3"]; await mockedApp.removeAction(mockedCommand); assert.isTrue(getOrAskForProjectFromGitStub.calledOnce); assert.isTrue(exitStub.calledOnce); exitStub.restore(); }); it("should remove specific record with arguments", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord, ]; const getProjectByNameStub = sinon.stub().returns({ meta: { host: "test.git.com", port: 443, }, name: "mocked", } as IProject); const findProjectByNameStub = sinon.stub().resolves({ meta: { host: "test.git.com", port: 443, }, name: "mocked", records: mockedRecords, }); const commitChangesStub = sinon.stub().resolves(); const saveProjectObjectStub = sinon.stub().resolves(); mockedHelper.FileHelper = class { public static getHomeDir = sinon.stub().returns("/home/test"); public findProjectByName = findProjectByNameStub; public saveProjectObject = saveProjectObjectStub; } mockedHelper.ConfigHelper = class { public static instance: any; public static getInstance(): any { if (!this.instance) { this.instance = new this() } return this.instance } public isInitialized = sinon.stub().resolves(true); } mockedHelper.GitHelper = class { public commitChanges = commitChangesStub; } mockedHelper.ProjectHelper = class { public getProjectByName = getProjectByNameStub; } const proxy: any = proxyquire("../../app", { "./helper": mockedHelper, }); const mockedApp: App = new proxy.App(); await mockedApp.setup(); const program = new commander.Command(); const mockedCommand: commander.Command = program.createCommand(); mockedCommand.guid = "mocked-guid"; // Mock arguments array to be greater than 3 process.argv = ["1", "2", "3", "4"]; await mockedApp.removeAction(mockedCommand); assert.isTrue(getProjectByNameStub.calledOnce); assert.isTrue(findProjectByNameStub.calledOnce); assert.isTrue(saveProjectObjectStub.calledOnce); expect(saveProjectObjectStub.args[0][0].records.length).to.eq(0); assert.isTrue(commitChangesStub.calledOnce); }); it("should fail to remove specific record with arguments [no guid]", async function () { const mockedHelper: any = Object.assign({}, emptyHelper); const mockedRecords: IRecord[] = [ { amount: 1337, created: 1234, guid: "mocked-guid", type: RECORD_TYPES.Time, } as IRecord,