import { test } from 'node:test'; import assert from 'node:assert/strict'; import { mkdtemp, rm } from 'node:fs/promises'; import { join } from 'node:path'; import { tmpdir } from 'node:os'; import Database from 'better-sqlite3'; import { readMigrationFiles } from 'drizzle-orm/migrator'; import { openDatabase } from '../src/db/index.js'; test('기존 30일·즐겨찾기 자료는 ID·본문·권한을 유지하며 변경 시점부터 최대 7일로 제한', async () => { const folder = await mkdtemp(join(tmpdir(), 'hop-retention-')); try { const path = join(folder, 'existing.sqlite'), old = new Database(path); const migrations = readMigrationFiles({ migrationsFolder: join(import.meta.dirname, '../drizzle'), }); old.exec( 'CREATE TABLE __drizzle_migrations(id INTEGER PRIMARY KEY AUTOINCREMENT, hash TEXT NOT NULL, created_at INTEGER)', ); for (const migration of migrations.slice(0, 8)) { for (const statement of migration.sql) old.exec(statement); old .prepare('INSERT INTO __drizzle_migrations(hash,created_at) VALUES (?,?)') .run(migration.hash, migration.folderMillis); } const now = Date.now(); for (const id of ['a', 'b']) old .prepare('INSERT INTO guest_sessions(id,tokenHash,expiresAt,createdAt) VALUES (?,?,?,?)') .run(id, id, now + 30 * 86400000, now); old .prepare( 'INSERT INTO transfer_requests(id,senderGuestId,recipientGuestId,kind,byteSize,count,status,createdAt,expiresAt) VALUES (?,?,?,?,?,?,?,?,?)', ) .run('request', 'a', 'b', 'url', 1, 1, 'accepted', now, now + 60000); old .prepare('INSERT INTO transfer_batches(id,requestId,status) VALUES (?,?,?)') .run('batch', 'request', 'stored'); old .prepare('INSERT INTO items(id,batchId,kind,url,createdAt,expiresAt) VALUES (?,?,?,?,?,?)') .run('item', 'batch', 'url', 'https://example.com/existing', now, now + 30 * 86400000); old .prepare('INSERT INTO item_access(id,itemId,guestId,role,favorite) VALUES (?,?,?,?,?)') .run('access', 'item', 'b', 'recipient', 1); old.close(); const migrated = openDatabase(path); try { const item = migrated.sqlite.prepare('SELECT * FROM items WHERE id=?').get('item'); assert.equal(item.url, 'https://example.com/existing'); assert( item.expiresAt <= Date.now() + 7 * 86400000 && item.expiresAt >= now + 7 * 86400000 - 1500, ); const access = migrated.sqlite.prepare('SELECT * FROM item_access WHERE id=?').get('access'); assert.equal(access.guestId, 'b'); assert.equal(access.favorite, 0); assert.equal(access.note, null); assert.equal(migrated.sqlite.pragma('foreign_key_check').length, 0); assert.equal(migrated.sqlite.pragma('integrity_check', { simple: true }), 'ok'); } finally { migrated.sqlite.close(); } } finally { await rm(folder, { recursive: true, force: true }); } });