// @vitest-environment jsdom /** * Opt-in consent gate for the un-delayable bootstrap loader (assets/bootstrap.js). * * The bootstrap exposes its event sender as window.aisthetixTrackEvent, so we can * drive the real gate end-to-end: load the file into jsdom, mock fetch + * AISTHETIX_CONFIG, and assert whether an event is POSTed. * * Contract (2026-07-18 wordpress.org compliance): * - default (no CMP, analyticsEnabled false) -> NO event. * - analyticsEnabled true, no CMP -> event. * - CMP grants (analyticsEnabled false) -> event. * - CMP denies (analyticsEnabled true) -> NO event. */ import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; const BOOTSTRAP_SRC = readFileSync( resolve( __dirname, '../../assets/bootstrap.js' ), 'utf8' ); function loadBootstrap( config: Record< string, unknown > ) { ( window as any ).AISTHETIX_CONFIG = config; // Execute the IIFE in the jsdom window scope; it re-exposes aisthetixTrackEvent. // eslint-disable-next-line no-new-func new Function( BOOTSTRAP_SRC )(); } function track() { ( window as any ).aisthetixTrackEvent( 'product_viewed', { productId: '1' } ); } const BASE = { eventsUrl: 'https://woo.aisthetix.fyi/api/events', publishableKey: 'pk_test', }; describe( 'bootstrap analytics consent gate (opt-in)', () => { let fetchMock: ReturnType< typeof vi.fn >; beforeEach( () => { fetchMock = vi.fn( () => Promise.resolve( { ok: true } ) ); ( window as any ).fetch = fetchMock; delete ( window as any ).Cookiebot; delete ( window as any ).gtag; delete ( window as any ).google_tag_data; delete ( window as any ).dataLayer; document.cookie = 'cmplz_statistics=; expires=Thu, 01 Jan 1970 00:00:00 GMT'; } ); afterEach( () => { delete ( window as any ).aisthetixTrackEvent; delete ( window as any ).AISTHETIX_CONFIG; vi.restoreAllMocks(); } ); it( 'does NOT send when analytics is off and no CMP is present (default)', () => { loadBootstrap( { ...BASE, analyticsEnabled: false } ); track(); expect( fetchMock ).not.toHaveBeenCalled(); } ); it( 'sends when the merchant enabled analytics and no CMP is present', () => { loadBootstrap( { ...BASE, analyticsEnabled: true } ); track(); expect( fetchMock ).toHaveBeenCalledTimes( 1 ); } ); it( 'sends when a CMP grants analytics even if the merchant toggle is off', () => { ( window as any ).Cookiebot = { consent: { statistics: true } }; loadBootstrap( { ...BASE, analyticsEnabled: false } ); track(); expect( fetchMock ).toHaveBeenCalledTimes( 1 ); } ); it( 'does NOT send when a CMP denies analytics even if the merchant toggle is on', () => { ( window as any ).Cookiebot = { consent: { statistics: false } }; loadBootstrap( { ...BASE, analyticsEnabled: true } ); track(); expect( fetchMock ).not.toHaveBeenCalled(); } ); } );