diff --git a/.gitignore b/.gitignore index 63248c7..1c0d2cd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules/ switchmon-*.tgz coverage +.lvimrc diff --git a/cli.js b/cli.js index d71c69b..7dcddc3 100755 --- a/cli.js +++ b/cli.js @@ -16,20 +16,17 @@ function connectionStatus(device) { if (argv.help || argv.h) { console.log(usage); - process.exit(0); -} - -const devices = swm.getDevices(); - -if (argv.list || argv.l) { - devices - .then(devices => { - console.log('Detected devices:\n'); - Object.keys(devices) - .sort(key => !devices[key].connected) - .forEach(key => console.log(key + ':', connectionStatus(devices[key]))); - process.exit(0); - }); + return; +} else if (argv.list || argv.l) { + const devices = swm.getDevices((err, devices) => { + if (err) { + throw new Error(err); + } + console.log('Detected devices:\n'); + Object.keys(devices) + .sort(key => !devices[key].connected) + .forEach(key => console.log(key + ':', connectionStatus(devices[key]))); + }); } else { let selectedMonitors = argv._; @@ -42,14 +39,14 @@ if (argv.list || argv.l) { console.log('Using profile', profile); } - console.log('Switching on', selectedMonitors); + console.log('Switching on', selectedMonitors.length ? selectedMonitors : 'all connected monitors'); - devices - .then(swm.generateXrandrOptions.bind(null, selectedMonitors)) - .then(swm.switchDevices) - .then(swm.executePostCmd.bind(null, postCmd)) - .catch(err => { - console.error(err); - process.exit(2); - }); + swm.getDevices((err, devices) => { + if (err) { + throw new Error(err); + } + const xrandrOptions = swm.generateXrandrOptions(selectedMonitors, devices); + swm.switchDevices(xrandrOptions); + swm.executePostCmd(postCmd); + }); } diff --git a/swm.js b/swm.js index 7a3bc1a..56940d4 100644 --- a/swm.js +++ b/swm.js @@ -3,28 +3,20 @@ const xrandrParse = require('xrandr-parse'); const exec = require('child_process').exec; -function executeCmd(cmd) { - return new Promise((resolve, reject) => { - exec(cmd, (err, stdout, stderr) => { - if (err || stderr) { - reject(err); - return; - } - resolve(stdout); - }); - }); +function executeCmd(cmd, callback) { + exec(cmd, callback); } -function getDevices() { - return executeCmd('xrandr').then(stdout => xrandrParse(stdout)); +function getDevices(callback) { + executeCmd('xrandr', (err, stdout) => callback(err, err ? null : xrandrParse(stdout))); } -function switchDevices(xrandrOptions) { - return executeCmd('xrandr ' + xrandrOptions); +function switchDevices(xrandrOptions, callback) { + executeCmd('xrandr ' + xrandrOptions, callback); } -function executePostCmd(postCmd) { - return executeCmd(postCmd); +function executePostCmd(postCmd, callback) { + executeCmd(postCmd, callback); } function orderDeviceKeys(selectedDevices, devices) { diff --git a/test/cli.tests.js b/test/cli.tests.js new file mode 100644 index 0000000..e79b60f --- /dev/null +++ b/test/cli.tests.js @@ -0,0 +1,116 @@ +'use strict'; + +const sinon = require('sinon'); +const assert = require('assert'); +const proxyquire = require('proxyquire'); + +describe('cli', () => { + let sandbox; + let consoleLogSpy; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + consoleLogSpy = sandbox.spy(console, 'log'); + }); + + afterEach(function() { + sandbox.restore(); + }); + + it('shows help', function() { + const minimistStub = sandbox.stub(); + minimistStub.returns({h: true}); + + const cli = proxyquire('../cli.js', { + 'minimist': minimistStub, + './usage.js': '[usage]' + }); + assert.equal(consoleLogSpy.callCount, 1); + assert.equal(consoleLogSpy.args[0][0], '[usage]'); + }); + + it('lists devices', function() { + const minimistStub = sandbox.stub(); + minimistStub.returns({l: true}); + const getDevicesStub = sandbox.stub(); + + proxyquire('../cli.js', { + 'minimist': minimistStub, + './swm.js': { + getDevices: getDevicesStub + } + }); + getDevicesStub.args[0][0](null, { + LVDS1: {connected: true}, + HDMI2: {connected: false} + }); + + assert.equal(getDevicesStub.callCount, 1); + assert.equal(consoleLogSpy.callCount, 3); + assert.equal(consoleLogSpy.args[0][0], 'Detected devices:\n'); + assert.equal(consoleLogSpy.args[1].join(' '), 'LVDS1: Connected'); + assert.equal(consoleLogSpy.args[2].join(' '), 'HDMI2: Disconnected'); + }); + + describe('switching', () => { + let minimistStub; + let selectedMonitors; + let deviceData; + let getDevicesStub; + let generateXrandrOptionsStub; + let switchDevicesStub; + let executePostCmdStub; + + beforeEach(() => { + selectedMonitors = ['LVDS1']; + minimistStub = sandbox.stub(); + minimistStub.returns({ + _: selectedMonitors, + postCmd: '[some post cmd]' + }); + + deviceData = { + LVDS1: {connected: true}, + HDMI2: {connected: false} + }; + + getDevicesStub = sandbox.stub(); + generateXrandrOptionsStub = sandbox.stub().returns('[some xrandr options]'); + switchDevicesStub = sandbox.stub(); + executePostCmdStub = sandbox.stub(); + + const cli = proxyquire('../cli.js', { + 'minimist': minimistStub, + './swm.js': { + getDevices: getDevicesStub, + generateXrandrOptions: generateXrandrOptionsStub, + switchDevices: switchDevicesStub, + executePostCmd: executePostCmdStub + }, + './config.js': {} + }); + + getDevicesStub.args[0][0](null, deviceData); + }); + + it('calls getDevices', () => { + assert.equal(getDevicesStub.callCount, 1, 'calls device stub'); + }); + + it('calls generateXrandrOptions', () => { + assert.equal(generateXrandrOptionsStub.callCount, 1, 'calls generateXrandrOptions'); + assert.equal(generateXrandrOptionsStub.args[0][0], selectedMonitors); + }); + + it('calls switchDevices', () => { + assert.equal(switchDevicesStub.callCount, 1); + assert.equal(switchDevicesStub.args[0][0], '[some xrandr options]'); + }); + + it('calls executePostCmd', () => { + assert.equal(executePostCmdStub.callCount, 1); + assert.equal(executePostCmdStub.args[0][0], '[some post cmd]'); + }); + }); +}); + diff --git a/test/swm.tests.js b/test/swm.tests.js index a3d4a34..2a212c4 100644 --- a/test/swm.tests.js +++ b/test/swm.tests.js @@ -32,43 +32,32 @@ describe('swm', () => { }); it('calls exec', () => { - swm.getDevices(); + swm.getDevices(sandbox.stub()); assert.equal(execStub.callCount, 1); assert.equal(execStub.args[0][0], 'xrandr'); }); - it('returns promise', () => { - const devices = swm.getDevices(); - assert.equal(typeof devices.then, 'function'); - assert.equal(typeof devices.catch, 'function'); - }); - - it('rejects when exec passes error', (done) => { - const devices = swm.getDevices(); - const cb = execStub.args[0][1]; - cb('some error'); - - return devices.catch((err) => { + it('passes error when exec passes error', (done) => { + const devices = swm.getDevices((err, devices) => { assert.equal(xrandrParseStub.callCount, 0); assert.equal(err, 'some error'); done(); }); - + const cb = execStub.args[0][1]; + cb('some error'); }); it('parses result', (done) => { - xrandrParseStub.returns('some result'); - const devices = swm.getDevices(); - const cb = execStub.args[0][1]; - cb(null, 'stdout'); - - return devices.then((result) => { - assert.equal(xrandrParseStub.args[0][0], 'stdout'); + xrandrParseStub.returns('[some result]'); + swm.getDevices((err, devices) => { + assert.equal(xrandrParseStub.args[0][0], '[some stdout]'); assert.equal(xrandrParseStub.callCount, 1); - assert.equal(result, 'some result'); + assert.equal(devices, '[some result]'); done(); }); + const cb = execStub.args[0][1]; + cb(null, '[some stdout]'); }); }); @@ -144,27 +133,19 @@ describe('swm', () => { }); it('calls exec with xrandr and opitons', () => { - swm.switchDevices('[some options]'); + swm.switchDevices('[some options]', sandbox.stub()); assert.equal(execStub.callCount, 1); assert.equal(execStub.args[0][0], 'xrandr [some options]'); }); - it('returns promise', () => { - const promise = swm.switchDevices('[some options]'); - assert.equal(typeof promise.then, 'function'); - assert.equal(typeof promise.catch, 'function'); - }); - - it('rejects when exec passes error', (done) => { - const promise = swm.switchDevices('[some options]'); - const cb = execStub.args[0][1]; - cb('some error'); - - return promise.catch((err) => { + it('passes error when exec passes error', (done) => { + swm.switchDevices('[some options]', (err, devices) => { assert.equal(err, 'some error'); done(); }); + const cb = execStub.args[0][1]; + cb('some error'); }); }); @@ -188,21 +169,13 @@ describe('swm', () => { assert.equal(execStub.args[0][0], '[some cmd]'); }); - it('returns promise', () => { - const promise = swm.executePostCmd('[some cmd]'); - assert.equal(typeof promise.then, 'function'); - assert.equal(typeof promise.catch, 'function'); - }); - - it('rejects when exec passes error', (done) => { - const promise = swm.executePostCmd('[some cmd]'); - const cb = execStub.args[0][1]; - cb('some error'); - - return promise.catch((err) => { - assert.equal(err, 'some error'); + it('passes error when exec passes error', (done) => { + swm.executePostCmd('[some cmd]', (err, devices) => { + assert.equal(err, '[some error]'); done(); }); + const cb = execStub.args[0][1]; + cb('[some error]'); }); }); });