Skip to content

Commit 1157fa5

Browse files
adds tests for spawnPipe
1 parent 301d0a0 commit 1157fa5

File tree

1 file changed

+82
-2
lines changed

1 file changed

+82
-2
lines changed

packages/cli/test/unit/lib/pg/push_pull.unit.test.ts

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import {expect} from 'chai'
22
import sinon from 'sinon'
3-
import {Server} from 'node:net';
3+
import {Server} from 'node:net'
4+
import {EventEmitter} from 'node:events'
5+
import {PassThrough} from 'node:stream'
46

57
import { ux } from '@oclif/core'
68
import { utils } from '@heroku/heroku-cli-util'
7-
import {parseExclusions, prepare, maybeTunnel, connArgs} from '../../../../src/lib/pg/push_pull.js'
9+
import {parseExclusions, prepare, maybeTunnel, connArgs, spawnPipe} from '../../../../src/lib/pg/push_pull.js'
810

911
describe('push_pull', function () {
1012
describe('parseExclusions', function () {
@@ -191,4 +193,82 @@ describe('push_pull', function () {
191193
expect(actual).to.eql(expected)
192194
})
193195
})
196+
197+
describe('spawnPipe', function () {
198+
it('resolves when both pgDump and pgRestore close successfully', async function () {
199+
const pgDump = new EventEmitter() as EventEmitter & {stdout: PassThrough}
200+
const pgRestore = new EventEmitter() as EventEmitter & {stdin: PassThrough}
201+
pgDump.stdout = new PassThrough()
202+
pgRestore.stdin = new PassThrough()
203+
204+
const promise = spawnPipe(pgDump as any, pgRestore as any)
205+
206+
pgDump.emit('close', 0)
207+
pgRestore.emit('close', 0)
208+
209+
await expect(promise).to.eventually.be.fulfilled
210+
})
211+
212+
it('rejects with pg_dump error when pgDump closes with non-zero code', async function () {
213+
const pgDump = new EventEmitter() as EventEmitter & { stdout: PassThrough }
214+
const pgRestore = new EventEmitter() as EventEmitter & { stdin: PassThrough }
215+
pgDump.stdout = new PassThrough()
216+
pgRestore.stdin = new PassThrough()
217+
218+
const promise = spawnPipe(pgDump as any, pgRestore as any)
219+
220+
pgDump.emit('close', 1)
221+
222+
await expect(promise).to.eventually.be.rejectedWith('pg_dump errored with 1')
223+
})
224+
225+
it('rejects with pg_restore error when pgRestore closes with non-zero code', async function () {
226+
const pgDump = new EventEmitter() as EventEmitter & { stdout: PassThrough }
227+
const pgRestore = new EventEmitter() as EventEmitter & { stdin: PassThrough }
228+
pgDump.stdout = new PassThrough()
229+
pgRestore.stdin = new PassThrough()
230+
231+
const promise = spawnPipe(pgDump as any, pgRestore as any)
232+
233+
pgDump.emit('close', 0)
234+
pgRestore.emit('close', 1)
235+
236+
await expect(promise).to.eventually.be.rejectedWith('pg_restore errored with 1')
237+
})
238+
239+
it('pipes pgDump stdout to pgRestore stdin', async function () {
240+
const pgDump = new EventEmitter() as EventEmitter & { stdout: PassThrough }
241+
const pgRestore = new EventEmitter() as EventEmitter & { stdin: PassThrough }
242+
pgDump.stdout = new PassThrough()
243+
pgRestore.stdin = new PassThrough()
244+
245+
const chunks: Buffer[] = []
246+
pgRestore.stdin.on('data', (chunk: Buffer) => chunks.push(chunk))
247+
248+
spawnPipe(pgDump as any, pgRestore as any)
249+
250+
pgDump.stdout.write('test data')
251+
pgDump.emit('close', 0)
252+
pgRestore.emit('close', 0)
253+
254+
expect(Buffer.concat(chunks).toString()).to.equal('test data')
255+
})
256+
257+
it('ends pgRestore stdin when pgDump closes successfully', async function () {
258+
const pgDump = new EventEmitter() as EventEmitter & { stdout: PassThrough }
259+
const pgRestore = new EventEmitter() as EventEmitter & { stdin: PassThrough }
260+
pgDump.stdout = new PassThrough()
261+
pgRestore.stdin = new PassThrough()
262+
263+
const endSpy = sinon.spy(pgRestore.stdin, 'end')
264+
265+
spawnPipe(pgDump as any, pgRestore as any)
266+
267+
pgDump.emit('close', 0)
268+
pgRestore.emit('close', 0)
269+
270+
expect(endSpy.calledOnce).to.be.true
271+
})
272+
})
194273
})
274+

0 commit comments

Comments
 (0)