import { test } from 'node:test'; import assert from 'node:assert/strict'; import { createClientAnalytics } from '../src/client/analytics.js'; test('client sends batches at 20 events or five seconds and limits activity including visibility toggles', async t => { t.mock.timers.enable({ apis: ['setInterval', 'Date'], now: 1000 }); const doc = new EventTarget() as EventTarget & { hidden: boolean; referrer: string }; doc.hidden = false; doc.referrer = ''; Object.defineProperty(globalThis, 'document', { value: doc, configurable: true }); Object.defineProperty(globalThis, 'location', { value: { search: '' }, configurable: true }); const batches: any[][] = [], activities: boolean[] = []; const analytics = createClientAnalytics({ events: async events => { batches.push(events); }, activity: async visible => { activities.push(visible); }, }); const flush = async () => { for (let i = 0; i < 5; i++) await Promise.resolve(); }; try { analytics.ready(); await flush(); assert.equal(batches.length, 0); for (let i = 0; i < 19; i++) analytics.screen('match'); await flush(); assert.equal(batches[0].length, 20); analytics.screen('result'); t.mock.timers.tick(4999); await flush(); assert.equal(batches.length, 1); t.mock.timers.tick(1); await flush(); assert.equal(batches[1].length, 1); for (let i = 0; i < 10; i++) { doc.hidden = true; doc.dispatchEvent(new Event('visibilitychange')); doc.hidden = false; doc.dispatchEvent(new Event('visibilitychange')); } await flush(); assert.deepEqual(activities, [true, false]); t.mock.timers.tick(55000); await flush(); assert.deepEqual(activities, [true, false, true]); } finally { analytics.destroy(); Reflect.deleteProperty(globalThis, 'document'); Reflect.deleteProperty(globalThis, 'location'); } });