Files
jh-military-admin/tests/device-group-tree.test.ts
T
dzc 3554d0cc80
build / task (16.x, npm, macOS-latest) (push) Canceled after 0s
build / task (16.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, npm, windows-latest) (push) Canceled after 0s
build / task (16.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (16.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (16.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (16.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (16.x, yarn, windows-latest) (push) Canceled after 0s
build / task (18.x, npm, macOS-latest) (push) Canceled after 0s
build / task (18.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, npm, windows-latest) (push) Canceled after 0s
build / task (18.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (18.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (18.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (18.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (18.x, yarn, windows-latest) (push) Canceled after 0s
build / task (20.x, npm, macOS-latest) (push) Canceled after 0s
build / task (20.x, npm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, npm, windows-latest) (push) Canceled after 0s
build / task (20.x, pnpm, macOS-latest) (push) Canceled after 0s
build / task (20.x, pnpm, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, pnpm, windows-latest) (push) Canceled after 0s
build / task (20.x, yarn, macOS-latest) (push) Canceled after 0s
build / task (20.x, yarn, ubuntu-latest) (push) Canceled after 0s
build / task (20.x, yarn, windows-latest) (push) Canceled after 0s
11
2026-10-27 16:38:51 +08:00

77 lines
4.0 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { flushPromises, mount, type VueWrapper } from '@vue/test-utils';
import { defineComponent, h } from 'vue';
import { ElTree, ElInput, ElButton, ElIcon } from 'element-plus';
import * as icons from '@element-plus/icons-vue';
import GroupTree from '../src/components/DraggableDeviceGroupDraggable/index.vue';
const api = vi.hoisted(() => ({ query: vi.fn(), editGroupSort: vi.fn(), error: vi.fn() }));
vi.mock('../src/api/device/deviceGroup', () => ({ getDeviceGroupTree: api.query, editGroupSort: api.editGroupSort }));
vi.mock('../src/hooks/message', () => ({ useMessage: () => ({ error: api.error }) }));
const Slot = defineComponent({ setup(_, { slots }) { return () => h('div', slots.default?.()); } });
const groupData = () => [
{ id: 'group-a', name: '值班员视图', deep: 1, visible: true, children: [
{ id: 'a', parentId: 'group-a', name: '南门球机', code: 'channel-a', deep: 2, visible: true },
{ id: 'b', parentId: 'group-a', name: '西围墙', code: 'channel-b', deep: 2, visible: true },
] },
{ id: 'group-b', name: '兵器场', deep: 1, visible: true, children: [
{ id: 'c', parentId: 'group-b', name: '额外通道', code: 'channel-c', deep: 2, visible: true },
] },
];
let wrapper: VueWrapper;
const checkedCodes = () => (wrapper.emitted('getSelectNode')!.at(-1)![1] as any[]).filter(item => item.deep === 2).map(item => item.code);
beforeEach(() => {
api.query.mockReset().mockResolvedValue({ code: 0, data: groupData() });
wrapper = mount(GroupTree, { global: {
components: { ElTree, ElInput, ElButton, ElIcon, ...icons }, stubs: { Splitpanes: Slot, Pane: Slot, 'el-switch': true },
directives: { loading: () => undefined },
} });
});
afterEach(() => wrapper.unmount());
describe('分组树的真实勾选与筛选', () => {
it('默认勾选第一个分组,按树顺序提交可播放通道', async () => {
await flushPromises();
expect(checkedCodes()).toEqual(['channel-a', 'channel-b']);
expect(wrapper.find('.selection-count').text()).toBe('已选 2');
});
it('搜索只过滤展示,保留当前勾选且不重新请求或触发播放', async () => {
await flushPromises();
const count = wrapper.emitted('getSelectNode')!.length;
await wrapper.find('.sidebar-search input').setValue('额外');
await flushPromises();
expect(api.query).toHaveBeenCalledTimes(1);
expect(wrapper.emitted('getSelectNode')).toHaveLength(count);
expect(wrapper.findComponent(ElTree).vm.getCheckedNodes(true).map((item: any) => item.code)).toEqual(['channel-a', 'channel-b']);
const row = wrapper.findAll('.el-tree-node__content').find(item => item.text().includes('额外通道'))!;
expect(row.isVisible()).toBe(true);
await row.find('input[type="checkbox"]').setValue(true);
await flushPromises();
expect(checkedCodes()).toEqual(['channel-a', 'channel-b', 'channel-c']);
expect(wrapper.find('.selection-count').text()).toBe('已选 3');
});
it('清空选择会同步树和父页面,半选分组不会算成视频通道', async () => {
await flushPromises();
const row = wrapper.findAll('.el-tree-node__content').find(item => item.text().includes('南门球机'))!;
await row.find('input[type="checkbox"]').setValue(false);
await flushPromises();
expect(checkedCodes()).toEqual(['channel-b']);
expect(wrapper.find('.selection-count').text()).toBe('已选 1');
await wrapper.findAll('button').find(item => item.text() === '清空选择')!.trigger('click');
await flushPromises();
expect(checkedCodes()).toEqual([]);
expect(wrapper.findComponent(ElTree).vm.getCheckedNodes()).toHaveLength(0);
expect(wrapper.find('.selection-count').text()).toBe('已选 0');
});
it('空分组响应仍正常显示空树', async () => {
api.query.mockResolvedValueOnce({ code: 0, data: null });
await flushPromises();
await wrapper.vm.getTreeData();
await flushPromises();
expect(wrapper.text()).toContain('暂无匹配的分组或通道');
});
});