UNPKG

cabdriver

Version:

Helps you to fill in your hours with taxi

483 lines (452 loc) 17.3 kB
/*global describe it afterEach*/ var Sinon = require('sinon'); var stdMocks = require('std-mocks'); var MockFs = require('mock-fs'); var expect = require('chai').expect; var path = require('path'); var GoogleAuth = require('../lib/auth/google_auth'); var GoogleCalendar = require('../lib/source/calendar'); var GoogleMail = require('../lib/source/mail'); var FetchCli = require('../cli/fetch'); describe('CLI Fetch', function() { afterEach(function () { Sinon.restore(); stdMocks.flush(); stdMocks.restore(); MockFs.restore(); }); describe('querySources', function() { describe('Calendar option', function() { it('should call Google Calendar', function(done) { //setup stubs var expectedConfig = { 'defaults': { 'calendar': 'primary', 'git': '/home/testuser', 'hours': true, 'mail': 'primary' }, 'mail': { 'exclude': ['Notification', 'Newsletter'], 'query': '-to:team@liip.ch' } }; var expectedMsg = { 'project': 'xxx', 'time': '1', 'text': 'Test Entry', 'timestamp': 0, 'comment': false, 'type': 'calendar' }; var getEntriesStub = Sinon.stub().resolves([expectedMsg]); var sourceStub = function() { return { 'getEntries': getEntriesStub }; }; var sourceConfig = { calendar: { source: sourceStub, auth: GoogleAuth }, }; var options = { 'date': 'today', 'calendar': 'primary', }; var test_config = path.resolve(__dirname, 'test_mail.yml'); var cli = new FetchCli(options, test_config, sourceConfig); cli.querySources(function(err, results) { try { expect(err).to.not.exist; expect(results).to.be.deep.equal([expectedMsg]); expect(getEntriesStub.calledWith(expectedConfig)).to.be.true; done(); } catch (err) { done(err); } }); }); it('should return an empty list if argument is not set', function(done) { //setup stubs var options = { 'date': 'today' }; var cli = new FetchCli(options, null, {}); cli.querySources(function(err, results) { try { expect(err).to.not.exist; expect(results).to.be.deep.equal([]); done(); } catch (err) { done(err); } }); }); }); describe('Failing source', function() { it('should not fail everything, print error msg on stderr', function(done) { //setup stubs stdMocks.use(); var sourceStub = function() { return { 'getEntries': Sinon.stub().rejects('Could not fetch mails') }; }; var options = { 'date': 'today', 'mail': true }; var sourceConfig = { mail: { source: sourceStub, auth: GoogleAuth }, }; var cli = new FetchCli(options, null, sourceConfig); cli.querySources(function(err, results) { try { expect(err).to.not.exist; expect(results).to.deep.equal([]); var output = stdMocks.flush().stderr; stdMocks.restore(); expect(output).to.include( 'mail source failed: Could not fetch mails\n' ); done(); } catch (err) { done(err); } }); }); }); }); describe('postProcess', function() { it('should map entries to defined projects', function() { var test_config = path.resolve(__dirname, 'test_mapping.yml'); var cli = new FetchCli(null, test_config); var msgs = [ { 'project': 'xxx', 'time': '1', 'text': 'Team Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'important internal stuff', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'company', 'time': '2', 'text': 'Something important', 'timestamp': 123, 'comment': false, 'type': 'git' } ]; var result = cli.postProcess(msgs); expect(result[0].project).to.equal('_internal'); expect(result[1].project).to.equal('xxx'); expect(result[2].project).to.equal('_internal'); expect(result[3].project).to.equal('_internal'); }); it('should map entries to first defined project', function() { var test_config = path.resolve(__dirname, 'test_mapping.yml'); var cli = new FetchCli(null, test_config); var msgs = [ { 'project': 'open-source', 'time': '1', 'text': 'Ticket 1', 'timestamp': 123, 'comment': false, 'type': 'jira' } ]; var result = cli.postProcess(msgs); expect(result[0].project).to.equal('acme_dev'); }); it('should not change any entries if no mapping is defined', function() { var test_config = path.resolve(__dirname, 'test_cabdriver.yml'); var cli = new FetchCli(null, test_config); var msgs = [ { 'project': 'xxx', 'time': '1', 'text': 'Team Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'important internal stuff', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'company', 'time': '2', 'text': 'Something important', 'timestamp': 123, 'comment': false, 'type': 'git' } ]; var result = cli.postProcess(msgs); expect(result).to.deep.equal(msgs); }); it('should comment out entries mapped to `__comment__`', function() { var test_config = path.resolve(__dirname, 'test_mapping.yml'); var cli = new FetchCli(null, test_config); var msgs = [ { 'project': 'xxx', 'time': '1', 'text': 'Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Lunch', 'timestamp': 123, 'comment': false, 'type': 'calendar' } ]; var result = cli.postProcess(msgs); expect(result[0].comment).to.be.false; expect(result[1].comment).to.be.true; }); it('should remove entries mapped to `__remove__`', function() { var test_config = path.resolve(__dirname, 'test_mapping.yml'); var cli = new FetchCli(null, test_config); var msgs = [ { 'project': 'xxx', 'time': '1', 'text': 'Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Hours!', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Important Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' } ]; var result = cli.postProcess(msgs); expect(result.length).to.equal(2); }); it('should comment out entries mapped to `__remove__` when using --verbose', function() { var test_config = path.resolve(__dirname, 'test_mapping.yml'); stdMocks.use(); var cli = new FetchCli({'verbose': true}, test_config); stdMocks.restore(); var msgs = [ { 'project': 'xxx', 'time': '1', 'text': 'Meeting', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Hours!', 'timestamp': 123, 'comment': false, 'type': 'calendar' }, { 'project': 'xxx', 'time': '1', 'text': 'Hours!', 'timestamp': 123, 'comment': false, 'type': 'calendar' } ]; var result = cli.postProcess(msgs); expect(result.length).to.equal(3); expect(result[1].comment).to.be.true; expect(result[1].text).to.include('[REMOVED]'); }); }); describe('printResults', function() { it('should print a correct calendar taxi entry', function() { //setup mocks stdMocks.use(); var msg = { 'project': 'xxx', 'time': '1', 'text': 'Test Entry', 'timestamp': 123, 'comment': false, 'type': 'calendar' }; var cli = new FetchCli(null, null, null); cli.printResults([msg]); var output = stdMocks.flush().stdout; stdMocks.restore(); var expectedOutput = [ '\n', '01/01/1970 # Thursday\n', '\n', '# calendar', ' (Total: 1.00h)', '\n', '#------------------\n', 'xxx 1 Test Entry\n' ]; expect(output).to.deep.equal(expectedOutput); }); }); describe('sourcesInOptions', function() { it('should find sources in options', function() { var sources = {'test': '', 'jira': ''}; var cli = new FetchCli(null, null, sources); var optionsWithOneSource = {'test': true, 'hallo': 'velo'}; expect(cli.sourcesInOptions(optionsWithOneSource)).to.be.true; var optionsWithMultipleSources = {'test': 'blubb', 'hallo': 'velo', 'jira': true}; expect(cli.sourcesInOptions(optionsWithMultipleSources)).to.be.true; var optionsWithoutSource = {'hallo': 'velo', 'bla': 'blubb'}; expect(cli.sourcesInOptions(optionsWithoutSource)).to.be.false; }); it('should not find any sources if there are none', function() { var sources = {}; var cli = new FetchCli(null, null, sources); var options = {'test': true, 'hallo': 'velo'}; expect(cli.sourcesInOptions(options)).to.be.false; }); }); describe('updateOptions', function() { it('should combine config values with cli arguments', function() { //setup mocks var ymlContent = 'defaults:\n' + ' jira: false\n' + ' slack: true\n' + ' logbot: false\n' + ' calendar: \'primary\'\n' + ' zebra: false\n' + ' git: false\n' + ' gitlab: true\n' + ' github: true\n' + ' mail: false\n' + ' pie: false\n' + ' hours: false\n' + ' number: 1000'; MockFs({ '/home/testuser/.cabdriver/cabdriver.yml': ymlContent }); var opts = { 'date': '02.12.2017', 'jira': true, 'verbose': true, 'hours': true }; stdMocks.use(); var cli = new FetchCli(opts, '/home/testuser/.cabdriver/cabdriver.yml'); var output = stdMocks.flush().stdout; var err = stdMocks.flush().stderr; stdMocks.restore(); var expectedOutput = [ 'Start date: 02.12.2017\n', 'End date: 02.12.2017\n', 'Calendar: primary\n', 'Mail: false\n', 'Slack: true\n', 'Logbot: false\n', 'Jira: true\n', 'Zebra: false\n', 'Git: false\n', 'Github: true\n', 'Gitlab: true\n', 'Pie chart: false\n', 'Hours: true\n', 'Count: 1000\n', 'Config: undefined\n', ]; expect(output).to.deep.equal(expectedOutput); }); }); describe('loadConfig', function() { it('should load a provided config file', function() { var cli = new FetchCli(); //setup mocks var ymlContent = 'defaults:\n' + ' jira: true\n' + ' slack: true\n' + ' calendar: primary\n' + ' zebra: false\n' + ' logbot: true\n' + ' git: /home/testuser\n' + ' hours: true'; MockFs({ '/home/testuser/.cabdriver/cabdriver.yml': ymlContent }); var config = cli.loadConfig('/home/testuser/.cabdriver/cabdriver.yml'); expect(config).to.deep.equal({ 'defaults': { 'jira': true, 'slack': true, 'calendar': 'primary', 'zebra': false, 'logbot': true, 'git': '/home/testuser', 'hours': true } }); }); it('should default to empty config on error', function() { //setup mocks MockFs({ '/home/testuser/.cabdriver/cabdriver.yml': 'test: badconfig' }); var cli = new FetchCli(); stdMocks.use(); var config = cli.loadConfig('/home/testuser/.cabdriver/cabdriver.yml'); expect(config).to.deep.equal({'defaults': {}}); var output = stdMocks.flush().stderr; stdMocks.restore(); expect(output).to.include('Config file has no \'defaults\' key\n'); }); }); });