39 lines
3.4 KiB
TypeScript
39 lines
3.4 KiB
TypeScript
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(); }
|
|
});
|