Merge pull request #3 from tomru/callbacks

switch to good old cbs
This commit is contained in:
Thomas Ruoff
2016-03-13 15:00:31 +01:00
5 changed files with 166 additions and 87 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
node_modules/ node_modules/
switchmon-*.tgz switchmon-*.tgz
coverage coverage
.lvimrc

43
cli.js
View File

@@ -16,20 +16,17 @@ function connectionStatus(device) {
if (argv.help || argv.h) { if (argv.help || argv.h) {
console.log(usage); console.log(usage);
process.exit(0); return;
} } else if (argv.list || argv.l) {
const devices = swm.getDevices((err, devices) => {
const devices = swm.getDevices(); if (err) {
throw new Error(err);
if (argv.list || argv.l) { }
devices console.log('Detected devices:\n');
.then(devices => { Object.keys(devices)
console.log('Detected devices:\n'); .sort(key => !devices[key].connected)
Object.keys(devices) .forEach(key => console.log(key + ':', connectionStatus(devices[key])));
.sort(key => !devices[key].connected) });
.forEach(key => console.log(key + ':', connectionStatus(devices[key])));
process.exit(0);
});
} else { } else {
let selectedMonitors = argv._; let selectedMonitors = argv._;
@@ -42,14 +39,14 @@ if (argv.list || argv.l) {
console.log('Using profile', profile); console.log('Using profile', profile);
} }
console.log('Switching on', selectedMonitors); console.log('Switching on', selectedMonitors.length ? selectedMonitors : 'all connected monitors');
devices swm.getDevices((err, devices) => {
.then(swm.generateXrandrOptions.bind(null, selectedMonitors)) if (err) {
.then(swm.switchDevices) throw new Error(err);
.then(swm.executePostCmd.bind(null, postCmd)) }
.catch(err => { const xrandrOptions = swm.generateXrandrOptions(selectedMonitors, devices);
console.error(err); swm.switchDevices(xrandrOptions);
process.exit(2); swm.executePostCmd(postCmd);
}); });
} }

24
swm.js
View File

@@ -3,28 +3,20 @@
const xrandrParse = require('xrandr-parse'); const xrandrParse = require('xrandr-parse');
const exec = require('child_process').exec; const exec = require('child_process').exec;
function executeCmd(cmd) { function executeCmd(cmd, callback) {
return new Promise((resolve, reject) => { exec(cmd, callback);
exec(cmd, (err, stdout, stderr) => {
if (err || stderr) {
reject(err);
return;
}
resolve(stdout);
});
});
} }
function getDevices() { function getDevices(callback) {
return executeCmd('xrandr').then(stdout => xrandrParse(stdout)); executeCmd('xrandr', (err, stdout) => callback(err, err ? null : xrandrParse(stdout)));
} }
function switchDevices(xrandrOptions) { function switchDevices(xrandrOptions, callback) {
return executeCmd('xrandr ' + xrandrOptions); executeCmd('xrandr ' + xrandrOptions, callback);
} }
function executePostCmd(postCmd) { function executePostCmd(postCmd, callback) {
return executeCmd(postCmd); executeCmd(postCmd, callback);
} }
function orderDeviceKeys(selectedDevices, devices) { function orderDeviceKeys(selectedDevices, devices) {

116
test/cli.tests.js Normal file
View File

@@ -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]');
});
});
});

View File

@@ -32,43 +32,32 @@ describe('swm', () => {
}); });
it('calls exec', () => { it('calls exec', () => {
swm.getDevices(); swm.getDevices(sandbox.stub());
assert.equal(execStub.callCount, 1); assert.equal(execStub.callCount, 1);
assert.equal(execStub.args[0][0], 'xrandr'); assert.equal(execStub.args[0][0], 'xrandr');
}); });
it('returns promise', () => { it('passes error when exec passes error', (done) => {
const devices = swm.getDevices(); const devices = swm.getDevices((err, devices) => {
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) => {
assert.equal(xrandrParseStub.callCount, 0); assert.equal(xrandrParseStub.callCount, 0);
assert.equal(err, 'some error'); assert.equal(err, 'some error');
done(); done();
}); });
const cb = execStub.args[0][1];
cb('some error');
}); });
it('parses result', (done) => { it('parses result', (done) => {
xrandrParseStub.returns('some result'); xrandrParseStub.returns('[some result]');
const devices = swm.getDevices(); swm.getDevices((err, devices) => {
const cb = execStub.args[0][1]; assert.equal(xrandrParseStub.args[0][0], '[some stdout]');
cb(null, 'stdout');
return devices.then((result) => {
assert.equal(xrandrParseStub.args[0][0], 'stdout');
assert.equal(xrandrParseStub.callCount, 1); assert.equal(xrandrParseStub.callCount, 1);
assert.equal(result, 'some result'); assert.equal(devices, '[some result]');
done(); done();
}); });
const cb = execStub.args[0][1];
cb(null, '[some stdout]');
}); });
}); });
@@ -144,27 +133,19 @@ describe('swm', () => {
}); });
it('calls exec with xrandr and opitons', () => { 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.callCount, 1);
assert.equal(execStub.args[0][0], 'xrandr [some options]'); assert.equal(execStub.args[0][0], 'xrandr [some options]');
}); });
it('returns promise', () => { it('passes error when exec passes error', (done) => {
const promise = swm.switchDevices('[some options]'); swm.switchDevices('[some options]', (err, devices) => {
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) => {
assert.equal(err, 'some error'); assert.equal(err, 'some error');
done(); done();
}); });
const cb = execStub.args[0][1];
cb('some error');
}); });
}); });
@@ -188,21 +169,13 @@ describe('swm', () => {
assert.equal(execStub.args[0][0], '[some cmd]'); assert.equal(execStub.args[0][0], '[some cmd]');
}); });
it('returns promise', () => { it('passes error when exec passes error', (done) => {
const promise = swm.executePostCmd('[some cmd]'); swm.executePostCmd('[some cmd]', (err, devices) => {
assert.equal(typeof promise.then, 'function'); assert.equal(err, '[some error]');
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');
done(); done();
}); });
const cb = execStub.args[0][1];
cb('[some error]');
}); });
}); });
}); });