import { afterEach, beforeEach, describe, expect, it, vi, type MockInstance, } from 'vitest'; const mockState = vi.hoisted(() => ({ slotName: 'test_slot_name', pubName: 'test_pub_name', existsResult: (() => undefined) as () => unknown, tablesResult: (() => undefined) as () => unknown, })); vi.mock('zapatos/db', async () => { const actual = await vi.importActual( 'zapatos/db', ); return { ...actual, sql: vi.fn().mockImplementation((_query, firstParam) => { return stub({ run: vi.fn().mockImplementation(() => { if (firstParam.value === mockState.slotName) { return mockState.existsResult(); } if (firstParam.value === mockState.pubName) { return mockState.tablesResult(); } return undefined; }), }); }), transaction: vi.fn().mockImplementation(() => { return; }), }; }); import { stub } from '@axinom/mosaic-dev-be-common/vitest'; import { Pool } from 'pg'; import { SQLFragment } from 'zapatos/db'; import { ensureReplicationSlotAndPublicationExist } from './ensure-replication-slot-and-publication-exist'; const slotName = mockState.slotName; const pubName = mockState.pubName; describe('ensureReplicationSlotAndPublicationExist', () => { let consoleLogSpy: MockInstance; const expectSingleLog = (message: string): void => { expect(consoleLogSpy).toHaveBeenCalledTimes(1); expect(consoleLogSpy).toHaveBeenCalledWith(message); }; beforeEach(() => { consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { return; }); }); afterEach(() => { mockState.existsResult = () => undefined; mockState.tablesResult = () => undefined; vi.restoreAllMocks(); }); it.each([ [true, false], [false, true], [false, false], ])( 'call when slot and/or publication does not exist -> pass, %p, %p', async (slotExists, pubExists) => { // Arrange mockState.existsResult = () => [{ slotExists, pubExists }]; mockState.tablesResult = () => pubExists ? [ { schemaname: 'app_public', tablename: 'table_one' }, { schemaname: 'app_public', tablename: 'table_two' }, { schemaname: 'app_public', tablename: 'table_three' }, ] : []; // Act await ensureReplicationSlotAndPublicationExist({ replicationPgPool: stub(), replicationSlotName: slotName, publicationName: pubName, tableNames: ['table_one', 'table_two', 'table_three'], schemaName: 'app_public', }); // Assert expectSingleLog( 'The replication slot "test_slot_name" and publication "test_pub_name" successfully (re)created.', ); }, ); it('call when slot and publication exist and new table is added -> pass', async () => { // Arrange mockState.existsResult = () => [{ slotExists: true, pubExists: true }]; mockState.tablesResult = () => [ { schemaname: 'app_public', tablename: 'table_one' }, { schemaname: 'app_public', tablename: 'table_two' }, ]; // Act await ensureReplicationSlotAndPublicationExist({ replicationPgPool: stub(), replicationSlotName: slotName, publicationName: pubName, tableNames: ['table_one', 'table_two', 'table_three'], schemaName: 'app_public', }); // Assert expectSingleLog( 'The replication slot "test_slot_name" and publication "test_pub_name" successfully (re)created.', ); }); it('call when slot and publication exist and old table is removed -> pass', async () => { // Arrange mockState.existsResult = () => [{ slotExists: true, pubExists: true }]; mockState.tablesResult = () => [ { schemaname: 'app_public', tablename: 'table_one' }, { schemaname: 'app_public', tablename: 'table_two' }, { schemaname: 'app_public', tablename: 'table_three' }, ]; // Act await ensureReplicationSlotAndPublicationExist({ replicationPgPool: stub(), replicationSlotName: slotName, publicationName: pubName, tableNames: ['table_one', 'table_two'], schemaName: 'app_public', }); // Assert expectSingleLog( 'The replication slot "test_slot_name" and publication "test_pub_name" successfully (re)created.', ); }); it('call when slot and publication exist and one table is replaced by another -> pass', async () => { // Arrange mockState.existsResult = () => [{ slotExists: true, pubExists: true }]; mockState.tablesResult = () => [ { schemaname: 'app_public', tablename: 'table_one' }, { schemaname: 'app_public', tablename: 'table_two' }, { schemaname: 'app_public', tablename: 'table_three' }, ]; // Act await ensureReplicationSlotAndPublicationExist({ replicationPgPool: stub(), replicationSlotName: slotName, publicationName: pubName, tableNames: ['table_one', 'table_two', 'table_four'], schemaName: 'app_public', }); // Assert expectSingleLog( 'The replication slot "test_slot_name" and publication "test_pub_name" successfully (re)created.', ); }); it('call when slot and publication exist and tables are in sync -> skip', async () => { // Arrange mockState.existsResult = () => [{ slotExists: true, pubExists: true }]; mockState.tablesResult = () => [ { schemaname: 'app_public', tablename: 'table_one' }, { schemaname: 'app_public', tablename: 'table_two' }, { schemaname: 'app_public', tablename: 'table_three' }, ]; // Act await ensureReplicationSlotAndPublicationExist({ replicationPgPool: stub(), replicationSlotName: slotName, publicationName: pubName, tableNames: ['table_one', 'table_two', 'table_three'], schemaName: 'app_public', }); // Assert expectSingleLog( 'The replication slot "test_slot_name" and publication "test_pub_name" already exist.', ); }); });