Skip to content

Commit 998d5ed

Browse files
authored
feat: add confirmation for DATs to be deleted with datacloud disconnect (#157)
* Add table for confirmation of DATs to be deleted * CX feedback
1 parent a1a7db5 commit 998d5ed

File tree

3 files changed

+121
-0
lines changed

3 files changed

+121
-0
lines changed

src/commands/datacloud/disconnect.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,47 @@ export default class Disconnect extends Command {
2626
const {flags, args} = await this.parse(Disconnect)
2727
const {app, addon, confirm} = flags
2828
const {connection_name: connectionName} = args
29+
let dataActionTargets: AppLink.DataActionTarget[] = []
30+
let message: string | undefined
2931

3032
await this.configureAppLinkClient(app, addon)
3133

34+
try {
35+
const {body} = await this.applinkClient.get<AppLink.DataActionTarget[]>(
36+
`/addons/${this.addonId}/connections/datacloud/${connectionName}/data_action_targets`,
37+
{
38+
headers: {authorization: `Bearer ${this._applinkToken}`},
39+
retryAuth: false,
40+
}
41+
)
42+
dataActionTargets = body || []
43+
} catch {
44+
ux.error('Failed to fetch data action targets for connection', {exit: 1})
45+
}
46+
47+
if (dataActionTargets.length > 0) {
48+
const lines: string[] = []
49+
ux.table(dataActionTargets, {
50+
label: {header: 'Data Action Target Name'},
51+
}, {
52+
printLine: (line: string) => lines.push(line),
53+
})
54+
55+
const tableStr = lines.join('\n')
56+
const intro = heredoc`
57+
Destructive action
58+
This command disconnects the org ${color.bold.red(connectionName)} from add-on ${color.addon(this._addonName)} on app ${color.app(app)} and deletes the following data action targets:`
59+
60+
message = `${intro}\n${tableStr}`
61+
}
62+
3263
await confirmCommand({
3364
connectionName,
3465
connectionType: 'org',
3566
addon: this._addonName,
3667
app,
3768
confirm,
69+
message,
3870
})
3971

4072
try {

src/lib/applink/types.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,20 @@ export type DataActionTargetCreate = {
132132
}
133133
}
134134

135+
/**
136+
* A Data Action Target.
137+
*/
138+
export type DataActionTarget = {
139+
readonly id: string
140+
readonly type: string
141+
readonly label: string
142+
readonly api_name: string
143+
readonly status: string
144+
readonly target_endpoint: string
145+
readonly connection_id: string
146+
readonly app_id: string
147+
}
148+
135149
/**
136150
* Create Authorization process.
137151
*/

test/commands/datacloud/disconnect.test.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@ import {
1515
import {CLIError} from '@oclif/core/lib/errors'
1616
import stripAnsi from '../../helpers/strip-ansi'
1717
import heredoc from 'tsheredoc'
18+
import {ux} from '@oclif/core'
19+
import * as sinon from 'sinon'
20+
21+
const stdOutputMockStart = () => {
22+
stderr.start()
23+
stdout.start()
24+
}
25+
26+
const stdOutputMockStop = () => {
27+
stderr.stop()
28+
stdout.stop()
29+
}
1830

1931
describe('datacloud:disconnect', function () {
2032
let api: nock.Scope
@@ -46,10 +58,13 @@ describe('datacloud:disconnect', function () {
4658
api.done()
4759
applinkApi.done()
4860
nock.cleanAll()
61+
sinon.restore()
4962
})
5063

5164
it('shows the expected output after failing', async function () {
5265
applinkApi
66+
.get('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/datacloud/myorg/data_action_targets')
67+
.reply(200, [])
5368
.delete('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/myorg')
5469
.reply(202, connection5_disconnection_failed)
5570

@@ -68,6 +83,8 @@ describe('datacloud:disconnect', function () {
6883

6984
it('waits for DELETE /connections/orgName status to return "disconnecting" before ending the action successfully', async function () {
7085
applinkApi
86+
.get('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/datacloud/myorg/data_action_targets')
87+
.reply(200, [])
7188
.delete('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/myorg')
7289
.reply(202, connection5_disconnecting)
7390

@@ -83,6 +100,8 @@ describe('datacloud:disconnect', function () {
83100

84101
it('connection not found', async function () {
85102
applinkApi
103+
.get('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/datacloud/myorg/data_action_targets')
104+
.reply(200, [])
86105
.delete('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/myorg')
87106
.replyWithError(ConnectionError_record_not_found)
88107

@@ -102,6 +121,9 @@ describe('datacloud:disconnect', function () {
102121
})
103122

104123
it('errors when the wrong org name is passed to the confirm flag', async function () {
124+
applinkApi
125+
.get('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/datacloud/myorg/data_action_targets')
126+
.reply(200, [])
105127
try {
106128
await runCommand(Cmd, [
107129
'myorg',
@@ -114,5 +136,58 @@ describe('datacloud:disconnect', function () {
114136
expect(oclif.exit).to.equal(1)
115137
}
116138
})
139+
140+
it('prompts with DAT table when data action targets exist (no indent)', async function () {
141+
applinkApi
142+
.get('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/datacloud/myorg/data_action_targets')
143+
.reply(200, [
144+
{
145+
label: 'Target One',
146+
api_name: 'TargetOne',
147+
},
148+
{
149+
label: 'Target Two',
150+
api_name: 'TargetTwo',
151+
},
152+
])
153+
.delete('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/myorg')
154+
.reply(202, connection5_disconnecting)
155+
156+
sinon.stub(ux, 'prompt').resolves('myorg')
157+
stdOutputMockStart()
158+
await runCommand(Cmd, [
159+
'myorg',
160+
'--app=my-app',
161+
])
162+
stdOutputMockStop()
163+
164+
expect(stderr.output).to.contain('Destructive action')
165+
expect(stderr.output).to.contain('Data Action Target Name')
166+
expect(stderr.output).to.contain('Target One')
167+
expect(stderr.output).to.contain('Target Two')
168+
})
169+
170+
it('prompts without DAT table when no data action targets exist', async function () {
171+
applinkApi
172+
.delete('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/myorg')
173+
.reply(202, connection5_disconnecting)
174+
.get('/addons/01234567-89ab-cdef-0123-456789abcdef/connections/datacloud/myorg/data_action_targets')
175+
.reply(200, [])
176+
177+
sinon.stub(ux, 'prompt').resolves('myorg')
178+
stdOutputMockStart()
179+
await runCommand(Cmd, [
180+
'myorg',
181+
'--app=my-app',
182+
])
183+
stdOutputMockStop()
184+
185+
console.log(stderr.output)
186+
187+
expect(stderr.output).to.contain('Destructive action')
188+
expect(stderr.output).to.contain('This command disconnects the org myorg')
189+
expect(stderr.output).to.not.contain('data action targets')
190+
expect(stderr.output).to.not.contain('Data Action Target Name')
191+
})
117192
})
118193
})

0 commit comments

Comments
 (0)