import test from 'node:test'; import assert from 'node:assert/strict'; import vm from 'node:vm'; import { injectMindSpaceAnalytics, pseudonymizeAnalyticsId, resolveAnalyticsOwnerSegment, resolveAnalyticsOwnerLabel, resolveMindSpaceAnalyticsConfig, sendMindSpaceAnalyticsEvent, } from './mindspace-analytics.mjs'; test('analytics config is disabled unless explicitly enabled and configured', () => { assert.equal(resolveMindSpaceAnalyticsConfig({ MEMIND_ANALYTICS_ENABLED: 'true' }).enabled, false); assert.equal(resolveMindSpaceAnalyticsConfig({ MEMIND_ANALYTICS_ENABLED: 'true', MEMIND_ANALYTICS_WEBSITE_ID: 'local-website', }).enabled, false); const config = resolveMindSpaceAnalyticsConfig({ MEMIND_ANALYTICS_ENABLED: 'true', MEMIND_ANALYTICS_URL: 'http://127.0.0.1:3200', MEMIND_ANALYTICS_WEBSITE_ID: 'local-website', MEMIND_ANALYTICS_ID_SECRET: 'local-secret', }); assert.equal(config.enabled, true); assert.equal(config.analyticsUrl, 'http://127.0.0.1:3200'); assert.equal(config.hostPath, '/analytics'); }); test('owner ids are stable pseudonyms and never expose the source id', () => { const first = pseudonymizeAnalyticsId('user-123', 'secret'); assert.equal(first, pseudonymizeAnalyticsId('user-123', 'secret')); assert.notEqual(first, 'user-123'); assert.notEqual(first, pseudonymizeAnalyticsId('user-456', 'secret')); }); test('owner segments come from server-side Memind user profile data', () => { assert.equal(resolveAnalyticsOwnerSegment({ role: 'admin' }), 'admin'); assert.equal(resolveAnalyticsOwnerSegment({ role: 'user', planType: 'pro' }), 'plan:pro'); assert.equal(resolveAnalyticsOwnerSegment({ role: 'user' }), 'plan:free'); }); test('owner labels are readable but bounded and stripped of control characters', () => { assert.equal(resolveAnalyticsOwnerLabel({ displayName: '张三\n管理员' }), '张三 管理员'); assert.equal(resolveAnalyticsOwnerLabel({}), '未命名用户'); }); test('injects one local same-origin tracker with page dimensions', () => { const html = 'Demo

Demo

'; const out = injectMindSpaceAnalytics(html, { ownerId: 'user-123', ownerLabel: '张三', pageId: 'page-1', publicationId: 'pub-1', config: { enabled: true, websiteId: 'local-website', idSecret: 'secret', scriptPath: '/analytics/script.js', hostPath: '/analytics', domains: '127.0.0.1,localhost', }, }); assert.match(out, /src="\/analytics\/script\.js"/); assert.match(out, /data-host-url="\/analytics"/); assert.match(out, /data-auto-track="false"/); assert.match(out, /window\.umami\.identify\(d\.owner_id,\{username:d\.username,memind_page_url:location\.href,owner_segment:d\.owner_segment,channel:d\.channel\}\)/); assert.match(out, /function pageview\(\).*window\.umami\.track\(\)/); assert.ok(out.indexOf('identify();pageview();') > 0); assert.doesNotMatch(out, /t\('page_view'\)/); assert.match(out, /page_id/); assert.match(out, /owner_segment/); assert.doesNotMatch(out, /owner_label/); assert.match(out, /"username":"张三"/); assert.match(out, /page_click/); assert.match(out, /page_form_submit/); assert.match(out, /page_scroll_/); assert.match(out, /page_engaged_10s/); assert.doesNotMatch(out, /user-123/); assert.equal(injectMindSpaceAnalytics(out, { ownerId: 'user-123', config: { enabled: true, websiteId: 'local-website', idSecret: 'secret' } }), out); }); test('identifies the pseudonymous owner before sending a standard page view', () => { const out = injectMindSpaceAnalytics('', { ownerId: 'user-123', ownerSegment: 'plan:pro', ownerLabel: '张三', channel: 'h5', config: { enabled: true, websiteId: 'local-website', idSecret: 'secret', scriptPath: '/analytics/script.js', hostPath: '/analytics', }, }); const inlineScript = out.match(/