diff --git a/src/cmd/cloud.js b/src/cmd/cloud.js index a5571c9ec..b33703052 100644 --- a/src/cmd/cloud.js +++ b/src/cmd/cloud.js @@ -1,8 +1,6 @@ const _ = require('lodash'); const VError = require('verror'); -const whenNode = require('when/node'); const prompt = require('inquirer').prompt; -const temp = require('temp').track(); const settings = require('../../settings.js'); const specs = require('../lib/deviceSpecs'); diff --git a/src/cmd/function.js b/src/cmd/function.js index 4c9834ecc..1d956d2fb 100644 --- a/src/cmd/function.js +++ b/src/cmd/function.js @@ -3,10 +3,6 @@ const VError = require('verror'); const ensureError = require('../lib/utilities').ensureError; class FunctionCommand { - constructor(options) { - this.options = options; - } - listFunctions() { const api = new ApiClient(); api.ensureToken(); @@ -42,7 +38,7 @@ class FunctionCommand { api.ensureToken(); return api.callFunction(deviceId, functionName, funcParam).then(result => { - if (result && result.return_value) { + if (result && result.hasOwnProperty('return_value')) { console.log(result.return_value); } else { throw api.normalizedApiError(result); diff --git a/src/cmd/variable.js b/src/cmd/variable.js index 7a168d9c7..d5b87b9af 100644 --- a/src/cmd/variable.js +++ b/src/cmd/variable.js @@ -67,7 +67,7 @@ class VariableCommand { return when.map(deviceId, (deviceId) => { return api.getVariable(deviceId, variableName); }).then((results) => { - const time = moment().format(); + const now = moment().format(); let hasErrors = false; for (let i = 0; i < results.length; i++) { const parts = []; @@ -82,7 +82,7 @@ class VariableCommand { parts.push(result.coreInfo.deviceID); } if (time) { - parts.push(time); + parts.push(now); } parts.push(result.result); diff --git a/test/cmd/function.spec.js b/test/cmd/function.spec.js new file mode 100644 index 000000000..0330a395e --- /dev/null +++ b/test/cmd/function.spec.js @@ -0,0 +1,109 @@ +const expect = require('chai').expect; +const proxyquire = require('proxyquire'); +const sandbox = require('sinon').createSandbox(); + +const stubs = { + api: { + ensureToken: () => {}, + callFunction: () => {}, + normalizedApiError: (resp) => new Error(resp.error), + }, + ApiClient: function ApiClient(){ + return stubs.api; + } +}; + +const FunctionCommand = proxyquire('../../src/cmd/function', { + '../lib/ApiClient.js': stubs.ApiClient +}); + + +describe('Function Command', () => { + + let deviceId, functionName, functionParam; + + beforeEach(() => { + deviceId = 'test-device'; + functionName = 'fn'; + functionParam = 'param'; + }); + + afterEach(() => { + sandbox.restore(); + }); + + describe('when the function succeeds', () => { + it('prints the return value', withConsoleStubs(() => { + const { func, api } = stubForFunction(new FunctionCommand(), stubs); + api.callFunction.resolves({ ok: true, return_value: 42 }); + + return func.callFunction(deviceId, functionName, functionParam).then(() => { + expectSuccessMessage(42); + }); + })); + + it('prints the return value of 0', withConsoleStubs(() => { + const { func, api } = stubForFunction(new FunctionCommand(), stubs); + api.callFunction.resolves({ ok: true, return_value: 0 }); + + return func.callFunction(deviceId, functionName, functionParam).then(() => { + expectSuccessMessage(0); + }); + })); + }); + + describe('when the function does not exist', () => { + it('rejects with an error',() => { + const { func, api } = stubForFunction(new FunctionCommand(), stubs); + api.callFunction.resolves({ + ok: false, + error: `Function ${functionName} not found` + }); + + return func.callFunction(deviceId, functionName, functionParam).then(() => { + throw new Error('expected promise to be rejected'); + }).catch(error => { + expect(error).to.have.property('message', `Function call failed: Function ${functionName} not found`); + }); + }); + }); + + function expectSuccessMessage(value){ + expect(process.stdout.write).to.have.property('callCount', 1); + expect(process.stdout.write.firstCall.args[0]) + .to.match(new RegExp(`${value}\\n$`)); + } + + function stubForFunction(func, stubs){ + const { api } = stubs; + sandbox.stub(api, 'ensureToken'); + sandbox.stub(api, 'callFunction'); + return { func, api }; + } + + // TODO (mirande): figure out a better approach. this allows us to verify + // log output without supressing mocha's success / error messages but is a + // bit awkward + function withConsoleStubs(fn){ + + return () => { + let result; + + sandbox.stub(process.stdout, 'write'); + sandbox.stub(process.stderr, 'write'); + + try { + result = fn(); + } catch (error) { + sandbox.restore(); + throw error; + } + + if (result && typeof result.finally === 'function'){ + return result.finally(() => sandbox.restore()); + } + sandbox.restore(); + return result; + }; + } +});