Skip to content

Commit 357795d

Browse files
committed
test: add tests for selects
1 parent 6b6cc0f commit 357795d

File tree

2 files changed

+202
-0
lines changed

2 files changed

+202
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { mountSuspended } from '@nuxt/test-utils/runtime'
3+
import SelectBase from '~/components/Select/Base.vue'
4+
5+
describe('SelectBase', () => {
6+
describe('rendering', () => {
7+
it('renders native select with slot options', async () => {
8+
const component = await mountSuspended(SelectBase, {
9+
slots: {
10+
default:
11+
'<option value="option1">option 1</option><option value="option2">option 2</option>',
12+
},
13+
})
14+
const select = component.find('select')
15+
expect(select.exists()).toBe(true)
16+
expect(component.findAll('option')).toHaveLength(2)
17+
})
18+
19+
it('renders with initial modelValue', async () => {
20+
const component = await mountSuspended(SelectBase, {
21+
props: { modelValue: 'option2' },
22+
slots: {
23+
default:
24+
'<option value="option1">option 1</option><option value="option2">option 2</option>',
25+
},
26+
})
27+
const select = component.find('select').element
28+
expect(select.value).toBe('option2')
29+
})
30+
31+
it('renders without disabled attribute when disabled is false', async () => {
32+
const component = await mountSuspended(SelectBase, {
33+
props: { disabled: false },
34+
slots: { default: '<option value="option1">option 1</option>' },
35+
})
36+
const select = component.find('select')
37+
expect(select.attributes('disabled')).toBeUndefined()
38+
})
39+
40+
it('renders disabled when disabled is true', async () => {
41+
const component = await mountSuspended(SelectBase, {
42+
props: { disabled: true },
43+
slots: { default: '<option value="option1">option 1</option>' },
44+
})
45+
const select = component.find('select').element
46+
expect(select.disabled).toBe(true)
47+
})
48+
})
49+
50+
describe('v-model', () => {
51+
it('emits update:modelValue when selection changes', async () => {
52+
const component = await mountSuspended(SelectBase, {
53+
props: { modelValue: 'option1' },
54+
slots: {
55+
default:
56+
'<option value="option1">option 1</option><option value="option2">option 2</option>',
57+
},
58+
})
59+
const select = component.find('select')
60+
await select.setValue('option2')
61+
expect(component.emitted('update:modelValue')).toBeTruthy()
62+
expect(component.emitted('update:modelValue')?.at(-1)).toEqual(['option2'])
63+
})
64+
65+
it('reflects modelValue prop changes', async () => {
66+
const component = await mountSuspended(SelectBase, {
67+
props: { modelValue: 'option1' },
68+
slots: {
69+
default:
70+
'<option value="option1">option 1</option><option value="option2">option 2</option>',
71+
},
72+
})
73+
await component.setProps({ modelValue: 'option2' })
74+
const select = component.find('select').element
75+
expect(select.value).toBe('option2')
76+
})
77+
})
78+
})
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { mountSuspended } from '@nuxt/test-utils/runtime'
3+
import SelectField from '~/components/Select/Field.vue'
4+
5+
const defaultItems = [
6+
{ label: 'Option 1', value: 'option1' },
7+
{ label: 'Option 2', value: 'option2' },
8+
]
9+
10+
describe('SelectField', () => {
11+
describe('rendering', () => {
12+
it('renders options from items prop', async () => {
13+
const component = await mountSuspended(SelectField, {
14+
props: { id: 'select', items: defaultItems },
15+
})
16+
const options = component.findAll('option')
17+
expect(options).toHaveLength(2)
18+
expect(options[0]?.text()).toBe('Option 1')
19+
expect(options[1]?.text()).toBe('Option 2')
20+
expect(options[0]?.attributes('value')).toBe('option1')
21+
expect(options[1]?.attributes('value')).toBe('option2')
22+
})
23+
24+
it('renders label when provided', async () => {
25+
const component = await mountSuspended(SelectField, {
26+
props: { id: 'select', items: defaultItems, label: 'Choose one' },
27+
})
28+
const label = component.find('label')
29+
expect(label.exists()).toBe(true)
30+
expect(label.text()).toBe('Choose one')
31+
expect(label.attributes('for')).toBe('select')
32+
})
33+
34+
it('renders disabled option when item.disabled is true', async () => {
35+
const component = await mountSuspended(SelectField, {
36+
props: {
37+
id: 'select',
38+
items: [
39+
{ label: 'Enabled', value: 'on' },
40+
{ label: 'Disabled', value: 'off', disabled: true },
41+
],
42+
},
43+
})
44+
const options = component.findAll('option')
45+
expect(options[1]?.element?.disabled).toBe(true)
46+
})
47+
48+
it('applies block class when block is true', async () => {
49+
const component = await mountSuspended(SelectField, {
50+
props: { id: 'select', items: defaultItems, block: true },
51+
})
52+
const wrapper = component.find('.relative')
53+
expect(wrapper.classes()).toContain('w-full')
54+
const select = component.find('select')
55+
expect(select.classes()).toContain('w-full')
56+
})
57+
})
58+
59+
describe('v-model', () => {
60+
it('emits update:modelValue when option is selected', async () => {
61+
const component = await mountSuspended(SelectField, {
62+
props: { id: 'select', items: defaultItems, modelValue: 'option1' },
63+
})
64+
const select = component.find('select')
65+
await select.setValue('option2')
66+
expect(component.emitted('update:modelValue')).toBeTruthy()
67+
expect(component.emitted('update:modelValue')?.at(-1)).toEqual(['option2'])
68+
})
69+
70+
it('reflects modelValue prop changes', async () => {
71+
const component = await mountSuspended(SelectField, {
72+
props: { id: 'select', items: defaultItems, modelValue: 'option1' },
73+
})
74+
await component.setProps({ modelValue: 'option2' })
75+
const select = component.find('select').element
76+
expect(select.value).toBe('option2')
77+
})
78+
})
79+
80+
describe('disabled', () => {
81+
it('passes disabled to SelectBase', async () => {
82+
const component = await mountSuspended(SelectField, {
83+
props: { id: 'select', items: defaultItems, disabled: true },
84+
})
85+
const select = component.find('select').element
86+
expect(select.disabled).toBe(true)
87+
})
88+
})
89+
90+
describe('accessibility', () => {
91+
it('chevron has aria-hidden', async () => {
92+
const component = await mountSuspended(SelectField, {
93+
props: { id: 'select', items: defaultItems },
94+
})
95+
const chevron = component.find('span[aria-hidden="true"]')
96+
expect(chevron.exists()).toBe(true)
97+
})
98+
99+
it('render sr-only label when hiddenLabel is true', async () => {
100+
const component = await mountSuspended(SelectField, {
101+
props: {
102+
id: 'select',
103+
items: defaultItems,
104+
label: 'Hidden',
105+
hiddenLabel: true,
106+
},
107+
})
108+
const label = component.find('label')
109+
expect(label.exists()).toBe(true)
110+
expect(label.classes()).toContain('sr-only')
111+
expect(label.text()).toBe('Hidden')
112+
})
113+
114+
it('associates select with id', async () => {
115+
const component = await mountSuspended(SelectField, {
116+
props: { id: 'my-select', items: defaultItems, label: 'My Select' },
117+
})
118+
const select = component.find('select')
119+
expect(select.attributes('id')).toBe('my-select')
120+
const label = component.find('label')
121+
expect(label.attributes('for')).toBe('my-select')
122+
})
123+
})
124+
})

0 commit comments

Comments
 (0)