import {describe, expect, it} from 'vitest' import {mount} from '@vue/test-utils' import type {DefineComponent} from 'vue' import InputTextArea from './InputTextArea.vue' type InputTextAreaProps = { id?: string label?: string name?: string autocomplete?: string modelValue?: string | null size?: number | string textInput?: string textLabel?: string required?: boolean maxLength?: number showCounter?: boolean disabled?: boolean readonly?: boolean hint?: string error?: string success?: string rounded?: string } const InputTextAreaForTest = InputTextArea as DefineComponent describe('MalioInputTextArea', () => { it('renders the initial textarea value', () => { const wrapper = mount(InputTextAreaForTest, { props: {modelValue: 'initial textarea value'}, }) expect(wrapper.get('textarea').element.value).toBe('initial textarea value') }) it('renders the label text and reuses a provided id', () => { const wrapper = mount(InputTextAreaForTest, { props: {id: 'custom-textarea-id', label: 'Description'}, }) expect(wrapper.get('textarea').attributes('id')).toBe('custom-textarea-id') expect(wrapper.get('label').attributes('for')).toBe('custom-textarea-id') expect(wrapper.get('label').text()).toBe('Description') }) it('generates an id when missing', () => { const wrapper = mount(InputTextAreaForTest, { props: {label: 'Description'}, }) const textareaId = wrapper.get('textarea').attributes('id') expect(textareaId?.startsWith('malio-input-textarea-')).toBe(true) expect(wrapper.get('label').attributes('for')).toBe(textareaId) }) it('applies name, autocomplete and rows attributes', () => { const wrapper = mount(InputTextAreaForTest, { props: {name: 'bio', autocomplete: 'on', size: 4}, }) expect(wrapper.get('textarea').attributes('name')).toBe('bio') expect(wrapper.get('textarea').attributes('autocomplete')).toBe('on') expect(wrapper.get('textarea').attributes('rows')).toBe('4') }) it('sets required, readonly and disabled attributes', () => { const wrapper = mount(InputTextAreaForTest, { props: { required: true, readonly: true, disabled: true, }, }) expect(wrapper.get('textarea').attributes('required')).toBeDefined() expect(wrapper.get('textarea').attributes('readonly')).toBeDefined() expect(wrapper.get('textarea').attributes('disabled')).toBeDefined() expect(wrapper.get('textarea').classes()).toContain('cursor-not-allowed') }) it('emits update:modelValue on input change', async () => { const wrapper = mount(InputTextAreaForTest, { props: {modelValue: ''}, }) await wrapper.get('textarea').setValue('new textarea value') expect(wrapper.emitted('update:modelValue')?.[0]).toEqual(['new textarea value']) }) it('shows the character counter when enabled', () => { const wrapper = mount(InputTextAreaForTest, { props: { modelValue: 'hello', showCounter: true, maxLength: 20, }, }) expect(wrapper.get('span.text-xs').text()).toBe('5/20') expect(wrapper.get('textarea').classes()).toContain('pb-6') }) it('shows hint message in muted color', () => { const wrapper = mount(InputTextAreaForTest, { props: {hint: 'Helpful hint'}, }) expect(wrapper.get('p.text-m-muted').text()).toBe('Helpful hint') }) it('shows error state on textarea and label', () => { const wrapper = mount(InputTextAreaForTest, { props: { label: 'Description', error: 'Textarea error', }, }) expect(wrapper.get('textarea').classes()).toContain('border-m-error') expect(wrapper.get('label').classes()).toContain('text-m-error') expect(wrapper.get('p.text-m-error').text()).toBe('Textarea error') expect(wrapper.get('textarea').attributes('aria-invalid')).toBe('true') }) it('shows success state on textarea and label', () => { const wrapper = mount(InputTextAreaForTest, { props: { label: 'Description', success: 'Textarea success', }, }) expect(wrapper.get('textarea').classes()).toContain('border-m-success') expect(wrapper.get('label').classes()).toContain('text-m-success') expect(wrapper.get('p.text-m-success').text()).toBe('Textarea success') }) it('prioritizes error over success', () => { const wrapper = mount(InputTextAreaForTest, { props: { error: 'Textarea error', success: 'Textarea success', }, }) expect(wrapper.get('textarea').classes()).toContain('border-m-error') expect(wrapper.find('p.text-m-success').exists()).toBe(false) expect(wrapper.get('p.text-m-error').text()).toBe('Textarea error') }) })