diff --git a/packages/cli/src/commands/apps/join.ts b/packages/cli/src/commands/apps/join.ts new file mode 100644 index 0000000000..a5334af4e5 --- /dev/null +++ b/packages/cli/src/commands/apps/join.ts @@ -0,0 +1,25 @@ +import color from '@heroku-cli/color' +import {Command, flags} from '@heroku-cli/command' +import {ux} from '@oclif/core' +import * as Heroku from '@heroku-cli/schema' + +export default class AppsJoin extends Command { + static topic = 'apps'; + static description = 'add yourself to a team app'; + static aliases = ['join'] + static flags = { + app: flags.app({required: true}), + remote: flags.remote({char: 'r'}), + }; + + public async run(): Promise { + const {flags} = await this.parse(AppsJoin) + const {app} = flags + ux.action.start(`Joining ${color.cyan(app)}`) + const {body: user} = await this.heroku.get('/account') + await this.heroku.post(`/teams/apps/${app}/collaborators`, { + body: {user: user.email}, + }) + ux.action.stop() + } +} diff --git a/packages/cli/test/helpers/stubs/post.ts b/packages/cli/test/helpers/stubs/post.ts index 83d39061dc..aa39666e54 100644 --- a/packages/cli/test/helpers/stubs/post.ts +++ b/packages/cli/test/helpers/stubs/post.ts @@ -7,7 +7,7 @@ export function collaborators() { }).reply(200) } -export function teamAppCollaborators(email = 'raulb@heroku.com', permissions: string[] = [], response: {code?: number, description?: string} = {}) { +export function teamAppCollaborators(email = 'raulb@heroku.com', permissions: string[] = [], response: {code?: number, description?: Record} = {}) { const body: {user: string, permissions?: string[]} = {user: email} if (permissions.length > 0) { body.permissions = permissions diff --git a/packages/cli/test/unit/commands/apps/join.unit.test.ts b/packages/cli/test/unit/commands/apps/join.unit.test.ts new file mode 100644 index 0000000000..ff7919a3ba --- /dev/null +++ b/packages/cli/test/unit/commands/apps/join.unit.test.ts @@ -0,0 +1,46 @@ +import {stdout, stderr} from 'stdout-stderr' +import * as nock from 'nock' +import {expect} from 'chai' +import Cmd from '../../../../src/commands/apps/join' +import runCommand from '../../../helpers/runCommand' +import expectOutput from '../../../helpers/utils/expectOutput' +import {userAccount} from '../../../helpers/stubs/get' +import {teamAppCollaborators} from '../../../helpers/stubs/post' + +describe('heroku apps:join', () => { + let apiGetUserAccount: nock.Scope + let apiPostCollaborators: nock.Scope + beforeEach(() => { + apiGetUserAccount = userAccount('raulb@heroku.com') + }) + afterEach(() => nock.cleanAll()) + it('joins the app', async () => { + apiPostCollaborators = teamAppCollaborators('raulb@heroku.com') + await runCommand(Cmd, [ + '--app', + 'myapp', + ]) + expectOutput(stdout.output, '') + expectOutput(stderr.output, 'Joining myapp...\nJoining myapp... done\n') + apiGetUserAccount.done() + apiPostCollaborators.done() + }) + it('is forbidden from joining the app', async () => { + const response = { + code: 403, description: {id: 'forbidden', error: 'You do not have access to the team heroku-tools.'}, + } + apiPostCollaborators = teamAppCollaborators('raulb@heroku.com', [], response) + let thrown = false + await runCommand(Cmd, [ + '--app', + 'myapp', + ]) + .catch(function (error) { + thrown = true + expect(error.body.error).to.eq('You do not have access to the team heroku-tools.') + }) + expect(thrown).to.eq(true) + apiGetUserAccount.done() + apiPostCollaborators.done() + }) +}) diff --git a/packages/orgs-v5/commands/apps/join.js b/packages/orgs-v5/commands/apps/join.js deleted file mode 100644 index dbcbe6ddf2..0000000000 --- a/packages/orgs-v5/commands/apps/join.js +++ /dev/null @@ -1,26 +0,0 @@ -'use strict' - -let cli = require('heroku-cli-util') - -async function run(context, heroku) { - let request = heroku.get('/account') - .then(function (user) { - return heroku.post(`/teams/apps/${context.app}/collaborators`, { - body: {user: user.email}, - }) - }) - - await cli.action(`Joining ${cli.color.cyan(context.app)}`, request) -} - -let cmd = { - topic: 'apps', - command: 'join', - description: 'add yourself to a team app', - needsAuth: true, - needsApp: true, - run: cli.command(run), -} - -let root = Object.assign({}, cmd, {topic: 'join', command: null}) -module.exports = [cmd, root] diff --git a/packages/orgs-v5/index.js b/packages/orgs-v5/index.js index e713c1aa4e..c5fd5b47e1 100644 --- a/packages/orgs-v5/index.js +++ b/packages/orgs-v5/index.js @@ -15,7 +15,6 @@ exports.topics = [ ] exports.commands = flatten([ - require('./commands/apps/join'), require('./commands/apps/leave'), require('./commands/apps/lock'), require('./commands/apps/transfer'), diff --git a/packages/orgs-v5/test/unit/commands/apps/join.unit.test.js b/packages/orgs-v5/test/unit/commands/apps/join.unit.test.js deleted file mode 100644 index b6486f93f1..0000000000 --- a/packages/orgs-v5/test/unit/commands/apps/join.unit.test.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict' -/* globals beforeEach afterEach cli nock expect */ - -let cmd = require('../../../../commands/apps/join')[0] -let stubPost = require('../../stub/post') -let stubGet = require('../../stub/get') - -describe('heroku apps:join', () => { - let apiGetUserAccount - let apiPostCollaborators - - beforeEach(() => { - cli.mockConsole() - apiGetUserAccount = stubGet.userAccount('raulb@heroku.com') - }) - afterEach(() => nock.cleanAll()) - - it('joins the app', () => { - apiPostCollaborators = stubPost.teamAppCollaborators('raulb@heroku.com') - - return cmd.run({app: 'myapp'}) - .then(() => expect('').to.eq(cli.stdout)) - .then(() => expect(`Joining myapp... done -`).to.eq(cli.stderr)) - .then(() => apiGetUserAccount.done()) - .then(() => apiPostCollaborators.done()) - }) - - it('is forbidden from joining the app', () => { - let response = { - code: 403, - description: {id: 'forbidden', error: 'You do not have access to the team heroku-tools.'}, - } - - apiPostCollaborators = stubPost.teamAppCollaborators('raulb@heroku.com', [], response) - let thrown = false - - return cmd.run({app: 'myapp'}) - .then(() => apiGetUserAccount.done()) - .catch(function (error) { - thrown = true - expect(error.body.error).to.eq('You do not have access to the team heroku-tools.') - }) - .then(function () { - expect(thrown).to.eq(true) - }) - .then(() => apiPostCollaborators.done()) - }) -}) diff --git a/packages/orgs-v5/test/unit/stub/post.js b/packages/orgs-v5/test/unit/stub/post.js index 9cf7293290..f5d112de19 100644 --- a/packages/orgs-v5/test/unit/stub/post.js +++ b/packages/orgs-v5/test/unit/stub/post.js @@ -9,7 +9,7 @@ function collaborators() { }).reply(200) } -function teamAppCollaborators(email = 'raulb@heroku.com', permissions = [], response = {}) { +function teamAppCollaborators(email = 'raulb@heroku.com', permissions = []) { let body = {user: email} if (permissions.length > 0) { body.permissions = permissions @@ -18,7 +18,7 @@ function teamAppCollaborators(email = 'raulb@heroku.com', permissions = [], resp return nock('https://api.heroku.com:443', { reqheaders: {Accept: 'application/vnd.heroku+json; version=3'}, }) - .post('/teams/apps/myapp/collaborators', body).reply(response.code || 200, response.description) + .post('/teams/apps/myapp/collaborators', body).reply(200) } function personalToPersonal() {