Add organizer-only attendee list to event detail view (011)
All checks were successful
CI / backend-test (push) Successful in 59s
CI / frontend-test (push) Successful in 23s
CI / frontend-e2e (push) Successful in 1m11s
CI / build-and-publish (push) Has been skipped

New GET /events/{token}/attendees endpoint returns attendee names when
a valid organizer token is provided (403 otherwise). The frontend
conditionally renders the list below the attendee count for organizers,
silently degrading for visitors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 18:34:27 +01:00
parent d7ed28e036
commit 763811fce6
24 changed files with 1307 additions and 3 deletions

View File

@@ -339,6 +339,42 @@ describe('EventDetailView', () => {
wrapper.unmount()
})
// Attendee list (organizer)
it('shows attendee list for organizer', async () => {
mockGetOrganizerToken.mockReturnValue('org-token-123')
mockLoadedEvent()
vi.mocked(api.GET)
.mockResolvedValueOnce({
data: fullEvent,
error: undefined,
response: new Response(null, { status: 200 }),
} as never)
.mockResolvedValueOnce({
data: { attendees: [{ name: 'Alice' }, { name: 'Bob' }] },
error: undefined,
response: new Response(null, { status: 200 }),
} as never)
const wrapper = await mountWithToken()
await flushPromises()
expect(wrapper.find('.attendee-list').exists()).toBe(true)
expect(wrapper.text()).toContain('Alice')
expect(wrapper.text()).toContain('Bob')
expect(wrapper.find('.attendee-list__heading').text()).toBe('2 Attendees')
wrapper.unmount()
})
it('does not show attendee list for visitor', async () => {
mockLoadedEvent()
const wrapper = await mountWithToken()
await flushPromises()
expect(wrapper.find('.attendee-list').exists()).toBe(false)
wrapper.unmount()
})
it('shows error when RSVP submission fails', async () => {
mockLoadedEvent()
vi.mocked(api.POST).mockResolvedValue({