/** * Tests for VisualBaselineRepository and VisualRegressionCollector. */ import Database from 'better-sqlite3'; import { runMigrations } from '../../src/db/migrations'; import { VisualBaselineRepository } from '../../src/db/VisualBaselineRepository'; import { VisualRegressionCollector } from '../../src/plugins/collectors/VisualRegressionCollector'; import { IState } from '../../src/core/interfaces'; import * as path from 'path'; import * as os from 'os'; import * as fs from 'fs'; function makeDb(): Database.Database { const db = new Database(':memory:'); db.pragma('foreign_keys = ON'); runMigrations(db); return db; } function makeState(id = 'state1'): IState { return { id, url: 'http://test.com/page', title: 'Test Page', timestamp: Date.now(), domSnapshot: '', visitCount: 1, }; } describe('VisualBaselineRepository', () => { let db: Database.Database; let repo: VisualBaselineRepository; beforeEach(() => { db = makeDb(); repo = new VisualBaselineRepository(db); }); afterEach(() => db.close()); it('creates and finds a baseline by state id', () => { repo.createBaseline({ id: 'b1', stateId: 'state1', url: 'http://test.com', screenshotPath: '/tmp/screenshot.png', width: 1280, height: 720, }); const found = repo.findBaselineByStateId('state1'); expect(found).toBeDefined(); expect(found!.id).toBe('b1'); expect(found!.approved_by).toBe('user'); }); it('returns undefined for unknown state', () => { expect(repo.findBaselineByStateId('unknown')).toBeUndefined(); }); it('creates and finds a comparison', () => { repo.createComparison({ id: 'cmp1', sessionId: 'sess1', stateId: 'state1', currentScreenshotPath: '/tmp/current.png', status: 'new_state', }); const found = repo.findComparisonById('cmp1'); expect(found).toBeDefined(); expect(found!.status).toBe('new_state'); expect(found!.baseline_id).toBeNull(); }); it('findComparisons with status filter', () => { repo.createComparison({ id: 'c1', sessionId: 's1', stateId: 'st1', currentScreenshotPath: '/a.png', status: 'new_state' }); repo.createComparison({ id: 'c2', sessionId: 's1', stateId: 'st2', currentScreenshotPath: '/b.png', status: 'passed' }); const pending = repo.findComparisons({ status: 'new_state' }); expect(pending).toHaveLength(1); expect(pending[0]!.id).toBe('c1'); }); it('updateComparisonStatus changes status', () => { repo.createComparison({ id: 'c1', sessionId: 's1', stateId: 'st1', currentScreenshotPath: '/a.png', status: 'pending' }); repo.updateComparisonStatus('c1', 'passed'); expect(repo.findComparisonById('c1')!.status).toBe('passed'); }); it('promoteToBaseline creates baseline and updates comparison status', () => { repo.createComparison({ id: 'cmp1', sessionId: 's1', stateId: 'state1', currentScreenshotPath: '/current.png', status: 'new_state' }); const baselineId = repo.promoteToBaseline('cmp1'); expect(baselineId).toBeTruthy(); expect(repo.findComparisonById('cmp1')!.status).toBe('passed'); }); }); describe('VisualRegressionCollector', () => { let db: Database.Database; let repo: VisualBaselineRepository; let tmpDir: string; beforeEach(() => { db = makeDb(); repo = new VisualBaselineRepository(db); tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'abe-visual-test-')); }); afterEach(() => { db.close(); fs.rmSync(tmpDir, { recursive: true, force: true }); }); it('returns null when disabled', async () => { const collector = new VisualRegressionCollector(tmpDir, repo, { enabled: false }); const result = await collector.processScreenshot('/fake.png', makeState(), 'sess1', []); expect(result).toBeNull(); }); it('creates new_state comparison when no baseline exists', async () => { const collector = new VisualRegressionCollector(tmpDir, repo); const result = await collector.processScreenshot('/fake.png', makeState(), 'sess1', []); expect(result).toBeNull(); const comparisons = repo.findComparisons({ sessionId: 'sess1' }); expect(comparisons).toHaveLength(1); expect(comparisons[0]!.status).toBe('new_state'); }); });