import { describe, it, expect, afterEach } from 'vitest' import { DatabaseSync } from 'node:sqlite' import { migrate } from '../../src/main/db/migrate' import schemaV1 from '../../src/main/db/schema-v1.sql?raw' import type { SqliteDb } from '../../src/main/db/types' function tableExists(db: SqliteDb, name: string): boolean { const row = db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=?").get(name) return row != null } describe('migrate v2', () => { let db: SqliteDb afterEach(() => { db?.close() }) it('applies v1 and v2 on fresh database', () => { db = new DatabaseSync(':memory:') migrate(db) expect(tableExists(db, 'volumes')).toBe(true) expect(tableExists(db, 'chapters')).toBe(true) expect(tableExists(db, 'outline_items')).toBe(true) expect(tableExists(db, 'settings')).toBe(true) expect(tableExists(db, 'inspiration')).toBe(true) expect(tableExists(db, 'snapshots')).toBe(true) expect(tableExists(db, 'bookmarks')).toBe(true) expect(tableExists(db, 'search_fts')).toBe(true) const version = db.prepare('SELECT MAX(version) AS v FROM schema_version').get() as { v: number } expect(version.v).toBe(7) }) it('migrates existing v1 database to v2', () => { db = new DatabaseSync(':memory:') db.exec(`CREATE TABLE IF NOT EXISTS schema_version ( version INTEGER PRIMARY KEY, applied_at TEXT NOT NULL DEFAULT (datetime('now')), description TEXT )`) db.exec(schemaV1) db.prepare('INSERT INTO schema_version (version, description) VALUES (?, ?)').run(1, 'initial schema') migrate(db) expect(tableExists(db, 'outline_items')).toBe(true) const version = db.prepare('SELECT MAX(version) AS v FROM schema_version').get() as { v: number } expect(version.v).toBe(7) const cols = db.prepare('PRAGMA table_info(chapters)').all() as { name: string }[] const colNames = cols.map((c) => c.name) expect(colNames).toContain('publish_status') expect(colNames).toContain('summary') }) })