109 lines
3.5 KiB
TypeScript
109 lines
3.5 KiB
TypeScript
import { http, HttpResponse } from 'msw'
|
|
import { test, expect } from './msw-setup'
|
|
import type { StoredEvent } from '../src/composables/useEventStorage'
|
|
|
|
const STORAGE_KEY = 'fete:events'
|
|
|
|
const fullEvent = {
|
|
eventToken: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
|
|
title: 'Sommerfest am See',
|
|
description: 'Bring your own drinks!',
|
|
dateTime: '2026-07-15T18:00:00+02:00',
|
|
timezone: 'Europe/Berlin',
|
|
location: 'Stadtpark Berlin',
|
|
attendeeCount: 12,
|
|
cancelled: false,
|
|
}
|
|
|
|
const cancelledEvent = {
|
|
...fullEvent,
|
|
cancelled: true,
|
|
cancellationReason: 'Bad weather',
|
|
}
|
|
|
|
function seedEvents(events: StoredEvent[]): string {
|
|
return `window.localStorage.setItem('${STORAGE_KEY}', ${JSON.stringify(JSON.stringify(events))})`
|
|
}
|
|
|
|
function rsvpSeed(): StoredEvent {
|
|
return {
|
|
eventToken: fullEvent.eventToken,
|
|
title: fullEvent.title,
|
|
dateTime: fullEvent.dateTime,
|
|
rsvpToken: 'd4e5f6a7-b8c9-0123-4567-890abcdef012',
|
|
rsvpName: 'Anna',
|
|
}
|
|
}
|
|
|
|
function organizerSeed(): StoredEvent {
|
|
return {
|
|
eventToken: fullEvent.eventToken,
|
|
title: fullEvent.title,
|
|
dateTime: fullEvent.dateTime,
|
|
organizerToken: 'org-token-1234',
|
|
}
|
|
}
|
|
|
|
test.describe('iCal download: calendar button visibility', () => {
|
|
test('calendar button visible for pre-RSVP visitor', async ({ page, network }) => {
|
|
network.use(
|
|
http.get('*/api/events/:token', () => HttpResponse.json(fullEvent)),
|
|
)
|
|
await page.goto(`/events/${fullEvent.eventToken}`)
|
|
|
|
const calendarBtn = page.getByRole('button', { name: /add to calendar/i })
|
|
await expect(calendarBtn).toBeVisible()
|
|
})
|
|
|
|
test('calendar button visible for post-RSVP attendee', async ({ page, network }) => {
|
|
network.use(
|
|
http.get('*/api/events/:token', () => HttpResponse.json(fullEvent)),
|
|
)
|
|
await page.addInitScript(seedEvents([rsvpSeed()]))
|
|
await page.goto(`/events/${fullEvent.eventToken}`)
|
|
|
|
const calendarBtn = page.getByRole('button', { name: /add to calendar/i })
|
|
await expect(calendarBtn).toBeVisible()
|
|
})
|
|
|
|
test('calendar button visible for organizer', async ({ page, network }) => {
|
|
network.use(
|
|
http.get('*/api/events/:token', () => HttpResponse.json(fullEvent)),
|
|
http.get('*/api/events/:token/attendees*', () =>
|
|
HttpResponse.json({ attendees: [] }),
|
|
),
|
|
)
|
|
await page.addInitScript(seedEvents([organizerSeed()]))
|
|
await page.goto(`/events/${fullEvent.eventToken}`)
|
|
|
|
const calendarBtn = page.getByRole('button', { name: /add to calendar/i })
|
|
await expect(calendarBtn).toBeVisible()
|
|
})
|
|
|
|
test('calendar button NOT visible for cancelled event', async ({ page, network }) => {
|
|
network.use(
|
|
http.get('*/api/events/:token', () => HttpResponse.json(cancelledEvent)),
|
|
)
|
|
await page.goto(`/events/${fullEvent.eventToken}`)
|
|
|
|
const calendarBtn = page.getByRole('button', { name: /add to calendar/i })
|
|
await expect(calendarBtn).not.toBeVisible()
|
|
})
|
|
})
|
|
|
|
test.describe('iCal download: file generation', () => {
|
|
test('triggers download with correct filename', async ({ page, network }) => {
|
|
network.use(
|
|
http.get('*/api/events/:token', () => HttpResponse.json(fullEvent)),
|
|
)
|
|
await page.goto(`/events/${fullEvent.eventToken}`)
|
|
|
|
// Intercept the download by overriding the click-link mechanism
|
|
const downloadPromise = page.waitForEvent('download')
|
|
await page.getByRole('button', { name: /add to calendar/i }).click()
|
|
const download = await downloadPromise
|
|
|
|
expect(download.suggestedFilename()).toBe('sommerfest-am-see.ics')
|
|
})
|
|
})
|