import { test } from 'node:test'; import assert from 'node:assert/strict'; import { randomUUID } from 'node:crypto'; import { mkdtemp, readFile, rm } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join, resolve, sep } from 'node:path'; import { BSON, MongoClient } from 'mongodb'; import { cleanupLegacyData } from '../scripts/cleanup-legacy-data.js'; test('legacy cleanup backs up removed data, preserves current data and is repeatable', { skip: !process.env.TEST_MONGODB_URI }, async () => { const client = await new MongoClient(process.env.TEST_MONGODB_URI!).connect(); const db = client.db(`dragon_ball_test_cleanup_${randomUUID().replaceAll('-', '')}`); const directory = await mkdtemp(join(tmpdir(), 'dragon-ball-cleanup-')); try { const date = new Date(); await db.collection('matches').insertOne({ endedAt: date }); await db.collection('players').insertOne({ firstMatchAt: date, firstVisitAt: date, guestTokenHash: 'keep-identity' }); await db.collection('analytics_events').insertMany([{ eventType: 'match_started' }, { eventType: 'page_view' }, { eventType: 'game_finished', source: 'client' }]); await db.collection('analytics_presence_samples').insertMany([{ connected: 2 }, { source: 'activity_reports', active: 1 }]); for (const name of ['game_sessions', 'rooms', 'analytics_sessions', 'analytics_metadata']) await db.collection(name).insertOne({ keep: true }); const before = await cleanupLegacyData(db); assert.equal(before.applied, false); assert.deepEqual(before.counts, { matches: 1, events: 1, samples: 1, playerFields: 1 }); assert.equal(await db.collection('matches').countDocuments(), 1); const path = join(directory, 'backup.ejson'); await cleanupLegacyData(db, path); const backup = BSON.EJSON.parse(await readFile(path, 'utf8')); assert.equal(+backup.matches[0].endedAt, +date); assert.equal(backup.players.length, 1); assert.equal((await db.listCollections({ name: 'matches' }).toArray()).length, 0); assert.equal(await db.collection('analytics_events').countDocuments(), 2); assert.equal(await db.collection('analytics_presence_samples').countDocuments(), 1); const player = await db.collection('players').findOne(); assert.equal(player?.firstMatchAt, undefined); assert.equal(player?.guestTokenHash, 'keep-identity'); assert.equal(+player!.firstVisitAt, +date); for (const name of ['game_sessions', 'rooms', 'analytics_sessions', 'analytics_metadata']) assert.equal(await db.collection(name).countDocuments({ keep: true }), 1); const again = await cleanupLegacyData(db, join(directory, 'second.ejson')); assert.deepEqual(again.counts, { matches: 0, events: 0, samples: 0, playerFields: 0 }); await assert.rejects(cleanupLegacyData(db, path), { code: 'EEXIST' }); } finally { await db.dropDatabase(); await client.close(); assert.ok(resolve(directory).startsWith(resolve(tmpdir()) + sep + 'dragon-ball-cleanup-')); await rm(directory, { recursive: true }); } });