Implement academy analytics, billing, and web stories updates

This commit is contained in:
2026-05-26 07:27:29 +02:00
parent 456c3d6bb0
commit 0b33a1b074
177 changed files with 27360 additions and 2685 deletions

View File

@@ -0,0 +1,70 @@
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()
})