PermissionGroupList.test.tsx
3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// REQ-USR-001 / REQ-USR-002: PermissionGroupList 权限分类勾选列表单测(渲染/勾选集合/全选 indeterminate/回勾,BR10/BR11/D3)
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderShell } from './renderShell';
import PermissionGroupList from '../../src/pages/usr/UserDetail/PermissionGroupList';
import type { PermissionItem } from '../../src/api/types';
const PERMS: PermissionItem[] = [
{ id: 1, name: '默认显示', category: '基础' },
{ id: 2, name: '高级查看', category: '基础' },
{ id: 3, name: '导出', category: '报表' },
];
function setup(over: {
permissions?: PermissionItem[];
checkedIds?: number[];
} = {}) {
const onToggle = vi.fn();
const onToggleAll = vi.fn();
renderShell(
<PermissionGroupList
permissions={over.permissions ?? PERMS}
checkedIds={over.checkedIds ?? []}
onToggle={onToggle}
onToggleAll={onToggleAll}
/>,
{ preloadedAuth: { token: 't', user: { id: 1, sUserName: 'a', sUserType: 'x', sLanguage: '中文' } } },
);
return { onToggle, onToggleAll };
}
function rowCheckbox(id: number): HTMLInputElement {
return screen.getByTestId('perm-check-' + id) as HTMLInputElement;
}
function allCheckbox(): HTMLInputElement {
return screen.getByTestId('perm-check-all') as HTMLInputElement;
}
describe('PermissionGroupList', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('renders header 权限分类 and one row per permission', () => {
setup();
expect(screen.getByText('权限分类')).toBeInTheDocument();
expect(screen.getByText('默认显示')).toBeInTheDocument();
expect(screen.getByText('高级查看')).toBeInTheDocument();
expect(screen.getByText('导出')).toBeInTheDocument();
});
it('checked rows reflect checkedIds', () => {
setup({ checkedIds: [1] });
expect(rowCheckbox(1).checked).toBe(true);
expect(rowCheckbox(2).checked).toBe(false);
expect(rowCheckbox(3).checked).toBe(false);
});
it('toggling a row calls onToggle(id, checked)', async () => {
const user = userEvent.setup();
const { onToggle } = setup({ checkedIds: [1] });
await user.click(rowCheckbox(2));
expect(onToggle).toHaveBeenCalledWith(2, true);
await user.click(rowCheckbox(1));
expect(onToggle).toHaveBeenCalledWith(1, false);
});
it('header select-all checked when all selected; indeterminate when partial', () => {
const { } = setup({ checkedIds: [1, 2, 3] });
expect(allCheckbox().checked).toBe(true);
});
it('header indeterminate when partial; unchecked when none', () => {
setup({ checkedIds: [1] });
const all = allCheckbox();
expect(all.checked).toBe(false);
// AntD 半选用 aria-checked='mixed' 表达于 wrapper;input 仍未 checked
const wrapper = all.closest('.ant-checkbox');
expect(wrapper?.classList.contains('ant-checkbox-indeterminate')).toBe(true);
});
it('header toggle calls onToggleAll', async () => {
const user = userEvent.setup();
const { onToggleAll } = setup({ checkedIds: [] });
await user.click(allCheckbox());
expect(onToggleAll).toHaveBeenCalledWith(true);
});
it('header toggle off when all selected', async () => {
const user = userEvent.setup();
const { onToggleAll } = setup({ checkedIds: [1, 2, 3] });
await user.click(allCheckbox());
expect(onToggleAll).toHaveBeenCalledWith(false);
});
it('empty permissions renders empty list (no rows)', () => {
setup({ permissions: [] });
expect(screen.queryByTestId('perm-check-1')).toBeNull();
});
});