@@ -6,7 +6,7 @@ import {PassThrough} from 'node:stream'
66
77import { ux } from '@oclif/core'
88import { utils } from '@heroku/heroku-cli-util'
9- import { parseExclusions , prepare , maybeTunnel , connArgs , spawnPipe } from '../../../../src/lib/pg/push_pull.js'
9+ import { parseExclusions , prepare , maybeTunnel , connArgs , spawnPipe , verifyExtensionsMatch } from '../../../../src/lib/pg/push_pull.js'
1010
1111describe ( 'push_pull' , function ( ) {
1212 describe ( 'parseExclusions' , function ( ) {
@@ -270,5 +270,65 @@ describe('push_pull', function () {
270270 expect ( endSpy . calledOnce ) . to . be . true
271271 } )
272272 } )
273+
274+ describe ( 'verifyExtensionsMatch' , function ( ) {
275+ let uxWarnStub : sinon . SinonStub
276+ let execQueryStub : sinon . SinonStub
277+
278+ const source = { database : 'source_db' , host : 'localhost' , port : '5432' , user : 'user1' }
279+ const target = { database : 'target_db' , host : 'localhost' , port : '5432' , user : 'user2' }
280+
281+ beforeEach ( function ( ) {
282+ uxWarnStub = sinon . stub ( ux , 'warn' )
283+ } )
284+
285+ afterEach ( function ( ) {
286+ sinon . restore ( )
287+ } )
288+
289+ it ( 'does not warn when extensions match' , async function ( ) {
290+ const extensions = 'plpgsql\nuuid-ossp\n'
291+ execQueryStub = sinon . stub ( utils . pg . PsqlService . prototype , 'execQuery' ) . resolves ( extensions )
292+
293+ await verifyExtensionsMatch ( source as any , target as any )
294+
295+ expect ( uxWarnStub . called ) . to . be . false
296+ } )
297+
298+ it ( 'warns when extensions differ between source and target' , async function ( ) {
299+ execQueryStub = sinon . stub ( utils . pg . PsqlService . prototype , 'execQuery' )
300+ execQueryStub . onFirstCall ( ) . resolves ( 'plpgsql\n' ) // target
301+ execQueryStub . onSecondCall ( ) . resolves ( 'plpgsql\nuuid-ossp\n' ) // source
302+
303+ await verifyExtensionsMatch ( source as any , target as any )
304+
305+ expect ( uxWarnStub . calledOnce ) . to . be . true
306+ } )
307+
308+ it ( 'includes both extension lists in the warning message' , async function ( ) {
309+ const targetExtensions = 'plpgsql\n'
310+ const sourceExtensions = 'plpgsql\nuuid-ossp\n'
311+ execQueryStub = sinon . stub ( utils . pg . PsqlService . prototype , 'execQuery' )
312+ execQueryStub . onFirstCall ( ) . resolves ( targetExtensions )
313+ execQueryStub . onSecondCall ( ) . resolves ( sourceExtensions )
314+
315+ await verifyExtensionsMatch ( source as any , target as any )
316+
317+ const warningMessage = uxWarnStub . firstCall . args [ 0 ]
318+ expect ( warningMessage ) . to . include ( targetExtensions )
319+ expect ( warningMessage ) . to . include ( sourceExtensions )
320+ expect ( warningMessage ) . to . include ( 'Extensions in newly created target database differ' )
321+ } )
322+
323+ it ( 'queries both databases for installed extensions' , async function ( ) {
324+ execQueryStub = sinon . stub ( utils . pg . PsqlService . prototype , 'execQuery' )
325+
326+ await verifyExtensionsMatch ( source as any , target as any )
327+
328+ expect ( execQueryStub . calledTwice ) . to . be . true
329+ expect ( execQueryStub . firstCall . args [ 0 ] ) . to . equal ( 'SELECT extname FROM pg_extension ORDER BY extname;' )
330+ expect ( execQueryStub . secondCall . args [ 0 ] ) . to . equal ( 'SELECT extname FROM pg_extension ORDER BY extname;' )
331+ } )
332+ } )
273333} )
274334
0 commit comments