import { mount } from '@vue/test-utils' import { describe, expect, it } from 'vitest' import FieldRenderer from '@/components/public-form/FieldRenderer.vue' import { FormFieldType } from '@/types/formBuilder' import type { PublicFormField } from '@/types/formBuilder' function makeField(partial: Partial): PublicFormField { return { id: partial.id ?? 'id', slug: partial.slug ?? 'slug', field_type: partial.field_type ?? FormFieldType.TEXT, label: partial.label ?? 'Label', help_text: partial.help_text ?? null, options: partial.options ?? null, available_tags: partial.available_tags ?? null, validation_rules: partial.validation_rules ?? null, is_required: partial.is_required ?? false, display_width: partial.display_width ?? 'full', conditional_logic: partial.conditional_logic ?? null, sort_order: partial.sort_order ?? 0, form_schema_section_id: partial.form_schema_section_id ?? null, } } function mountRenderer(field: PublicFormField, allValues: Record = {}) { return mount(FieldRenderer, { props: { field, modelValue: undefined, allValues }, global: { stubs: { VCol: { name: 'VCol', template: '
' }, VAlert: { name: 'VAlert', template: '
' }, FieldText: { name: 'FieldText', template: '
' }, FieldTextarea: { name: 'FieldTextarea', template: '
' }, FieldEmail: { name: 'FieldEmail', template: '
' }, FieldPhone: { name: 'FieldPhone', template: '
' }, FieldNumber: { name: 'FieldNumber', template: '
' }, FieldDate: { name: 'FieldDate', template: '
' }, FieldBoolean: { name: 'FieldBoolean', template: '
' }, FieldRadio: { name: 'FieldRadio', template: '
' }, FieldSelect: { name: 'FieldSelect', template: '
' }, FieldMultiselect: { name: 'FieldMultiselect', template: '
' }, FieldCheckboxList: { name: 'FieldCheckboxList', template: '
' }, FieldHeading: { name: 'FieldHeading', template: '
' }, FieldParagraph: { name: 'FieldParagraph', template: '
' }, FieldUrl: { name: 'FieldUrl', template: '
' }, }, }, }) } describe('FieldRenderer', () => { it.each<[string, string]>([ [FormFieldType.TEXT, 'field-text-stub'], [FormFieldType.TEXTAREA, 'field-textarea-stub'], [FormFieldType.EMAIL, 'field-email-stub'], [FormFieldType.PHONE, 'field-phone-stub'], [FormFieldType.NUMBER, 'field-number-stub'], [FormFieldType.DATE, 'field-date-stub'], [FormFieldType.BOOLEAN, 'field-boolean-stub'], [FormFieldType.RADIO, 'field-radio-stub'], [FormFieldType.SELECT, 'field-select-stub'], [FormFieldType.MULTISELECT, 'field-multiselect-stub'], [FormFieldType.CHECKBOX_LIST, 'field-checkboxlist-stub'], [FormFieldType.HEADING, 'field-heading-stub'], [FormFieldType.PARAGRAPH, 'field-paragraph-stub'], [FormFieldType.URL, 'field-url-stub'], ])('dispatches to the right component for %s', (fieldType, className) => { const wrapper = mountRenderer(makeField({ field_type: fieldType as typeof FormFieldType[keyof typeof FormFieldType] })) expect(wrapper.find(`.${className}`).exists()).toBe(true) }) it.each([ FormFieldType.TAG_PICKER, FormFieldType.AVAILABILITY_PICKER, FormFieldType.SECTION_PRIORITY, FormFieldType.FILE_UPLOAD, FormFieldType.IMAGE_UPLOAD, FormFieldType.SIGNATURE, FormFieldType.TABLE_ROWS, FormFieldType.DATETIME, ])('renders placeholder alert for out-of-scope type %s', fieldType => { const wrapper = mountRenderer(makeField({ field_type: fieldType as typeof FormFieldType[keyof typeof FormFieldType] })) expect(wrapper.find('.v-alert-stub').exists()).toBe(true) expect(wrapper.text()).toContain('binnenkort ondersteund') }) it('hides the field when conditional logic evaluates to false', () => { const field = makeField({ field_type: FormFieldType.TEXT, conditional_logic: { show_when: { all: [{ field_slug: 'gate', operator: 'equals', value: 'yes' }] }, }, }) const hidden = mountRenderer(field, { gate: 'no' }) expect(hidden.find('.field-text-stub').exists()).toBe(false) expect(hidden.find('.v-col-stub').exists()).toBe(false) const shown = mountRenderer(field, { gate: 'yes' }) expect(shown.find('.field-text-stub').exists()).toBe(true) }) })