mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-07 01:28:30 +08:00
269 lines
7.7 KiB
TypeScript
269 lines
7.7 KiB
TypeScript
import { mount } from '@vue/test-utils'
|
|
import WdSegmented from '@/uni_modules/wot-design-uni/components/wd-segmented/wd-segmented.vue'
|
|
import { describe, test, expect, vi, beforeEach } from 'vitest'
|
|
import { nextTick } from 'vue'
|
|
|
|
describe('分段器组件', () => {
|
|
beforeEach(() => {
|
|
// 模拟 createSelectorQuery 方法
|
|
vi.spyOn(uni, 'createSelectorQuery').mockImplementation(() => {
|
|
// 创建一个更简单但更健壮的 mock 对象
|
|
let isSelectAll = false
|
|
let boundingClientRectCallback: ((rect: any) => void) | null = null
|
|
|
|
const mockQuery: any = {
|
|
// 简化 in 方法,直接返回 mockQuery 自身
|
|
in: vi.fn(() => {
|
|
return mockQuery
|
|
}),
|
|
|
|
select: vi.fn((_) => {
|
|
// 忽略选择器,只设置 isSelectAll 标志
|
|
isSelectAll = false
|
|
return mockQuery
|
|
}),
|
|
|
|
selectAll: vi.fn((_) => {
|
|
// 忽略选择器,只设置 isSelectAll 标志
|
|
isSelectAll = true
|
|
return mockQuery
|
|
}),
|
|
|
|
selectViewport: vi.fn(() => {
|
|
// 忽略选择器,只设置 isSelectAll 标志
|
|
isSelectAll = false
|
|
return mockQuery
|
|
}),
|
|
|
|
boundingClientRect: vi.fn((callback) => {
|
|
boundingClientRectCallback = callback
|
|
return mockQuery
|
|
}),
|
|
|
|
exec: vi.fn(() => {
|
|
// 为所有查询返回固定的模拟数据
|
|
// 这样无论是什么选择器,都能返回有效的数据
|
|
const mockRects = Array(3)
|
|
.fill(0)
|
|
.map((_, index) => ({
|
|
id: `item-${index}`,
|
|
dataset: {},
|
|
width: 100,
|
|
height: 40,
|
|
top: 0,
|
|
left: index * 100,
|
|
right: (index + 1) * 100,
|
|
bottom: 40
|
|
}))
|
|
|
|
// 调用回调函数
|
|
if (boundingClientRectCallback) {
|
|
if (isSelectAll) {
|
|
boundingClientRectCallback(mockRects)
|
|
} else {
|
|
boundingClientRectCallback(mockRects[0])
|
|
}
|
|
}
|
|
|
|
return Promise.resolve(isSelectAll ? [mockRects] : [mockRects[0]])
|
|
})
|
|
}
|
|
|
|
return mockQuery as any
|
|
})
|
|
|
|
// 确保 uni.vibrateShort 是一个函数
|
|
if (typeof uni.vibrateShort !== 'function') {
|
|
uni.vibrateShort = vi.fn()
|
|
}
|
|
})
|
|
// 测试基本渲染
|
|
test('使用默认属性渲染分段器', async () => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2', 'option3']
|
|
}
|
|
})
|
|
await wrapper.vm.$nextTick()
|
|
expect(wrapper.classes()).toContain('wd-segmented')
|
|
expect(wrapper.findAll('.wd-segmented__item').length).toBe(3)
|
|
})
|
|
|
|
// 测试选中项
|
|
test('高亮显示激活项', async () => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option2',
|
|
options: ['option1', 'option2', 'option3']
|
|
}
|
|
})
|
|
|
|
await nextTick()
|
|
|
|
// 检查选中项
|
|
const items = wrapper.findAll('.wd-segmented__item')
|
|
expect(items[1].classes()).toContain('is-active')
|
|
})
|
|
|
|
// 测试点击事件
|
|
test('点击项目时触发事件', async () => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2', 'option3']
|
|
}
|
|
})
|
|
|
|
// 点击第二个选项
|
|
await wrapper.findAll('.wd-segmented__item')[1].trigger('click')
|
|
|
|
// 验证事件
|
|
const emitted = wrapper.emitted() as Record<string, any[]>
|
|
expect(emitted['update:value']).toBeTruthy()
|
|
expect(emitted['update:value'][0]).toEqual(['option2'])
|
|
|
|
expect(emitted['change']).toBeTruthy()
|
|
expect(emitted['change'][0][0]).toEqual({ value: 'option2' })
|
|
|
|
expect(emitted['click']).toBeTruthy()
|
|
expect(emitted['click'][0][0]).toEqual({ value: 'option2' })
|
|
})
|
|
|
|
// 测试禁用状态
|
|
test('禁用状态下禁用分段器', async () => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2', 'option3'],
|
|
disabled: true
|
|
}
|
|
})
|
|
|
|
// 所有选项都应该被禁用
|
|
wrapper.findAll('.wd-segmented__item').forEach((item) => {
|
|
expect(item.classes()).toContain('is-disabled')
|
|
})
|
|
|
|
// 点击第二个选项不应该触发事件
|
|
await wrapper.findAll('.wd-segmented__item')[1].trigger('click')
|
|
expect(wrapper.emitted('update:value')).toBeFalsy()
|
|
expect(wrapper.emitted('change')).toBeFalsy()
|
|
expect(wrapper.emitted('click')).toBeFalsy()
|
|
})
|
|
|
|
// 测试单个选项禁用
|
|
test('禁用单个项目', async () => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: [{ value: 'option1' }, { value: 'option2', disabled: true }, { value: 'option3' }]
|
|
}
|
|
})
|
|
// 只有第二个选项应该被禁用
|
|
const items = wrapper.findAll('.wd-segmented__item')
|
|
expect(items[0].classes()).not.toContain('is-disabled')
|
|
expect(items[1].classes()).toContain('is-disabled')
|
|
expect(items[2].classes()).not.toContain('is-disabled')
|
|
|
|
// 点击第二个选项不应该触发事件
|
|
await items[1].trigger('click')
|
|
expect(wrapper.emitted('update:value')).toBeFalsy()
|
|
|
|
// 点击第三个选项应该触发事件
|
|
await items[2].trigger('click')
|
|
const emitted = wrapper.emitted() as Record<string, any[]>
|
|
expect(emitted['update:value']).toBeTruthy()
|
|
expect(emitted['update:value'][0]).toEqual(['option3'])
|
|
})
|
|
|
|
// 测试不同尺寸
|
|
test('渲染不同尺寸', () => {
|
|
const sizes = ['large', 'middle', 'small'] as const
|
|
|
|
sizes.forEach((size) => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2'],
|
|
size
|
|
}
|
|
})
|
|
|
|
expect(wrapper.find(`.wd-segmented__item.is-${size}`).exists()).toBe(true)
|
|
})
|
|
})
|
|
|
|
// 测试自定义标签插槽
|
|
test('渲染标签插槽', () => {
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2']
|
|
},
|
|
slots: {
|
|
label: `<template #label="{ option }">
|
|
<div class="custom-label">{{ option.value }}</div>
|
|
</template>`
|
|
}
|
|
})
|
|
|
|
expect(wrapper.findAll('.custom-label').length).toBe(2)
|
|
expect(wrapper.findAll('.custom-label')[0].text()).toBe('option1')
|
|
expect(wrapper.findAll('.custom-label')[1].text()).toBe('option2')
|
|
})
|
|
|
|
// 测试振动反馈
|
|
test('启用振动反馈时触发振动', async () => {
|
|
// 确保 uni.vibrateShort 是一个函数
|
|
if (typeof uni.vibrateShort !== 'function') {
|
|
uni.vibrateShort = vi.fn()
|
|
}
|
|
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2'],
|
|
vibrateShort: true
|
|
}
|
|
})
|
|
|
|
// 点击第二个选项
|
|
await wrapper.findAll('.wd-segmented__item')[1].trigger('click')
|
|
|
|
// 更新 value 属性
|
|
await wrapper.setProps({ value: 'option2' })
|
|
|
|
// 验证振动函数被调用
|
|
expect(uni.vibrateShort).toHaveBeenCalled()
|
|
})
|
|
|
|
// 测试自定义类名
|
|
test('应用自定义类名', () => {
|
|
const customClass = 'my-segmented'
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2'],
|
|
customClass
|
|
}
|
|
})
|
|
|
|
expect(wrapper.classes()).toContain(customClass)
|
|
})
|
|
|
|
// 测试自定义样式
|
|
test('应用自定义样式', () => {
|
|
const customStyle = 'background-color: red;'
|
|
const wrapper = mount(WdSegmented, {
|
|
props: {
|
|
value: 'option1',
|
|
options: ['option1', 'option2'],
|
|
customStyle
|
|
}
|
|
})
|
|
|
|
expect(wrapper.attributes('style')).toBe(customStyle)
|
|
})
|
|
})
|