Skip to content

Commit 10bfe86

Browse files
committed
adding tests
1 parent be6025b commit 10bfe86

2 files changed

Lines changed: 175 additions & 2 deletions

File tree

packages/cli/src/commands/pg/upgrade/prepare.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default class Upgrade extends Command {
3232

3333
const db = await getAddon(this.heroku, app, database)
3434
if (legacyEssentialPlan(db))
35-
ux.error(`You can only use ${color.cmd('pg:upgrade')} commands on Essential-* and higher plans`)
35+
ux.error(`You can only use ${color.cmd('pg:upgrade:*')} commands on Essential-* and higher plans.`)
3636

3737
if (essentialNumPlan(db))
3838
ux.error(`You can only use ${color.cmd('heroku pg:upgrade:prepare')} on Standard-tier and higher leader databases. For Essential-tier databases, use ${color.cmd('heroku pg:upgrade:run')} instead.`)
@@ -55,6 +55,6 @@ export default class Upgrade extends Command {
5555
const data = {version}
5656
ux.action.start(`Preparing upgrade on ${color.addon(db.name)}`)
5757
await this.heroku.post(`/client/v11/databases/${db.id}/upgrade/prepare`, {hostname: pgHost(), body: data})
58-
ux.action.stop(`Done\nUse ${color.cmd('heroku pg:upgrade:wait')} to track status \nYou can also run this upgrade manually before the maintenance window with ${color.cmd('heroku pg:upgrade:wait')}. Keep in mind you may only run the upgrade once it is fully prepared, which may take up to a day.`)
58+
ux.action.stop(`done\nYour database is scheduled for upgrade during your next available maintenance window.\nRun ${color.cmd('heroku pg:upgrade:wait')} to track its status.\nYou can also run this upgrade manually before the maintenance window with ${color.cmd('heroku pg:upgrade:wait')}. You can only run the upgrade after it's fully prepared, which can take up to a day.`)
5959
}
6060
}
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
import {stderr} from 'stdout-stderr'
2+
import Cmd from '../../../../../src/commands/pg/upgrade/prepare'
3+
import runCommand from '../../../../helpers/runCommand'
4+
import expectOutput from '../../../../helpers/utils/expectOutput'
5+
import {expect} from 'chai'
6+
import * as nock from 'nock'
7+
import heredoc from 'tsheredoc'
8+
import * as fixtures from '../../../../fixtures/addons/fixtures'
9+
import color from '@heroku-cli/color'
10+
import {ux} from '@oclif/core'
11+
import * as sinon from 'sinon'
12+
import stripAnsi = require('strip-ansi')
13+
14+
describe.only('pg:upgrade:prepare', function () {
15+
const addon = fixtures.addons['dwh-db']
16+
let uxWarnStub: sinon.SinonStub
17+
let uxPromptStub: sinon.SinonStub
18+
19+
before(function () {
20+
uxWarnStub = sinon.stub(ux, 'warn')
21+
uxPromptStub = sinon.stub(ux, 'prompt').resolves('myapp')
22+
})
23+
24+
beforeEach(async function () {
25+
uxWarnStub.resetHistory()
26+
uxPromptStub.resetHistory()
27+
})
28+
29+
afterEach(async function () {
30+
nock.cleanAll()
31+
})
32+
33+
after(function () {
34+
uxWarnStub.restore()
35+
uxPromptStub.restore()
36+
})
37+
38+
it('refuses to prepare upgrade on legacy essential dbs', async function () {
39+
const hobbyAddon = fixtures.addons['www-db']
40+
41+
nock('https://api.heroku.com')
42+
.post('/actions/addon-attachments/resolve')
43+
.reply(200, [{addon: hobbyAddon}])
44+
await runCommand(Cmd, [
45+
'--app',
46+
'myapp',
47+
'--confirm',
48+
'myapp',
49+
]).catch(error => {
50+
expectOutput(error.message, heredoc(`
51+
You can only use ${color.cmd('pg:upgrade:*')} commands on Essential-* and higher plans.
52+
`))
53+
})
54+
})
55+
56+
it('refuses to prepare upgrade on essential tier dbs', async function () {
57+
const essentialAddon = {
58+
name: 'postgres-1', plan: {name: 'heroku-postgresql:essential-0'},
59+
}
60+
61+
nock('https://api.heroku.com')
62+
.post('/actions/addon-attachments/resolve')
63+
.reply(200, [{addon: essentialAddon}])
64+
65+
await runCommand(Cmd, [
66+
'--app',
67+
'myapp',
68+
'--confirm',
69+
'myapp',
70+
]).catch(error => {
71+
expect(error.message).to.equal(`You can only use ${color.cmd('heroku pg:upgrade:prepare')} on Standard-tier and higher leader databases. For Essential-tier databases, use ${color.cmd('heroku pg:upgrade:run')} instead.`)
72+
})
73+
})
74+
75+
it('refuses to upgrade follower dbs', async function () {
76+
nock('https://api.heroku.com')
77+
.post('/actions/addon-attachments/resolve')
78+
.reply(200, [{addon: addon}])
79+
nock('https://api.data.heroku.com')
80+
.get(`/client/v11/databases/${addon.id}`)
81+
.reply(200, {
82+
following: 'postgres://xxx.com:5432/abcdefghijklmn',
83+
leader: {
84+
addon_id: '5ba2ba8b-07a9-4a65-a808-585a50e37f98',
85+
name: 'postgresql-leader',
86+
},
87+
})
88+
await runCommand(Cmd, [
89+
'--app',
90+
'myapp',
91+
'--confirm',
92+
'myapp',
93+
]).catch(error => {
94+
expectOutput(error.message, heredoc(`
95+
You can only use ${color.cmd('heroku pg:upgrade:prepare')} on Standard-tier and higher leader databases. For follower databases, use ${color.cmd('heroku pg:upgrade:run')} instead.
96+
`))
97+
})
98+
})
99+
100+
it('upgrades db with version flag', async function () {
101+
nock('https://api.heroku.com')
102+
.post('/actions/addon-attachments/resolve')
103+
.reply(200, [{addon}])
104+
nock('https://api.heroku.com')
105+
.get('/apps/myapp/config-vars')
106+
.reply(200, {DATABASE_URL: 'postgres://db1'})
107+
nock('https://api.data.heroku.com')
108+
.get(`/client/v11/databases/${addon.id}`)
109+
.reply(200)
110+
nock('https://api.data.heroku.com')
111+
.post(`/client/v11/databases/${addon.id}/upgrade/prepare`)
112+
.reply(200)
113+
114+
const message = heredoc(`
115+
Destructive action
116+
This command prepares the upgrade for ${addon.name} to PostgreSQL version 15 and schedules to upgrade it during the next available maintenance window.
117+
`)
118+
119+
await runCommand(Cmd, [
120+
'--app',
121+
'myapp',
122+
'--version',
123+
'15',
124+
])
125+
126+
expect(stripAnsi(uxPromptStub.args[0].toString())).contains('To proceed, type myapp')
127+
expect(stripAnsi(uxWarnStub.args[0].toString())).to.eq(message)
128+
129+
expectOutput(stderr.output, heredoc(`
130+
Preparing upgrade on ${addon.name}...
131+
Preparing upgrade on ${addon.name}... done
132+
Your database is scheduled for upgrade during your next available maintenance window.
133+
Run heroku pg:upgrade:wait to track its status.
134+
You can also run this upgrade manually before the maintenance window with heroku pg:upgrade:wait. You can only run the upgrade after it's fully prepared, which can take up to a day.
135+
`))
136+
})
137+
138+
it('upgrades db without a version flag', async function () {
139+
nock('https://api.heroku.com')
140+
.post('/actions/addon-attachments/resolve')
141+
.reply(200, [{addon}])
142+
nock('https://api.heroku.com')
143+
.get('/apps/myapp/config-vars')
144+
.reply(200, {DATABASE_URL: 'postgres://db1'})
145+
nock('https://api.data.heroku.com')
146+
.get(`/client/v11/databases/${addon.id}`)
147+
.reply(200)
148+
nock('https://api.data.heroku.com')
149+
.post(`/client/v11/databases/${addon.id}/upgrade/prepare`)
150+
.reply(200)
151+
152+
const message = heredoc(`
153+
Destructive action
154+
This command prepares the upgrade for ${addon.name} to the latest supported PostgreSQL version and schedules to upgrade it during the next available maintenance window.
155+
`)
156+
157+
await runCommand(Cmd, [
158+
'--app',
159+
'myapp',
160+
])
161+
162+
expect(stripAnsi(uxPromptStub.args[0].toString())).contains('To proceed, type myapp')
163+
expect(stripAnsi(uxWarnStub.args[0].toString())).to.eq(message)
164+
165+
expectOutput(stderr.output, heredoc(`
166+
Preparing upgrade on ${addon.name}...
167+
Preparing upgrade on ${addon.name}... done
168+
Your database is scheduled for upgrade during your next available maintenance window.
169+
Run heroku pg:upgrade:wait to track its status.
170+
You can also run this upgrade manually before the maintenance window with heroku pg:upgrade:wait. You can only run the upgrade after it's fully prepared, which can take up to a day.
171+
`))
172+
})
173+
})

0 commit comments

Comments
 (0)