import { test } from 'node:test'; import assert from 'node:assert/strict'; import { randomUUID } from 'node:crypto'; import { createStatsStore } from '../src/server/stats-store.js'; import { createAnalyticsStore } from '../src/server/analytics-store.js'; import { getAnalyticsReport } from '../src/server/analytics-report.js'; test('dashboard preserves visit analytics and counts current client matches once across participants', { skip: !process.env.TEST_MONGODB_URI }, async () => { const store = await createStatsStore({ mongoUri: process.env.TEST_MONGODB_URI!, databaseName: `dragon_ball_test_report_${randomUUID().replaceAll('-', '')}` }); try { const analytics = await createAnalyticsStore(store.db), a = await store.createGuest(), b = await store.createGuest(); const now = new Date('2026-10-13T08:00:00Z'); const meta = { device: 'mobile', browser: 'Chrome 141', source: 'social', invitation: false }; const s1 = await analytics.touch(a.playerId, new Date('2026-10-11T14:00:00Z'), true, meta); const s2 = await analytics.touch(a.playerId, new Date('2026-10-12T15:00:00Z'), true, meta); const s3 = await analytics.touch(b.playerId, new Date('2026-10-12T15:00:00Z'), true, { ...meta, device: 'pc' }); const base = { environment: 'production', schemaVersion: 1, appVersion: '0.1.0', source: 'client' as const }; for (const [i, s] of [s1, s2, s3].entries()) await analytics.insert({ ...base, _id: `view-${i}`, playerId: s.playerId, sessionId: s.sessionId, occurredAt: s.startedAt, eventType: 'page_view' }); for (const [i, s] of [s2, s3].entries()) { await analytics.insert({ ...base, _id: `start-${i}`, playerId: s.playerId, sessionId: s.sessionId, eventType: 'game_started', matchId: 'shared-match', mode: 'friend', occurredAt: new Date('2026-10-13T00:00:00Z') }); await analytics.insert({ ...base, _id: `finish-${i}`, playerId: s.playerId, sessionId: s.sessionId, eventType: 'game_finished', matchId: 'shared-match', mode: 'friend', outcome: i ? 'loss' : 'win', occurredAt: new Date('2026-10-13T00:01:00Z') }); } await analytics.insert({ ...base, _id: 'test-game', eventType: 'game_started', matchId: 'test', mode: 'bot', occurredAt: new Date('2026-10-13T00:00:00Z'), environment: 'test' }); const filters = { start: new Date('2026-10-11T00:00:00Z'), end: now }; const report = await getAnalyticsReport(store.db, filters, now); assert.equal(report.overview.visitors, 2); assert.equal(report.overview.wau.visitors, 2); assert.equal(report.overview.mau.visitors, 2); assert.equal(report.clientGameplay.players, 2); assert.equal(report.clientGameplay.startedMatches, 1); assert.equal(report.clientGameplay.resultReports, 2); assert.equal(report.daily.find(d => d.day === '2026-10-13')!.matches, 1); assert.equal(report.overview.dau.players, 2); assert.ok(!('gameplay' in report)); assert.ok(!('sessionConversion' in report.overview)); const filtered = await getAnalyticsReport(store.db, { ...filters, device: 'mobile' }, now); assert.equal(filtered.overview.visitors, 1); assert.equal(filtered.clientGameplay.players, 1); assert.equal(filtered.revisit.visitCohorts[0].size, 1); const bot = await getAnalyticsReport(store.db, { ...filters, mode: 'bot' }, now); assert.equal(bot.overview.visitors, 2); assert.equal(bot.clientGameplay.startedMatches, 0); assert.equal((await store.db.listCollections({ name: 'matches' }).toArray()).length, 0); } finally { await store.db.dropDatabase(); await store.close(); } });