import { buildExperimentAssignmentScript, buildExperimentHeadSnippet, collectExperimentIds, } from '../src/analytics/experiments' import { NextAnalyticsProjectPlugin } from '../src/analytics/project-plugin' /** * A/B tests: the generator finds the experiments by their attributes, and the * head script picks ONE arm per visitor before the body is parsed, hides the * other, keeps the choice, and publishes it for the tracker. */ const element = (attrs: Record, children: any[] = []) => ({ type: 'element', content: { elementType: 'container', attrs: Object.fromEntries( Object.entries(attrs).map(([key, value]) => [key, { type: 'static', content: value }]) ), children, }, }) const uidlWith = (rootChildren: any[], componentChildren: any[] = []) => ({ globals: { customCode: { head: '' } }, root: { node: element({}, rootChildren) }, components: componentChildren.length ? { Hero: { node: element({}, componentChildren) } } : {}, } as any) function runScript(ids: string[], storage: Record, random = 0.2) { const styles: string[] = [] const fakeWindow = { localStorage: { getItem: (key: string) => (key in storage ? storage[key] : null), setItem: (key: string, value: string) => { storage[key] = value }, }, } as any const fakeDocument = { createElement: () => ({ textContent: '' }), head: { appendChild: (node: { textContent: string }) => styles.push(node.textContent) }, } new Function('window', 'document', 'Math', buildExperimentAssignmentScript(ids))( fakeWindow, fakeDocument, Object.assign(Object.create(Math), { random: () => random }) ) return { assigned: fakeWindow.__tpExp as Record, styles } } describe('experiments — finding them in the project', () => { it('collects the ids from pages and components, once each, sorted', () => { const uidl = uidlWith( [ element({ 'data-tq-exp': 'hero-1', 'data-tq-exp-variant': 'a' }), element({ 'data-tq-exp': 'hero-1', 'data-tq-exp-variant': 'b' }), element({ 'data-tq-exp': 'BAD ID', 'data-tq-exp-variant': 'a' }), ], [element({ 'data-tq-exp': 'cta-2', 'data-tq-exp-variant': 'a' })] ) expect(collectExperimentIds(uidl)).toEqual(['cta-2', 'hero-1']) expect(collectExperimentIds(uidlWith([]))).toEqual([]) }) it('puts the assignment script first in the head, only when there are experiments', async () => { const plugin = new NextAnalyticsProjectPlugin() const uidl = uidlWith([element({ 'data-tq-exp': 'hero-1', 'data-tq-exp-variant': 'a' })]) await plugin.runBefore({ uidl, files: new Map() } as any) expect(uidl.globals.customCode.head.startsWith('