import test from 'node:test'; import assert from 'node:assert/strict'; import { ROUTES as SITE_ROUTES } from '../../packages/site/content.ts'; import { CONSENT_KEY, CONSENT_MAX_AGE, DATA_LAYER, createAnalytics, validateConfig, validateEvent, parseConsent, safeAttribution, safeRoute, } from '../../apps/web/src/measurement/analytics.mjs'; function fixture(saved) { let clock = 1_800_000_000_000; const storage = new Map(saved ? [[CONSENT_KEY, saved]] : []); const listeners = {}; const cookies = new Map([['essential_session', 'kept']]); const scripts = []; const deletedCookies = []; let vitalsLoads = 0; const reporters = {}; const win = { location: { hostname: 'studio.example.com', pathname: '/', search: '?utm_source=chatgpt.com&email=visitor%40example.com&gclid=private' }, localStorage: { getItem: (key) => storage.get(key) ?? null, setItem: (key, value) => storage.set(key, value) }, addEventListener: (event, callback) => { listeners[event] = callback; }, }; const doc = { referrer: 'https://chatgpt.com/c/private-conversation?name=private#secret', addEventListener: (event, callback) => { listeners[event] = callback; }, createElement: () => ({ remove() { this.removed = true; } }), head: { appendChild: (script) => scripts.push(script) }, get cookie() { return [...cookies].map(([key, value]) => `${key}=${value}`).join('; '); }, set cookie(value) { deletedCookies.push(value); const key = value.split('=')[0]; if (value.includes('Max-Age=0')) cookies.delete(key); }, }; const service = createAnalytics({ getWindow: () => win, getDocument: () => doc, now: () => clock, loadVitals: async () => { vitalsLoads++; return { onCLS: (cb) => { reporters.CLS = cb; }, onINP: (cb) => { reporters.INP = cb; }, onLCP: (cb) => { reporters.LCP = cb; } }; }, }); const commands = () => Array.from(win[DATA_LAYER] ?? [], (args) => Array.from(args)); const events = () => commands().filter(([command]) => command === 'event'); return { service, win, doc, scripts, listeners, cookies, deletedCookies, reporters, commands, events, storage, get vitalsLoads() { return vitalsLoads; }, advance: (ms) => { clock += ms; } }; } const tick = () => new Promise((resolve) => setImmediate(resolve)); test('every public canonical page has a finite measurement route', () => { for (const page of SITE_ROUTES) assert.equal(safeRoute(page.path), page.path); }); test('canonical page context restores the hostname without copying visitor URLs', () => { const f = fixture(); f.service.configure({ canonicalOrigin: 'https://thatstupidcomputer.com', ga4MeasurementId: 'G-ABCDE' }); f.service.setConsent('granted'); f.service.pageView('/about/'); f.service.pageView('/visitor@example.com?private=1#secret'); assert.deepEqual(f.events().map(([, , fields]) => fields.page_location), [ 'https://thatstupidcomputer.com/', 'https://thatstupidcomputer.com/about/', 'https://thatstupidcomputer.com/404/', ]); for (const [, , fields] of f.events()) { const url = new URL(fields.page_location); assert.equal(url.hostname, 'thatstupidcomputer.com'); assert.equal(url.search, ''); assert.equal(url.hash, ''); assert.equal(fields.page_referrer, ''); } assert.doesNotMatch(JSON.stringify(f.commands()), /studio\.example|visitor|private|secret|@|gclid/); }); test('missing or unsafe canonical origins cannot activate Google', () => { for (const canonicalOrigin of [undefined, '', 'http://thatstupidcomputer.com', '/about/', 'https://[credentials removed]@thatstupidcomputer.com', 'https://thatstupidcomputer.com/about/', 'https://thatstupidcomputer.com?email=private', 'https://thatstupidcomputer.com/#private', ' https://thatstupidcomputer.com', 42, {}]) { const f = fixture(); assert.equal(f.service.configure({ canonicalOrigin, ga4MeasurementId: 'G-ABCDE' }), false); f.service.setConsent('granted'); assert.equal(f.service.getStatus(), 'unconfigured'); assert.equal(f.scripts.length, 0); assert.equal(f.events().length, 0); } }); test('normalizing a canonical root does not duplicate configuration or pageviews', () => { const f = fixture(); f.service.configure({ canonicalOrigin: 'https://thatstupidcomputer.com/', ga4MeasurementId: 'G-ABCDE' }); f.service.setConsent('granted'); f.service.configure({ canonicalOrigin: 'https://thatstupidcomputer.com', ga4MeasurementId: 'G-ABCDE' }); assert.equal(f.events().length, 1); assert.equal(f.events()[0][2].page_location, 'https://thatstupidcomputer.com/'); assert.equal(f.commands().filter(([command]) => command === 'config').length, 1); assert.equal(f.scripts.length, 1); }); test('changing an approved origin updates context and invalidating it stops collection', () => { const f = fixture(); f.service.configure({ canonicalOrigin: 'https://thatstupidcomputer.com', ga4MeasurementId: 'G-ABCDE' }); f.service.setConsent('granted'); f.scripts[0].onload(); f.service.configure({ canonicalOrigin: 'https://new-studio.example.com', ga4MeasurementId: 'G-ABCDE' }); assert.equal(f.events().at(-1)[2].page_location, 'https://new-studio.example.com/'); f.service.configure({ canonicalOrigin: 'https://new-studio.example.com/?private=1', ga4MeasurementId: 'G-ABCDE' }); assert.equal(f.service.getStatus(), 'unconfigured'); assert.equal(f.service.pageView('/about/'), false); assert.equal(f.win['ga-disable-G-ABCDE'], true); }); test('valid runtime changes retain one vital subscription with the current destination and context', async () => { const f = fixture(); const initial = { canonicalOrigin: 'https://thatstupidcomputer.com', ga4MeasurementId: 'G-ABCDE' }; f.service.configure(initial); f.service.setConsent('granted'); f.scripts[0].onload(); await tick(); const report = f.reporters.LCP; for (const next of [ { ...initial, analyticsDebug: true }, { ...initial, canonicalOrigin: 'https://new-studio.example.com' }, { ...initial, ga4MeasurementId: 'G-FGHIJ' }, ]) { f.service.configure(next); await tick(); report({ name: 'LCP', value: 900, rating: 'good' }); const vitals = f.events().filter(([, name]) => name === 'web_vital'); assert.equal(vitals.length, 1, 'a configuration refresh must not silence the consented document'); assert.equal(vitals[0][2].send_to, next.ga4MeasurementId); assert.equal(vitals[0][2].page_location, `${next.canonicalOrigin}/`); assert.equal(vitals[0][2].debug_mode, next.analyticsDebug); assert.equal(f.reporters.LCP, report); } assert.equal(f.vitalsLoads, 1); assert.equal(f.scripts.length, 1); assert.equal(f.win['ga-disable-G-ABCDE'], true); assert.equal(f.win['ga-disable-G-FGHIJ'], false); }); test('a valid configuration refresh during the vital import preserves its eventual report', async () => { const f = fixture(); const config = { canonicalOrigin: 'https://thatstupidcomputer.com', ga4MeasurementId: 'G-ABCDE' }; f.service.configure(config); f.service.setConsent('granted'); await Promise.resolve(); assert.equal(f.vitalsLoads, 1); assert.equal(f.reporters.LCP, undefined, 'import has started but registration is still pending'); f.service.configure({ ...config, analyticsDebug: true }); await tick(); assert.equal(typeof f.reporters.LCP, 'function'); f.reporters.LCP({ name: 'LCP', value: 800, rating: 'good' }); assert.equal(f.events().filter(([, name]) => name === 'web_vital').length, 1); assert.equal(f.vitalsLoads, 1); }); test('invalidating configuration permanently discards document vitals even after configuration returns', async () => { const f = fixture(); const config = { canonicalOrigin: 'https://thatstupidcomputer.com', ga4MeasurementId: 'G-ABCDE' }; f.service.configure(config); f.service.setConsent('granted'); await tick(); const report = f.reporters.LCP; f.service.configure({}); report({ name: 'LCP', value: 1000, rating: 'good' }); assert.equal(f.events().length, 0); f.service.configure(config); report({ name: 'LCP', value: 1200, rating: 'good' }); assert.deepEqual(f.events().map(([, name]) => name), ['page_view']); assert.equal(f.vitalsLoads, 1); }); test('missing and invalid runtime IDs fail closed, even after opt-in', async () => { for (const id of [undefined, '', 'G-', 'UA-123456-1', 'G-VALID12?email=private', 'G-