UNPKG

restmine

Version:

link git with redmine to automatically add refs to commits, log time on tickets...

676 lines (555 loc) 20.6 kB
'use strict'; const chai = require('chai'); const expect = chai.expect; const sinon = require('sinon'); const sinonChai = require("sinon-chai"); chai.use(sinonChai); const Cli = require('../lib/cli'); describe('Cli', () => { describe('isIssueBranch()', () => { let cli; before(() => { cli = new Cli(); }); it('should return the ticket id', () => { expect(cli.isIssueBranch('iss1234')).to.deep.equal({ type: 'iss', id: '1234' }); expect(cli.isIssueBranch('iss1')).to.deep.equal({ type: 'iss', id: '1' }); expect(cli.isIssueBranch('iss3344')).to.deep.equal({ type: 'iss', id: '3344' }); expect(cli.isIssueBranch('org3355')).to.deep.equal({ type: 'org', id: '3355' }); expect(cli.isIssueBranch('org1')).to.deep.equal({ type: 'org', id: '1' }); }); it('should return false', () => { expect(cli.isIssueBranch('test')).to.be.false; expect(cli.isIssueBranch('hier')).to.be.false; expect(cli.isIssueBranch('')).to.be.false; expect(cli.isIssueBranch('test')).to.be.false; expect(cli.isIssueBranch('hier')).to.be.false; expect(cli.isIssueBranch('iss')).to.be.false; // expect(cli.isIssueBranch('1234')).to.be.false; }); }); describe('logTime()', () => { let cli; const api = { logTime: function () {} }; before(() => { sinon.stub(api, 'logTime').returns(Promise.resolve('OK')); cli = new Cli(api, {}, {}, 2); }); after(() => { api.logTime.restore(); }); it('should call api.logTime()', () => { return cli .logTime(33, 4.5, 7) .then(_ => { expect(_).to.equal('OK'); expect(api.logTime).to.have.been.calledWith(33, 4.5, 7); }); }); }); describe('getTicket()', () => { let cli; const api = { getTicket: function () {} }; before(() => { sinon.stub(api, 'getTicket').returns(Promise.resolve('{ "issue": {} }')); cli = new Cli(api, {}, {}, 22); sinon.stub(cli, 'printTicket').returns(''); }); after(() => { cli.printTicket.restore(); api.getTicket.restore(); }); it('should call api.getTicket()', () => { return cli .getTicket(234) .then(_ => { expect(api.getTicket).to.have.been.calledWith(234); }); }); }); describe('getTimeDelta()', () => { let cli; before(() => { cli = new Cli(); }); it('should return hours in decimal', () => { const oneHour = 60 * 60 * 1000; expect(cli.getTimeDelta(0, 2 * oneHour)).to.equal(2); expect(cli.getTimeDelta(0, 0.5 * oneHour)).to.equal(0.5); expect(cli.getTimeDelta(0, 0.25 * oneHour)).to.equal(0.25); expect(cli.getTimeDelta(0.5 * oneHour, 3 * oneHour)).to.equal(2.5); }); }); describe('getCheckoutTime()', () => { const reflog = '4554b66 (hier) HEAD@{2018-03-28T21:01:42+02:00}: checkout: moving from master to test'; const git = { reflog: function () {} }; let cli before(() => { sinon.stub(git, 'reflog').returns(reflog); cli = new Cli({}, git, {}, 1); }); after(() => { git.reflog.restore(); }); it('should call git.reflog()', () => { cli.getCheckoutTime('hier'); expect(git.reflog).to.have.been.calledWith('to hier'); }); it('should return ISO 8601', () => { expect(cli.getCheckoutTime('test')).to.equal('2018-03-28T21:01:42+02:00'); }); }); describe('enterIssueBranch()', () => { let api = { getTicket: function () {} }; let cli; const testTicket = { id: 12 }; beforeEach(() => { sinon.stub(api, 'getTicket').returns(Promise.resolve(testTicket)); cli = new Cli(api, {}, {}, 1); sinon.stub(cli, 'printTicket').returns('halo') sinon.stub(cli, 'takeOver'); }); afterEach(() => { api.getTicket.restore(); cli.printTicket.restore(); cli.takeOver.restore(); }); it('should call api.getTicket()', () => { return cli .enterIssueBranch({ id: 55 }) .then(() => { expect(api.getTicket).to.have.been.calledWith(55); }); }); it('should call printTicket()', () => { return cli .enterIssueBranch({ id: 55 }) .then(() => { expect(cli.printTicket).to.have.been.calledWith({ id: 12 }); }); }); it('should call takeOver()', () => { return cli .enterIssueBranch({ id: 55 }) .then(() => { expect(cli.takeOver).to.have.been.calledWith({ id: 55 }, 'halo'); }); }); }); describe('formatProjects()', () => { let cli; const branchName = 'test'; const env = Object.assign({ autoLogTime: true, columns: 59 }, process.env); const issue = { id: 22 }; before(() => { cli = new Cli({}, {}, env, 1); }); it('should return a formated List of projects', () => { const projects = [ { id: '1', name: 'Test', description: 'Das Test-Projekt' }, { id: '12345', name: 'Zweites Projekt', description: 'Eine etwas längere Beschreibung die abgeschnitten wird.' } ]; const result = cli.formatProjects(projects); expect(result).to.eql(' 1 │ Test │ Das Test-Projekt\n 12345 │ Zweites Projekt │ Eine etwas längere Beschreibung'); }); }); describe('leaveIssueBranch()', () => { let cli; const branchName = 'test'; const env = Object.assign({ autoLogTime: true }, process.env); const issue = { id: 22 }; before(() => { cli = new Cli({}, {}, env, 1); sinon.stub(cli, 'getCheckoutTime').returns('2018-01-10T10:00:00.000Z'); sinon.stub(cli, 'getActivityId').returns(10); sinon.stub(cli, 'logTime'); sinon.stub(cli, 'getTimeDelta').returns(3); }); it('should call cli.getCheckoutTime()', () => { cli.leaveIssueBranch(issue, branchName); expect(cli.getCheckoutTime).to.have.been.calledWith('test'); }); it('should call cli.getTimeDelta()', () => { cli.leaveIssueBranch(issue, branchName); expect(cli.getTimeDelta).to.have.been.calledWith(1515578400000); }); it('should call cli.logTime()', () => { cli.leaveIssueBranch(issue, branchName); expect(cli.logTime).to.have.been.calledWith(22, '3.00', 10); }); describe('timeDelta == 0', () => { before(() => { cli.getTimeDelta.returns(0); cli.logTime.reset(); }); it('should not call cli.logTime()', () => { cli.leaveIssueBranch(issue, branchName); expect(cli.logTime).not.to.have.been.called; }); }); }); describe('info()', () => { let cli; const git = { currentBranchName: () => {} }; before(() => { sinon.stub(git, 'currentBranchName').returns('iss1234'); cli = new Cli({}, git, {}, 4); sinon.stub(cli, 'getTicket').returns(Promise.resolve('OK')); sinon.stub(cli, 'isIssueBranch'); }); describe('issueBranch', () => { before(() => { cli.isIssueBranch.returns({ id: 44, type: 'iss' }); }); after(() => { cli.getTicket.reset(); }); it('should call getTicket()', () => { return cli.info() .then(() => { expect(cli.getTicket).to.have.been.calledWith(44); }); }); }); describe('!issueBranch', () => { before(() => { cli.isIssueBranch.returns(false); }); it('should not call getTicket()', () => { expect( cli.info()).to.be.an('undefined'); expect(cli.getTicket).not.to.have.been.called; }); }); }); describe('tableSpecs()', () => { const cli = new Cli({}, {}, {}, {}); const testissues = [ { id: 1234, priority: { name: 'Hoch' }, tracker: { name: 'Fehler' }, status: { name: 'In Bearb.' }, subject: 'Das ist ein Test' }, { id: 13234, priority: { name: 'sehr Hoch' }, tracker: { name: 'schwerer Fehler' }, status: { name: 'offen' }, subject: 'Alles kaputt' } ]; it('should return an array', () => { expect(cli.tableSpecs([])).to.be.an('array'); }); it('should return an array with column specs', () => { const result = cli.tableSpecs(testissues); expect(result[0]).to.eql(5); // id expect(result[1]).to.eql(9); // priority expect(result[2]).to.eql(15); // tracker expect(result[3]).to.eql(9); // status expect(result[4]).to.eql(16); // subject }); }); describe('pad()', () => { const cli = new Cli({}, {}, {}, {}); it('should fill the string with spaces', () => { expect(cli.pad('Hallo', 10)).to.eql('Hallo '); expect(cli.pad('Hier', 4)).to.eql('Hier'); expect(cli.pad('Hier', 3)).to.eql('Hie'); expect(cli.pad('Hier ist ein Test', 4)).to.eql('Hier'); }); }); describe('parseLogTimeArgs()', () => { let cli; const config = { user_id: 2, category_id: 3, edit_id: 4, activity: { asd: 12, iss: 33 } }; const api = {}; const git = { currentBranchName: () => {} }; const fs = {}; before(() => { cli = new Cli(api, git, config, fs); sinon.stub(git, 'currentBranchName'); }); describe('not on an issue-branch', () => { beforeEach(() => { git.currentBranchName.reset(); git.currentBranchName.returns('master'); }); describe('issue_id', () => { it('should be the given id', () => { expect(cli.parseLogTimeArgs(['0:30', '1234']).issue_id).to.equal('1234'); expect(cli.parseLogTimeArgs(['456', '0:30', '1234']).issue_id).to.equal('1234'); expect(cli.parseLogTimeArgs(['456', '0:30']).issue_id).to.equal('456'); expect(cli.parseLogTimeArgs(['45', '0:30']).issue_id).to.equal('45'); expect(cli.parseLogTimeArgs(['iss45', '0:30']).issue_id).to.equal('45'); expect(cli.parseLogTimeArgs(['iss45', '0:30']).activity_id).to.equal(33); expect(cli.parseLogTimeArgs(['asd45', '0:30']).activity_id).to.equal(12); }); it('should throw', () => { expect(() => cli.parseLogTimeArgs(['0:30'])).to.throw('not on a iss-branch and no issue-id given?'); }); }); }); describe('on an issue-branch', () => { beforeEach(() => { git.currentBranchName.reset(); git.currentBranchName.returns('iss5677'); }); it('should return a timeDef-object', () => { const timeDef = cli.parseLogTimeArgs(['4:00']); expect(timeDef).to.have.all.keys('issue_id', 'hours', 'activity_id', 'spent_on'); }); describe('issue_id', () => { it('should be the given id', () => { expect(cli.parseLogTimeArgs(['0:30', '1234']).issue_id).to.equal('1234'); expect(cli.parseLogTimeArgs(['456', '0:30', '1234']).issue_id).to.equal('1234'); expect(cli.parseLogTimeArgs(['456', '0:30']).issue_id).to.equal('456'); expect(cli.parseLogTimeArgs(['45', '0:30']).issue_id).to.equal('45'); expect(cli.parseLogTimeArgs(['0:30']).issue_id).to.equal('5677'); }); }); describe('comments', () => { it('should take everything else as comments', () => { expect(cli.parseLogTimeArgs(['1:00', 'Das ist ein Kommentar']).comments).to.equal('Das ist ein Kommentar'); }); }); describe('spent_on', () => { it('should be today', () => { const now = new Date().toISOString().split('T')[0]; const timeDef = cli.parseLogTimeArgs(['3:00']); expect(timeDef.spent_on).to.equal(now); }); it('should be the given date', () => { expect(cli.parseLogTimeArgs(['2018-10-20', '2:30']).spent_on).to.equal('2018-10-20'); expect(cli.parseLogTimeArgs(['a', 'b', '2018-10-20', 'v', '2:30']).spent_on).to.equal('2018-10-20'); expect(cli.parseLogTimeArgs(['a', 'b', '2018-10-20', '2018-10-21', '2:30']).spent_on).to.equal('2018-10-21'); expect(cli.parseLogTimeArgs(['2018-10-21', 'asd', '2:30']).spent_on).to.equal('2018-10-21'); expect(cli.parseLogTimeArgs(['2018-10-21', '2018', '2:30']).spent_on).to.equal('2018-10-21'); expect(cli.parseLogTimeArgs(['2018-10-21', '2018-10-2', '2:30']).spent_on).to.equal('2018-10-21'); }); }); describe('hours', () => { it('should be the given hours in decimal', () => { expect(cli.parseLogTimeArgs(['2:30']).hours).to.equal('2.50'); expect(cli.parseLogTimeArgs([':30']).hours).to.equal('0.50'); expect(cli.parseLogTimeArgs([':25']).hours).to.equal('0.42'); expect(cli.parseLogTimeArgs(['3:00']).hours).to.equal('3.00'); expect(() => cli.parseLogTimeArgs([])).to.throw('no time given'); expect(() => cli.parseLogTimeArgs([':00'])).to.throw('no time given?'); expect(() => cli.parseLogTimeArgs([':0'])).to.throw('no time given?'); expect(() => cli.parseLogTimeArgs(['0:00'])).to.throw('no time given?'); expect(() => cli.parseLogTimeArgs(['100:00'])).to.throw('no time given?'); expect(() => cli.parseLogTimeArgs(['10:200'])).to.throw('no time given?'); }); }); describe('activity_id', () => { it('should use default (iss) activity_id', () => { expect(cli.parseLogTimeArgs(['1:00']).activity_id).to.equal(33); }); it('should be the id of the given activity-code', () => { expect(cli.parseLogTimeArgs(['iss', '1:00']).activity_id).to.equal(33); expect(cli.parseLogTimeArgs(['asd', '1:00']).activity_id).to.equal(12); expect(() => cli.parseLogTimeArgs(['tst', ':00'])).to.throw('unknown activity tst'); }); }); describe('combined parameters', () => { const timedef = { spent_on: '2018-10-20', hours: '2.75', activity_id: 33, issue_id: '3344' }; it('should identify all parameter', () => { expect(cli.parseLogTimeArgs(['iss', '2:45', '2018-10-20', '3344'])).to.eql(timedef); expect(cli.parseLogTimeArgs(['2:45', 'iss', '2018-10-20', '3344'])).to.eql(timedef); expect(cli.parseLogTimeArgs(['3344', '2:45', 'iss', '2018-10-20'])).to.eql(timedef); expect(cli.parseLogTimeArgs(['iss', '3344', '2:45', '2018-10-20'])).to.eql(timedef); expect(cli.parseLogTimeArgs(['2018-10-20', '3344', '2:45', 'iss'])).to.eql(timedef); expect(cli.parseLogTimeArgs(['Kommentar', '2018-10-20', '3344', '2:45', 'iss'])).to.eql({ spent_on: '2018-10-20', hours: '2.75', activity_id: 33, issue_id: '3344', comments: 'Kommentar' }); expect(cli.parseLogTimeArgs(['2018-10-20', '3344', 'Kommentar hier', '2:45', 'iss'])).to.eql({ spent_on: '2018-10-20', hours: '2.75', activity_id: 33, issue_id: '3344', comments: 'Kommentar hier' }); expect(cli.parseLogTimeArgs(['iss', '2:45', '2018-10-20'])).to.eql({ spent_on: '2018-10-20', hours: '2.75', activity_id: 33, issue_id: '5677' }); }); }); }); }); describe('logTimeCli()', () => { let cli; const timeDef = { spent_on: '2018-01-02', hours: '3:15', issue_id: '4536', activity_id: 12 }; const config = { user_id: 2, category_id: 3, edit_id: 4, activity: { asd: 12, iss: 33 } }; const api = {}; const git = {}; const fs = {}; before(() => { cli = new Cli(api, git, config, fs); sinon.stub(cli, 'parseLogTimeArgs'); sinon.stub(cli, 'logTime'); }); beforeEach(() => { cli.parseLogTimeArgs.reset(); cli.parseLogTimeArgs.returns(timeDef); cli.logTimeCli('hier'); }); it('should call parseLogTimeArgs()', () => { expect(cli.parseLogTimeArgs).to.have.been.calledWith('hier'); }); it('should call api.logTime()', () => { expect(cli.logTime).to.have.been.calledWith('4536', '3:15', 12, '2018-01-02'); }); }); describe('takeOver()', () => { let cli; const config = { user_id: 2, category_id: 3, edit_id: 4 }; const api = { updateTicket: () => {} }; const git = {}; const fs = {}; before(() => { sinon.stub(api, 'updateTicket'); cli = new Cli(api, git, config, fs); }); beforeEach(() => { api.updateTicket.reset(); }); describe('ticket-type == iss', () => { const handle = { type: 'iss' }; it('should set assigned_to', () => { const issue = { id: 55, status: { id: 4 }, category: { id: 3 } }; cli.takeOver(handle, issue); expect(api.updateTicket).to.have.been.calledWith(55, { issue: { assigned_to_id: 2 } }); }); it('should set category_id', () => { const issue = { id: 55, status: { id: 4 }, assigned_to: { id: 2 } }; cli.takeOver(handle, issue); expect(api.updateTicket).to.have.been.calledWith(55, { issue: { category_id: 3 } }); }); it('should set status_id', () => { const issue = { id: 55, status: { id: 1234 }, assigned_to: { id: 2 }, category: { id: 3 } }; cli.takeOver(handle, issue); expect(api.updateTicket).to.have.been.calledWith(55, { issue: { status_id: 4 } }); }); }); describe('ticket-type != iss', () => { const handle = {type: 'asd'}; it('should do nothing', () => { const issue = { id: 55, status: { id: 4 }, category: { id: 3 } }; cli.takeOver(handle, issue); expect(api.updateTicket).not.to.have.been.called; }); it('should do nothing', () => { const issue = { id: 55, status: { id: 4 }, assigned_to: { id: 2 } }; cli.takeOver(handle, issue); expect(api.updateTicket).not.to.have.been.called; }); it('should do nothing', () => { const issue = { id: 55, status: { id: 1234 }, assigned_to: { id: 2 }, category: { id: 3 } }; cli.takeOver(handle, issue); expect(api.updateTicket).not.to.have.been.called; }); }); }); describe('tabular()', () => { let cli; const fs = { appendFileSync: () => {} }; const git = { currentBranchName: () => {} }; before(() => { cli = new Cli({}, git, {}, fs, 1); }); it('should return aligned collumns', () => { const issues = [ { id: 15, subject: 'Das Subject', priority: { name: 'prio1' }, tracker: { name: 'trac1' }, status: { name: 'stat16' } }, { id: 315, subject: 'Das andere Subject', priority: { name: 'prio2' }, tracker: { name: 'trac51' }, status: { name: 'stat1' } }, ]; const specs = [ 3, 5, 6, 6 ]; let result = cli.tabular(issues[0], specs); expect(result).to.equal('15 | prio1 | trac1 | stat16 | \u001b[32mDas Subject\u001b[39m'); result = cli.tabular(issues[1], specs); expect(result).to.equal('315 | prio2 | trac51 | stat1 | \u001b[32mDas andere Subject\u001b[39m'); }); }); describe('commit_msg()', () => { let cli; const fs = { appendFileSync: () => {} }; const git = { currentBranchName: () => {} }; before(() => { sinon.stub(fs, 'appendFileSync'); sinon.stub(git, 'currentBranchName'); cli = new Cli({}, git, {}, fs, 1); sinon.stub(cli, 'isIssueBranch'); }); afterEach(() => { cli.isIssueBranch.reset(); git.currentBranchName.reset(); fs.appendFileSync.reset(); }); it('should call git.currentBranchName()', () => { cli.commit_msg(); expect(git.currentBranchName).to.have.been.called; }); it('should call isIssueBranch()', () => { git.currentBranchName.returns('hier'); cli.commit_msg(); expect(cli.isIssueBranch).to.have.been.calledWith('hier'); }); it('should call fs.appendFileSync()', () => { cli.isIssueBranch.returns({ id: 34 }) cli.commit_msg('dateiname'); expect(fs.appendFileSync).to.have.been.calledWith('dateiname', '\nrefs #34'); }); it('should not call fs.appendFileSync()', () => { cli.isIssueBranch.returns(null); cli.commit_msg('dateiname'); expect(fs.appendFileSync).not.to.have.been.called; }); }); });