/** @vitest-environment jsdom */
/**
* The wiring between the CMP signal and the recorder.
*
* replay.test.ts proves what `applyConsentDecision` does. This proves the widget
* actually calls it — the half that was missing, and the half no unit test of
* the replay module can catch: a shopper who opened the modal before the banner
* was answered and then accepted was never recorded, because the only code that
* could have started the recorder ran on modal open and had already decided.
*/
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, cleanup, waitFor } from '@testing-library/react';
import { App } from './App';
import { applyConsentDecision } from './replay';
import type { WidgetConfig } from './types';
vi.mock('./replay', () => ({
applyConsentDecision: vi.fn().mockResolvedValue( undefined ),
startReplay: vi.fn().mockResolvedValue( undefined ),
stopReplay: vi.fn(),
revokeReplay: vi.fn(),
MODAL_OVERLAY_CLASS: 'aisthetix-modal-overlay',
} ) );
const config = {
apiBaseUrl: 'https://brain.example.com',
publishableKey: 'pk_test',
productImage: 'https://cdn.example.com/shirt.jpg',
productTitle: 'Linen Shirt',
productId: '555',
variantId: '111',
locale: 'en',
analytics: {
replayKey: 'phc_browser',
ingestHost: 'https://ingest.aisthetix.fyi',
replayEnabled: true,
environment: 'staging',
storeId: 'store_1',
},
} as unknown as WidgetConfig;
beforeEach( () => {
localStorage.clear();
sessionStorage.clear();
document.body.innerHTML = '';
vi.mocked( applyConsentDecision ).mockClear();
} );
afterEach( () => {
cleanup();
document.body.innerHTML = '';
} );
/** The decision the bootstrap announces after reading the merchant's CMP. */
function announceConsent( productAnalytics: boolean ) {
document.dispatchEvent(
new CustomEvent( 'aisthetix:consent-changed', { detail: { productAnalytics } } )
);
}
describe( 'a CMP decision collected while the widget is mounted', () => {
it( 'is handed to the recorder as a grant', async () => {
render( );
announceConsent( true );
await waitFor( () => expect( applyConsentDecision ).toHaveBeenCalled() );
expect(
vi.mocked( applyConsentDecision ).mock.calls[ 0 ][ 0 ],
'a grant must reach the recorder'
).toBe( true );
} );
it( 'is handed to the recorder as a withdrawal', async () => {
render( );
announceConsent( false );
await waitFor( () => expect( applyConsentDecision ).toHaveBeenCalled() );
expect( vi.mocked( applyConsentDecision ).mock.calls[ 0 ][ 0 ] ).toBe( false );
} );
} );