diff --git a/lib/actions-oclif/env/add.ts b/lib/actions-oclif/env/add.ts index 9793908d..155d6f02 100644 --- a/lib/actions-oclif/env/add.ts +++ b/lib/actions-oclif/env/add.ts @@ -19,6 +19,7 @@ import { Command, flags } from '@oclif/command'; import { stripIndent } from 'common-tags'; import * as _ from 'lodash'; +import { ExpectedError } from '../../errors'; import * as cf from '../../utils/common-flags'; import { CommandHelp } from '../../utils/oclif-utils'; @@ -85,7 +86,9 @@ export default class EnvAddCmd extends Command { ); const cmd = this; const balena = (await import('balena-sdk')).fromSharedOptions(); - const { exitWithExpectedError } = await import('../../utils/patterns'); + const { checkLoggedIn } = await import('../../utils/patterns'); + + await checkLoggedIn(); if (params.value == null) { params.value = process.env[params.name]; @@ -120,7 +123,7 @@ export default class EnvAddCmd extends Command { params.value, ); } else { - exitWithExpectedError('You must specify an application or device'); + throw new ExpectedError('You must specify an application or device'); } } } diff --git a/lib/actions-oclif/env/rename.ts b/lib/actions-oclif/env/rename.ts index 6834a557..fdb56c4c 100644 --- a/lib/actions-oclif/env/rename.ts +++ b/lib/actions-oclif/env/rename.ts @@ -82,6 +82,9 @@ export default class EnvRenameCmd extends Command { EnvRenameCmd, ); const balena = (await import('balena-sdk')).fromSharedOptions(); + const { checkLoggedIn } = await import('../../utils/patterns'); + + await checkLoggedIn(); await balena.pine.patch({ resource: options.device diff --git a/lib/actions-oclif/env/rm.ts b/lib/actions-oclif/env/rm.ts index 734138a8..1f40c62c 100644 --- a/lib/actions-oclif/env/rm.ts +++ b/lib/actions-oclif/env/rm.ts @@ -18,6 +18,7 @@ import { Command, flags } from '@oclif/command'; import { stripIndent } from 'common-tags'; +import { ExpectedError } from '../../errors'; import { CommandHelp } from '../../utils/oclif-utils'; interface FlagsDef { @@ -91,15 +92,15 @@ export default class EnvRmCmd extends Command { EnvRmCmd, ); const balena = (await import('balena-sdk')).fromSharedOptions(); - const patterns = await import('../../utils/patterns'); + const { checkLoggedIn, confirm } = await import('../../utils/patterns'); + + await checkLoggedIn(); if (isNaN(params.id) || !Number.isInteger(Number(params.id))) { - patterns.exitWithExpectedError( - 'The environment variable id must be an integer', - ); + throw new ExpectedError('The environment variable id must be an integer'); } - await patterns.confirm( + await confirm( options.yes || false, 'Are you sure you want to delete the environment variable?', undefined, diff --git a/lib/actions-oclif/envs.ts b/lib/actions-oclif/envs.ts index 12b8266e..3f6fb939 100644 --- a/lib/actions-oclif/envs.ts +++ b/lib/actions-oclif/envs.ts @@ -19,6 +19,7 @@ import { ApplicationVariable, DeviceVariable } from 'balena-sdk'; import { stripIndent } from 'common-tags'; import * as _ from 'lodash'; +import { ExpectedError } from '../errors'; import * as cf from '../utils/common-flags'; import { CommandHelp } from '../utils/oclif-utils'; @@ -68,10 +69,12 @@ export default class EnvsCmd extends Command { const { flags: options } = this.parse(EnvsCmd); const balena = (await import('balena-sdk')).fromSharedOptions(); const visuals = await import('resin-cli-visuals'); - const { exitWithExpectedError } = await import('../utils/patterns'); + const { checkLoggedIn } = await import('../utils/patterns'); const cmd = this; - let environmentVariables: ApplicationVariable[] | DeviceVariable[]; + + await checkLoggedIn(); + if (options.application) { environmentVariables = await balena.models.application[ options.config ? 'configVar' : 'envVar' @@ -81,11 +84,11 @@ export default class EnvsCmd extends Command { options.config ? 'configVar' : 'envVar' ].getAllByDevice(options.device); } else { - return exitWithExpectedError('You must specify an application or device'); + throw new ExpectedError('You must specify an application or device'); } if (_.isEmpty(environmentVariables)) { - return exitWithExpectedError('No environment variables found'); + throw new ExpectedError('No environment variables found'); } cmd.log( diff --git a/tests/balena-api-mock.ts b/tests/balena-api-mock.ts index 4a7b4fad..dc417110 100644 --- a/tests/balena-api-mock.ts +++ b/tests/balena-api-mock.ts @@ -51,6 +51,18 @@ class BalenaAPIMock { nock.restore(); } + public expectTestDevice() { + this.scope.get(/\/v\d+\/device($|\?)/).reply(200, { d: [{ id: 7654321 }] }); + } + + public expectDeviceEnvVars() { + this.scope.post(/\/v\d+\/device_environment_variable($|\?)/).reply(201, { + id: 120203, + name: 'var3', + value: 'var3-val', + }); + } + public expectConfigVars() { this.scope.get('/config/vars').reply(200, { reservedNames: [], @@ -65,8 +77,8 @@ class BalenaAPIMock { // User details are cached in the SDK // so often we don't know if we can expect the whoami request - public expectOptionalWhoAmI() { - this.scope + public expectOptionalWhoAmI(persist = false) { + (persist ? this.scope.persist() : this.scope) .get('/user/v1/whoami') .optionally() .reply(200, { @@ -76,10 +88,10 @@ class BalenaAPIMock { }); } - public expectMixpanel() { - this.scope.get(/^\/mixpanel\/track/).reply(200, {}); + public expectMixpanel(optional = false) { + const get = this.scope.get(/^\/mixpanel\/track/); + (optional ? get.optionally() : get).reply(200, {}); } - protected handleUnexpectedRequest(req: any) { console.error(`Unexpected http request!: ${req.path}`); // Errors thrown here are not causing the tests to fail for some reason. diff --git a/tests/commands/env/add.spec.ts b/tests/commands/env/add.spec.ts index 2f842401..c3e4924b 100644 --- a/tests/commands/env/add.spec.ts +++ b/tests/commands/env/add.spec.ts @@ -1,29 +1,48 @@ +/** + * @license + * Copyright 2019 Balena Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { expect } from 'chai'; -import { balenaAPIMock, runCommand } from '../../helpers'; + +import { BalenaAPIMock } from '../../balena-api-mock'; +import { runCommand } from '../../helpers'; describe('balena env add', function() { + let api: BalenaAPIMock; + + beforeEach(() => { + api = new BalenaAPIMock(); + api.expectOptionalWhoAmI(true); + api.expectMixpanel(true); + }); + + afterEach(() => { + // Check all expected api calls have been made and clean up. + api.done(); + }); + it('should successfully add an environment variable', async () => { const deviceId = 'f63fd7d7812c34c4c14ae023fdff05f5'; - const mock = balenaAPIMock(); - mock - .get(/device/) - .reply(201, { - d: [ - { - id: 1031543, - __metadata: { uri: '/resin/device(@id)?@id=1031543' }, - }, - ], - }) - .post(/device_environment_variable/) - .reply(200, 'OK'); + api.expectTestDevice(); + api.expectConfigVars(); + api.expectDeviceEnvVars(); const { out, err } = await runCommand(`env add TEST 1 -d ${deviceId}`); expect(out.join('')).to.equal(''); expect(err.join('')).to.equal(''); - - // @ts-ignore - mock.remove(); }); }); diff --git a/tests/commands/env/rename.spec.ts b/tests/commands/env/rename.spec.ts index 40c929ab..b54a69d8 100644 --- a/tests/commands/env/rename.spec.ts +++ b/tests/commands/env/rename.spec.ts @@ -16,19 +16,30 @@ */ import { expect } from 'chai'; -import { balenaAPIMock, runCommand } from '../../helpers'; + +import { BalenaAPIMock } from '../../balena-api-mock'; +import { runCommand } from '../../helpers'; describe('balena env rename', function() { + let api: BalenaAPIMock; + + beforeEach(() => { + api = new BalenaAPIMock(); + api.expectOptionalWhoAmI(true); + api.expectMixpanel(true); + }); + + afterEach(() => { + // Check all expected api calls have been made and clean up. + api.done(); + }); + it('should successfully rename an environment variable', async () => { - const mock = balenaAPIMock(); - mock.patch(/device_environment_variable\(376\)/).reply(200, 'OK'); + api.scope.patch(/device_environment_variable\(376\)/).reply(200, 'OK'); const { out, err } = await runCommand('env rename 376 emacs --device'); expect(out.join('')).to.equal(''); expect(err.join('')).to.equal(''); - - // @ts-ignore - mock.remove(); }); }); diff --git a/tests/commands/env/rm.spec.ts b/tests/commands/env/rm.spec.ts index a8de5701..3ab4220b 100644 --- a/tests/commands/env/rm.spec.ts +++ b/tests/commands/env/rm.spec.ts @@ -1,17 +1,45 @@ +/** + * @license + * Copyright 2016-2019 Balena Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + import { expect } from 'chai'; -import { balenaAPIMock, runCommand } from '../../helpers'; + +import { BalenaAPIMock } from '../../balena-api-mock'; +import { runCommand } from '../../helpers'; describe('balena env rm', function() { + let api: BalenaAPIMock; + + beforeEach(() => { + api = new BalenaAPIMock(); + api.expectOptionalWhoAmI(true); + api.expectMixpanel(true); + }); + + afterEach(() => { + // Check all expected api calls have been made and clean up. + api.done(); + }); + it('should successfully delete an environment variable', async () => { - const mock = balenaAPIMock(); - mock.delete(/device_environment_variable/).reply(200, 'OK'); + api.scope.delete(/device_environment_variable/).reply(200, 'OK'); const { out, err } = await runCommand('env rm 144690 -d -y'); expect(out.join('')).to.equal(''); expect(err.join('')).to.equal(''); - - // @ts-ignore - mock.remove(); }); });