Files
crewli/apps/portal/tests/composables/api/usePublicFormSections.spec.ts
bert.hausmans dda60ed5e4 refactor(form-schema): extract schema types and schema-driven behaviors to shared package
Moves formBuilder types, formValidation, useConditionalLogic, useFormSteps,
and formatFieldValue from apps/portal/src to packages/form-schema/src.
Adds @form-schema path alias to both apps/portal and apps/app.
Vue field components remain per-app to allow independent visual evolution.
Behavior-neutral: all 35 Vitest tests green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 23:57:39 +02:00

84 lines
2.5 KiB
TypeScript

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 { usePublicFormSections } from '@/composables/api/usePublicFormSections'
import type { PublicFormSectionOption } from '@form-schema/types/formBuilder'
interface MockedApi { get: ReturnType<typeof vi.fn> }
const mocked = apiClient as unknown as MockedApi
function mountHook(tokenValue: string) {
const result: { query: ReturnType<typeof usePublicFormSections> | null } = { query: null }
const Host = defineComponent({
setup() {
result.query = usePublicFormSections(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 section(partial: Partial<PublicFormSectionOption> = {}): PublicFormSectionOption {
return {
id: partial.id ?? '01B',
name: partial.name ?? 'Bar',
category: partial.category ?? 'Horeca',
icon: partial.icon ?? 'tabler-beer',
registration_description: partial.registration_description ?? 'Tappen en serveren',
}
}
function flush(): Promise<void> {
return new Promise(resolve => setTimeout(resolve, 0))
}
describe('usePublicFormSections', () => {
beforeEach(() => { vi.clearAllMocks() })
afterEach(() => { vi.clearAllMocks() })
it('fetches and parses PublicFormSectionOption[] on happy path', async () => {
const s = section()
mocked.get.mockResolvedValueOnce({ data: { data: [s] } })
const { result } = mountHook('TKN42')
await flush()
await flush()
expect(mocked.get).toHaveBeenCalledWith('/public/forms/TKN42/sections')
expect(result.query?.data.value).toEqual([s])
})
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('boom'))
const { result } = mountHook('TKN99')
await flush()
await flush()
expect(result.query?.isError.value).toBe(true)
})
})