UNPKG

@magic-mustard/sqlsync

Version:

SQLSync simplifies database schema evolution by allowing a declarative approach to table management

150 lines (149 loc) 7.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const split_statement_processor_1 = require("./split.statement.processor"); const namespace_1 = require("./namespace"); describe('SplitStatementProcessor', () => { let processor; let mockFile; let mockAppender; let mockHandler; let mockContentBetweenFlags; beforeEach(() => { mockFile = { path: '/path/to/file.sql', contents: 'SQL content here' }; mockAppender = { append: jest.fn(), getLatestMigrationName: jest.fn().mockReturnValue('migration_1') }; mockHandler = { getMigrationState: jest.fn().mockReturnValue({}), updateMigrationState: jest.fn(), getNamespaceState: jest.fn().mockReturnValue({}), updateNamespaceState: jest.fn() }; mockContentBetweenFlags = { extractContentBetweenFlags: jest.fn().mockReturnValue([]) }; processor = new split_statement_processor_1.SplitStatementProcessor(mockFile, mockAppender, mockHandler, mockContentBetweenFlags); }); describe('getSplitStatementBlocks', () => { it('should extract content between split statement flags', () => { const mockBlocks = ['block1', 'block2']; mockContentBetweenFlags.extractContentBetweenFlags.mockReturnValue(mockBlocks); const result = processor.getSplitStatementBlocks(); expect(result).toEqual(mockBlocks); expect(mockContentBetweenFlags.extractContentBetweenFlags).toHaveBeenCalledWith(mockFile.contents, mockFile.path, namespace_1.SplitStatements.Flags.start, namespace_1.SplitStatements.Flags.end, false); }); }); describe('hasSplitStatements', () => { it('should return true if there are split statement blocks', () => { mockContentBetweenFlags.extractContentBetweenFlags.mockReturnValue(['block1']); const result = processor.hasSplitStatements(); expect(result).toBe(true); }); it('should return false if there are no split statement blocks', () => { mockContentBetweenFlags.extractContentBetweenFlags.mockReturnValue([]); const result = processor.hasSplitStatements(); expect(result).toBe(false); }); it('should return false if an error occurs', () => { mockContentBetweenFlags.extractContentBetweenFlags.mockImplementation(() => { throw new Error('Test error'); }); const result = processor.hasSplitStatements(); expect(result).toBe(false); }); }); describe('process', () => { it('should process split statement blocks', () => { const mockBlocks = ['block1', 'block2']; mockContentBetweenFlags.extractContentBetweenFlags.mockReturnValue(mockBlocks); jest.spyOn(processor, 'processSplitStatements'); processor.process(); expect(processor.processSplitStatements).toHaveBeenCalledWith(mockBlocks); }); }); describe('processSplitStatements', () => { it('should process each block as a single statement', () => { const mockBlocks = [ 'CREATE TRIGGER trigger1 ...', 'CREATE TRIGGER trigger2 ...' ]; const mockState = { 'migration_1': { [namespace_1.SplitStatements.StateIndex]: [] } }; mockHandler.getMigrationState.mockReturnValue(mockState); jest.spyOn(processor, 'cleanStatementBlock').mockImplementation(block => block); jest.spyOn(processor, 'generateChecksum').mockImplementation(block => block === mockBlocks[0] ? 'checksum1' : 'checksum2'); console.log('Before processing blocks'); processor.processSplitStatements(mockBlocks); console.log('After processing blocks'); expect(mockAppender.append).toHaveBeenCalledTimes(2); expect(mockAppender.append).toHaveBeenCalledWith({ token: mockBlocks[0], filePath: mockFile.path, checksum: 'checksum1' }); expect(mockAppender.append).toHaveBeenCalledWith({ token: mockBlocks[1], filePath: mockFile.path, checksum: 'checksum2' }); expect(mockHandler.updateMigrationState).toHaveBeenCalledTimes(2); }); it('should skip empty statements after cleaning', () => { const mockBlocks = [' ', 'CREATE TRIGGER trigger1 ...']; const mockState = { 'migration_1': { [namespace_1.SplitStatements.StateIndex]: [] } }; mockHandler.getMigrationState.mockReturnValue(mockState); jest.spyOn(processor, 'cleanStatementBlock').mockImplementation((block) => block.trim()); jest.spyOn(processor, 'generateChecksum').mockReturnValue('checksum'); processor.processSplitStatements(mockBlocks); expect(mockAppender.append).toHaveBeenCalledTimes(1); expect(mockHandler.updateMigrationState).toHaveBeenCalledTimes(1); }); it('should not add statements that already exist in state', () => { const mockBlocks = ['CREATE TRIGGER trigger1 ...']; const mockState = { 'migration_1': { [namespace_1.SplitStatements.StateIndex]: ['checksum'] } }; mockHandler.getMigrationState.mockReturnValue(mockState); jest.spyOn(processor, 'cleanStatementBlock').mockImplementation(block => block); jest.spyOn(processor, 'generateChecksum').mockReturnValue('checksum'); processor.processSplitStatements(mockBlocks); expect(mockAppender.append).not.toHaveBeenCalled(); expect(mockHandler.updateMigrationState).not.toHaveBeenCalled(); }); }); describe('cleanStatementBlock', () => { it('should remove comments and normalize whitespace', () => { const block = ` -- This is a comment CREATE TRIGGER trigger1 /* Another comment */ AFTER INSERT ON table1 `; const expected = 'CREATE TRIGGER trigger1 AFTER INSERT ON table1'; const result = processor.cleanStatementBlock(block); expect(result).toBe(expected); }); }); describe('generateChecksum', () => { it('should generate a SHA256 checksum for the statement', () => { const statement = 'CREATE TRIGGER trigger1 ...'; const expectedChecksum = expect.any(String); const result = processor.generateChecksum(statement); expect(result).toEqual(expectedChecksum); expect(result).toHaveLength(64); // SHA256 hash length }); }); });