UNPKG

apisurf

Version:

Analyze API surface changes between npm package versions to catch breaking changes

122 lines (121 loc) 5.72 kB
import { describe, it, expect } from '@jest/globals'; import { formatOutput } from './formatOutput.js'; describe('formatOutput', () => { it('returns success message when no breaking changes', () => { const result = { hasBreakingChanges: false, packages: [], summary: 'No breaking changes detected', semverImpact: { minimumBump: 'patch', reason: 'No changes detected' } }; const output = formatOutput(result, 'console', false); expect(output).toMatch(/✅ No changes detected/); }); it('returns JSON when format is json', () => { const result = { hasBreakingChanges: false, packages: [], summary: 'No breaking changes detected', semverImpact: { minimumBump: 'patch', reason: 'No changes detected' } }; const output = formatOutput(result, 'json', false); const parsed = JSON.parse(output); expect(parsed.hasBreakingChanges).toBe(false); expect(parsed.summary).toBe('No breaking changes detected'); }); it('returns markdown format when requested', () => { const result = { hasBreakingChanges: false, packages: [], summary: 'No changes', semverImpact: { minimumBump: 'patch', reason: 'No changes detected' } }; const output = formatOutput(result, 'md', false); expect(output).toMatch(/## API Surface Analysis/); expect(output).toMatch(/✅ No changes detected/); }); it('console output has proper blank line spacing', () => { const result = { hasBreakingChanges: true, packages: [{ name: '@test/package', path: 'npm:@test/package', breakingChanges: [{ type: 'export-removed', description: "Removed export 'SomeFunction'", before: 'SomeFunction' }, { type: 'type-changed', description: "Function 'calculateTotal' changed parameter 1 type", before: 'amount: number', after: 'amount: string | number' }], nonBreakingChanges: [{ type: 'export-added', description: "Added export 'NewFunction'", details: 'NewFunction' }] }], summary: 'Breaking changes detected', semverImpact: { minimumBump: 'major', reason: 'Breaking changes detected' } }; const output = formatOutput(result, 'console', false); const lines = output.split('\n'); // Find key sections const breakingChangesIndex = lines.findIndex(line => line.includes('❌ Breaking changes:')); const nonBreakingChangesIndex = lines.findIndex(line => line.includes('✅ Non-breaking changes:')); // Verify blank line before breaking changes section expect(lines[breakingChangesIndex - 1]).toBe(''); // Verify blank line between breaking and non-breaking changes expect(lines[nonBreakingChangesIndex - 1]).toBe(''); // Verify no verbose Before/After details are shown const beforeLines = lines.filter(line => line.includes('Before:')); const afterLines = lines.filter(line => line.includes('After:')); expect(beforeLines.length).toBe(0); expect(afterLines.length).toBe(0); }); it('verbose mode shows Before/After details', () => { const result = { hasBreakingChanges: true, packages: [{ name: '@test/package', path: 'npm:@test/package', breakingChanges: [{ type: 'type-changed', description: "Function 'calculateTotal' changed parameter 1 type", before: 'amount: number', after: 'amount: string | number' }], nonBreakingChanges: [] }], summary: 'Breaking changes detected', semverImpact: { minimumBump: 'major', reason: 'Breaking changes detected' } }; const output = formatOutput(result, 'console', true); // verbose = true // Verify Before/After details are shown in verbose mode expect(output).toMatch(/Before: amount: number/); expect(output).toMatch(/After: amount: string \| number/); }); it('shows breaking changes when detected', () => { const result = { hasBreakingChanges: true, packages: [{ name: 'test-package', path: './packages/test-package', breakingChanges: [{ type: 'export-removed', description: 'Removed export: oldFunction', before: 'export { oldFunction }', after: undefined }], nonBreakingChanges: [] }], summary: 'Breaking changes detected', semverImpact: { minimumBump: 'major', reason: 'Breaking changes detected' } }; const output = formatOutput(result, 'console', false); expect(output).toMatch(/❌ Breaking changes:/); // Package name appears in different context, test the actual change instead expect(output).toMatch(/Removed export: oldFunction/); }); });