import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query' import { mount } from '@vue/test-utils' import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' import { defineComponent, h, ref } from 'vue' vi.mock('@/lib/axios', () => ({ apiClient: { get: vi.fn() }, })) import { apiClient } from '@/lib/axios' import { usePublicFormTimeSlots } from '@/composables/api/usePublicFormTimeSlots' import type { PublicFormTimeSlot } from '@form-schema/types/formBuilder' interface MockedApi { get: ReturnType } const mocked = apiClient as unknown as MockedApi function mountHook(tokenValue: string) { const result: { query: ReturnType | null } = { query: null } const Host = defineComponent({ setup() { result.query = usePublicFormTimeSlots(ref(tokenValue)) return () => h('div') }, }) const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } }) const wrapper = mount(Host, { global: { plugins: [[VueQueryPlugin, { queryClient }]] }, }) return { wrapper, result } } function timeSlot(partial: Partial = {}): PublicFormTimeSlot { return { id: partial.id ?? '01A', name: partial.name ?? 'Zaterdag middag', date: partial.date ?? '2026-07-11', start_time: partial.start_time ?? '12:00:00', end_time: partial.end_time ?? '18:00:00', duration_hours: partial.duration_hours ?? 6, event_id: partial.event_id ?? 'evt_1', event_name: partial.event_name ?? 'Echt Feesten 2026', } } function flush(): Promise { return new Promise(resolve => setTimeout(resolve, 0)) } describe('usePublicFormTimeSlots', () => { beforeEach(() => { vi.clearAllMocks() }) afterEach(() => { vi.clearAllMocks() }) it('fetches and parses PublicFormTimeSlot[] on happy path', async () => { const slot = timeSlot() mocked.get.mockResolvedValueOnce({ data: { data: [slot] } }) const { result } = mountHook('TKN42') await flush() await flush() expect(mocked.get).toHaveBeenCalledWith('/public/forms/TKN42/time-slots') expect(result.query?.data.value).toEqual([slot]) }) it('is disabled when the token ref is empty', async () => { const { result } = mountHook('') await flush() expect(mocked.get).not.toHaveBeenCalled() expect(result.query?.isFetching.value).toBe(false) }) it('surfaces errors via isError', async () => { mocked.get.mockRejectedValueOnce(new Error('network')) const { result } = mountHook('TKN99') await flush() await flush() expect(result.query?.isError.value).toBe(true) }) })