Files
SkinbaseNova/resources/js/lib/academyAnalytics.test.js

70 lines
2.0 KiB
JavaScript

function prepareEnvironment() {
document.head.innerHTML = '<meta name="csrf-token" content="csrf-token" />'
vi.spyOn(Storage.prototype, 'getItem').mockReturnValue('visitor-123')
vi.spyOn(Storage.prototype, 'setItem').mockImplementation(() => {})
globalThis.fetch = vi.fn(() => Promise.resolve({ ok: true, headers: { get: () => 'application/json' }, json: () => Promise.resolve({ ok: true }) }))
}
function cleanupEnvironment() {
vi.restoreAllMocks()
document.head.innerHTML = ''
}
test('academy search click attribution uses sendBeacon without blocking navigation', async () => {
prepareEnvironment()
const { trackAcademySearchResultClick } = await import('./academyAnalytics.js')
Object.defineProperty(navigator, 'sendBeacon', {
configurable: true,
value: vi.fn(() => true),
})
const result = trackAcademySearchResultClick({
eventUrl: '/academy/analytics/events',
pageName: 'academy_prompts_index',
}, {
query: 'robot mascot',
resultsCount: 12,
filters: { difficulty: 'beginner' },
}, {
contentType: 'academy_prompt',
contentId: 123,
position: 3,
})
expect(result).toBeUndefined()
expect(navigator.sendBeacon).toHaveBeenCalledTimes(1)
expect(globalThis.fetch).not.toHaveBeenCalled()
cleanupEnvironment()
})
test('academy search click attribution falls back to keepalive fetch when sendBeacon cannot queue', async () => {
prepareEnvironment()
const { trackAcademySearchResultClick } = await import('./academyAnalytics.js')
Object.defineProperty(navigator, 'sendBeacon', {
configurable: true,
value: vi.fn(() => false),
})
trackAcademySearchResultClick({
eventUrl: '/academy/analytics/events',
pageName: 'academy_prompts_index',
}, {
query: 'robot mascot',
resultsCount: 12,
filters: { difficulty: 'beginner' },
}, {
contentType: 'academy_prompt',
contentId: 123,
position: 3,
})
expect(globalThis.fetch).toHaveBeenCalledTimes(1)
expect(globalThis.fetch.mock.calls[0][1].keepalive).toBe(true)
cleanupEnvironment()
})