UserFilterBar.test.tsx
5.05 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// REQ-USR-003: UserFilterBar 筛选栏单测(BR2/BR3/BR4/BR7/BR10/D2/D3)
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { screen, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { renderShell } from './renderShell';
import UserFilterBar from '../../src/pages/usr/UserList/UserFilterBar';
import { DEFAULT_QUERY } from '../../src/pages/usr/UserList/constants';
import type { UserListQuery } from '../../src/api/types';
function setup(overrides?: Partial<UserListQuery>) {
const onChangeQueryField = vi.fn();
const onChangeMatchType = vi.fn();
const onChangeQueryValue = vi.fn();
const onSearch = vi.fn();
const onClear = vi.fn();
const query: UserListQuery = { ...DEFAULT_QUERY, ...overrides };
renderShell(
<UserFilterBar
query={query}
onChangeQueryField={onChangeQueryField}
onChangeMatchType={onChangeMatchType}
onChangeQueryValue={onChangeQueryValue}
onSearch={onSearch}
onClear={onClear}
/>,
{ preloadedAuth: { token: 't', user: { id: 1, sUserName: 'a', sUserType: 'x', sLanguage: '中文' } } },
);
return { onChangeQueryField, onChangeMatchType, onChangeQueryValue, onSearch, onClear };
}
describe('UserFilterBar', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('renders defaults 用户名 / 包含 and empty value', () => {
setup();
const fieldSel = within(screen.getByTestId('filter-query-field'));
expect(fieldSel.getByText('用户名')).toBeInTheDocument();
const matchSel = within(screen.getByTestId('filter-match-type'));
expect(matchSel.getByText('包含')).toBeInTheDocument();
const input = screen.getByTestId('filter-query-value').querySelector('input')!;
expect(input.value).toBe('');
});
it('query field options match enum (BR4)', async () => {
const user = userEvent.setup();
setup();
// 展开查询字段下拉
const combobox = within(screen.getByTestId('filter-query-field')).getByRole('combobox');
await user.click(combobox);
// AntD options 渲染为 role=option(在 document.body 的下拉层)
const options = await screen.findAllByRole('option');
const labels = options.map((o) => o.textContent);
for (const label of ['用户名', '员工名', '用户号', '部门', '用户类型', '作废', '登录日期', '制单人']) {
expect(labels).toContain(label);
}
expect(options).toHaveLength(8);
});
it('match type options are 包含/不包含/等于 (BR4)', async () => {
const user = userEvent.setup();
setup();
const combobox = within(screen.getByTestId('filter-match-type')).getByRole('combobox');
await user.click(combobox);
const options = await screen.findAllByRole('option');
const labels = options.map((o) => o.textContent);
expect(labels).toEqual(['包含', '不包含', '等于']);
});
it('scope select shows 全部用户 only (D2)', () => {
setup();
const scope = within(screen.getByTestId('filter-scope'));
expect(scope.getByText('全部用户')).toBeInTheDocument();
});
it('Enter in value triggers onSearch (BR7)', async () => {
const user = userEvent.setup();
const { onSearch } = setup();
const input = screen.getByTestId('filter-query-value').querySelector('input')!;
input.focus();
await user.keyboard('{Enter}');
expect(onSearch).toHaveBeenCalledTimes(1);
});
it('click 搜索 calls onSearch / click 清空 calls onClear (BR7/BR10)', async () => {
const user = userEvent.setup();
const { onSearch, onClear } = setup();
await user.click(screen.getByTestId('btn-search'));
expect(onSearch).toHaveBeenCalledTimes(1);
await user.click(screen.getByTestId('btn-clear'));
expect(onClear).toHaveBeenCalledTimes(1);
});
it('typing value calls onChangeQueryValue', async () => {
const user = userEvent.setup();
const { onChangeQueryValue } = setup();
const input = screen.getByTestId('filter-query-value').querySelector('input')!;
await user.type(input, 'x');
expect(onChangeQueryValue).toHaveBeenCalled();
expect(onChangeQueryValue).toHaveBeenLastCalledWith('x');
});
it('changing query field select calls onChangeQueryField', async () => {
const user = userEvent.setup();
const { onChangeQueryField } = setup();
const combobox = within(screen.getByTestId('filter-query-field')).getByRole('combobox');
await user.click(combobox);
const options = await screen.findAllByRole('option');
const target = options.find((o) => o.textContent === '员工名')!;
await user.click(target);
// AntD Select.onChange 透传 (value, option),回调首参即选中值
expect(onChangeQueryField).toHaveBeenCalled();
expect(onChangeQueryField.mock.calls[0][0]).toBe('员工名');
});
it('more toggle ▾ is placeholder (no extra callback) (D3)', async () => {
const user = userEvent.setup();
const { onSearch, onChangeQueryField } = setup();
await user.click(screen.getByTestId('filter-more'));
expect(onSearch).not.toHaveBeenCalled();
expect(onChangeQueryField).not.toHaveBeenCalled();
});
});