Skip to content

Commit 5c80a9b

Browse files
committed
chore: ts support
1 parent b8b813d commit 5c80a9b

File tree

5 files changed

+152
-26
lines changed

5 files changed

+152
-26
lines changed

src/Cascader.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,15 @@ export type GetOptionType<
152152
Multiple extends boolean | React.ReactNode = false,
153153
> = false extends Multiple ? OptionType[] : OptionType[][];
154154

155-
type SemanticName = 'input' | 'prefix' | 'suffix';
155+
type SemanticName =
156+
| 'input'
157+
| 'prefix'
158+
| 'suffix'
159+
| 'placeholder'
160+
| 'content'
161+
| 'item'
162+
| 'itemContent'
163+
| 'itemRemove';
156164
type PopupSemantic = 'list' | 'listItem';
157165
export interface CascaderProps<
158166
OptionType extends DefaultOptionType = DefaultOptionType,
@@ -455,11 +463,21 @@ const Cascader = React.forwardRef<CascaderRef, InternalCascaderProps>((props, re
455463
prefix: classNames?.prefix,
456464
suffix: classNames?.suffix,
457465
input: classNames?.input,
466+
placeholder: classNames?.placeholder,
467+
content: classNames?.content,
468+
item: classNames?.item,
469+
itemContent: classNames?.itemContent,
470+
itemRemove: classNames?.itemRemove,
458471
}}
459472
styles={{
460473
prefix: styles?.prefix,
461474
suffix: styles?.suffix,
462475
input: styles?.input,
476+
placeholder: styles?.placeholder,
477+
content: styles?.content,
478+
item: styles?.item,
479+
itemContent: styles?.itemContent,
480+
itemRemove: styles?.itemRemove,
463481
}}
464482
popupStyle={{
465483
...popupStyle,

tests/fieldNames.spec.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ describe('Cascader.FieldNames', () => {
3939
);
4040

4141
// Open
42-
wrapper.find('.rc-cascader-selector').simulate('mousedown');
42+
wrapper.find('.rc-cascader').first().simulate('mousedown');
4343
expect(wrapper.isOpen()).toBeTruthy();
4444

4545
// Check values
@@ -76,7 +76,7 @@ describe('Cascader.FieldNames', () => {
7676
/>,
7777
);
7878

79-
expect(wrapper.find('.rc-cascader-selection-item').text()).toEqual('Bamboo / Little / Toy');
79+
expect(wrapper.find('.rc-cascader-content-value').text()).toEqual('Bamboo / Little / Toy');
8080

8181
expect(wrapper.find('.rc-cascader-menu')).toHaveLength(3);
8282
expect(wrapper.find('.rc-cascader-menu-item-active')).toHaveLength(3);
@@ -97,7 +97,7 @@ describe('Cascader.FieldNames', () => {
9797
/>,
9898
);
9999

100-
expect(wrapper.find('.rc-cascader-selection-item').text()).toEqual(
100+
expect(wrapper.find('.rc-cascader-content-value').text()).toEqual(
101101
'Bamboo->Little->Toy & bamboo>>little>>toy',
102102
);
103103
});

tests/search.spec.tsx

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -365,22 +365,26 @@ describe('Cascader.Search', () => {
365365

366366
it('onSearch and searchValue in showSearch', () => {
367367
const onSearch = jest.fn();
368-
const wrapper = mount(<Cascader options={options} open showSearch={{ onSearch }} />);
368+
const { container } = render(<Cascader options={options} open showSearch={{ onSearch }} />);
369369

370370
// Leaf
371-
doSearch(wrapper, 'toy');
372-
let itemList = wrapper.find('div.rc-cascader-menu-item-content');
371+
fireEvent.change(container.querySelector('input') as HTMLElement, {
372+
target: { value: 'toy' },
373+
});
374+
let itemList = container.querySelectorAll('div.rc-cascader-menu-item-content');
373375
expect(itemList).toHaveLength(2);
374-
expect(itemList.at(0).text()).toEqual('Label Bamboo / Label Little / Toy Fish');
375-
expect(itemList.at(1).text()).toEqual('Label Bamboo / Label Little / Toy Cards');
376+
expect(itemList[0].textContent).toEqual('Label Bamboo / Label Little / Toy Fish');
377+
expect(itemList[1].textContent).toEqual('Label Bamboo / Label Little / Toy Cards');
376378
expect(onSearch).toHaveBeenCalledWith('toy');
377379

378380
// Parent
379-
doSearch(wrapper, 'Label Little');
380-
itemList = wrapper.find('div.rc-cascader-menu-item-content');
381+
fireEvent.change(container.querySelector('input') as HTMLElement, {
382+
target: { value: 'Label Little' },
383+
});
384+
itemList = container.querySelectorAll('div.rc-cascader-menu-item-content');
381385
expect(itemList).toHaveLength(2);
382-
expect(itemList.at(0).text()).toEqual('Label Bamboo / Label Little / Toy Fish');
383-
expect(itemList.at(1).text()).toEqual('Label Bamboo / Label Little / Toy Cards');
386+
expect(itemList[0].textContent).toEqual('Label Bamboo / Label Little / Toy Fish');
387+
expect(itemList[1].textContent).toEqual('Label Bamboo / Label Little / Toy Cards');
384388
expect(onSearch).toHaveBeenCalledWith('Label Little');
385389
});
386390

@@ -404,10 +408,9 @@ describe('Cascader.Search', () => {
404408
/>,
405409
);
406410
expect(container.querySelectorAll('.rc-cascader-menu-item')).toHaveLength(1);
407-
expect(
408-
(container.querySelector('.rc-cascader-selection-search-input') as HTMLInputElement)?.value,
409-
).toBe('little');
411+
expect(container.querySelector('input') as HTMLInputElement).toHaveValue('little');
410412
});
413+
411414
it('autoClearSearchValue in showSearch', () => {
412415
const { container } = render(
413416
<Cascader

tests/selector.spec.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { fireEvent, render } from '@testing-library/react';
33
import { mount } from './enzyme';
44
import Cascader from '../src';
55
import { addressOptions } from './demoOptions';
6+
import { expectOpen } from './util';
67

78
// Mock `useActive` hook
89
jest.mock('../src/OptionList/useActive', () => (multiple: boolean, open: boolean) => {
@@ -23,7 +24,7 @@ describe('Cascader.Selector', () => {
2324
<Cascader value={['not', 'exist']} allowClear onChange={onChange} />,
2425
);
2526

26-
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear-icon') as HTMLElement);
27+
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear') as HTMLElement);
2728
expect(onChange).toHaveBeenCalledWith(undefined, undefined);
2829
});
2930

@@ -41,25 +42,25 @@ describe('Cascader.Selector', () => {
4142
);
4243

4344
// Open and select
44-
fireEvent.mouseDown(container.querySelector('.rc-cascader-selector') as HTMLElement);
45-
expect(container.querySelector('.rc-cascader-open')).toBeTruthy();
45+
fireEvent.mouseDown(container.querySelector('.rc-cascader') as HTMLElement);
46+
expectOpen(container);
4647

4748
fireEvent.click(container.querySelector('.rc-cascader-menu-item-content') as HTMLElement);
4849
fireEvent.click(container.querySelectorAll('.rc-cascader-menu-item-content')[1]);
49-
expect(container.querySelector('.rc-cascader-open')).toBeFalsy();
50+
expectOpen(container, false);
5051

5152
// Clear
52-
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear-icon') as HTMLElement);
53+
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear') as HTMLElement);
5354
expect((global as any).activeValueCells).toEqual([]);
5455
});
5556

5657
it('multiple', () => {
5758
const onChange = jest.fn();
58-
const wrapper = mount(
59+
const { container } = render(
5960
<Cascader checkable value={[['not'], ['exist']]} allowClear onChange={onChange} />,
6061
);
6162

62-
wrapper.find('.rc-cascader-clear-icon').simulate('mouseDown');
63+
fireEvent.mouseDown(container.querySelector('.rc-cascader-clear') as HTMLElement);
6364
expect(onChange).toHaveBeenCalledWith([], []);
6465
});
6566
});
@@ -70,7 +71,7 @@ describe('Cascader.Selector', () => {
7071
<Cascader checkable value={[['not'], ['exist']]} allowClear onChange={onChange} />,
7172
);
7273

73-
wrapper.find('.rc-cascader-selection-item-remove-icon').first().simulate('click');
74+
wrapper.find('.rc-cascader-selection-item-remove').first().simulate('click');
7475
expect(onChange).toHaveBeenCalledWith([['exist']], expect.anything());
7576
});
7677

tests/semantic.spec.tsx

Lines changed: 106 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ describe('Cascader.Search', () => {
99
prefix: 'test-prefix',
1010
suffix: 'test-suffix',
1111
input: 'test-input',
12+
placeholder: 'test-placeholder',
13+
content: 'test-content',
1214
popup: {
1315
list: 'test-popup-list',
1416
listItem: 'test-popup-list-item',
@@ -18,6 +20,8 @@ describe('Cascader.Search', () => {
1820
prefix: { color: 'green' },
1921
suffix: { color: 'blue' },
2022
input: { color: 'purple' },
23+
placeholder: { fontSize: '12px' },
24+
content: { backgroundColor: 'lightgray' },
2125
popup: {
2226
list: { background: 'red' },
2327
listItem: { color: 'yellow' },
@@ -34,20 +38,120 @@ describe('Cascader.Search', () => {
3438
optionRender={option => `${option.label} - test`}
3539
/>,
3640
);
37-
const input = container.querySelector('.rc-cascader-selection-search-input');
41+
42+
const input = container.querySelector('.rc-cascader-input');
3843
const prefix = container.querySelector('.rc-cascader-prefix');
39-
const suffix = container.querySelector('.rc-cascader-arrow');
44+
const suffix = container.querySelector('.rc-cascader-suffix');
45+
const placeholder = container.querySelector('.rc-cascader-placeholder');
46+
const content = container.querySelector('.rc-cascader-content');
4047
const list = container.querySelector('.rc-cascader-menu');
4148
const listItem = container.querySelector('.rc-cascader-menu-item');
49+
50+
// Test styles for supported semantic elements
4251
expect(input).toHaveStyle(testStyles.input);
4352
expect(prefix).toHaveStyle(testStyles.prefix);
4453
expect(suffix).toHaveStyle(testStyles.suffix);
54+
if (placeholder) {
55+
expect(placeholder).toHaveStyle(testStyles.placeholder);
56+
}
57+
expect(content).toHaveStyle(testStyles.content);
4558
expect(list).toHaveStyle(testStyles.popup.list);
4659
expect(listItem).toHaveStyle(testStyles.popup.listItem);
60+
61+
// Test class names for supported semantic elements
62+
expect(input?.className).toContain(testClassNames.input);
63+
expect(prefix?.className).toContain(testClassNames.prefix);
64+
expect(suffix?.className).toContain(testClassNames.suffix);
65+
if (placeholder) {
66+
expect(placeholder?.className).toContain(testClassNames.placeholder);
67+
}
68+
expect(content?.className).toContain(testClassNames.content);
69+
expect(list?.className).toContain(testClassNames.popup.list);
70+
expect(listItem?.className).toContain(testClassNames.popup.listItem);
71+
});
72+
73+
it('Should support semantic for multiple mode', () => {
74+
const testClassNames = {
75+
prefix: 'test-prefix',
76+
suffix: 'test-suffix',
77+
input: 'test-input',
78+
placeholder: 'test-placeholder',
79+
content: 'test-content',
80+
item: 'test-item',
81+
itemContent: 'test-item-content',
82+
itemRemove: 'test-item-remove',
83+
popup: {
84+
list: 'test-popup-list',
85+
listItem: 'test-popup-list-item',
86+
},
87+
};
88+
const testStyles = {
89+
prefix: { color: 'green' },
90+
suffix: { color: 'blue' },
91+
input: { color: 'purple' },
92+
placeholder: { fontSize: '12px' },
93+
content: { backgroundColor: 'lightgray' },
94+
item: { border: '1px solid red' },
95+
itemContent: { fontWeight: 'bold' },
96+
itemRemove: { color: 'red' },
97+
popup: {
98+
list: { background: 'red' },
99+
listItem: { color: 'yellow' },
100+
},
101+
};
102+
const { container } = render(
103+
<Cascader
104+
classNames={testClassNames}
105+
styles={testStyles}
106+
prefix="prefix"
107+
suffixIcon={() => 'icon'}
108+
open
109+
checkable
110+
value={[['bamboo']]}
111+
options={[
112+
{ label: 'bamboo', value: 'bamboo', children: [{ label: 'leaf', value: 'leaf' }] },
113+
]}
114+
optionRender={option => `${option.label} - test`}
115+
/>,
116+
);
117+
118+
const input = container.querySelector('.rc-cascader-input');
119+
const prefix = container.querySelector('.rc-cascader-prefix');
120+
const suffix = container.querySelector('.rc-cascader-suffix');
121+
const placeholder = container.querySelector('.rc-cascader-placeholder');
122+
const content = container.querySelector('.rc-cascader-content');
123+
const list = container.querySelector('.rc-cascader-menu');
124+
const listItem = container.querySelector('.rc-cascader-menu-item');
125+
const item = container.querySelector('.rc-cascader-selection-item');
126+
const itemContent = container.querySelector('.rc-cascader-selection-item-content');
127+
const itemRemove = container.querySelector('.rc-cascader-selection-item-remove');
128+
129+
// Test styles for supported semantic elements
130+
expect(input).toHaveStyle(testStyles.input);
131+
expect(prefix).toHaveStyle(testStyles.prefix);
132+
expect(suffix).toHaveStyle(testStyles.suffix);
133+
if (placeholder) {
134+
expect(placeholder).toHaveStyle(testStyles.placeholder);
135+
}
136+
expect(content).toHaveStyle(testStyles.content);
137+
expect(list).toHaveStyle(testStyles.popup.list);
138+
expect(listItem).toHaveStyle(testStyles.popup.listItem);
139+
expect(item).toHaveStyle(testStyles.item);
140+
expect(itemContent).toHaveStyle(testStyles.itemContent);
141+
expect(itemRemove).toHaveStyle(testStyles.itemRemove);
142+
143+
// Test class names for supported semantic elements
47144
expect(input?.className).toContain(testClassNames.input);
48145
expect(prefix?.className).toContain(testClassNames.prefix);
49146
expect(suffix?.className).toContain(testClassNames.suffix);
147+
if (placeholder) {
148+
expect(placeholder?.className).toContain(testClassNames.placeholder);
149+
}
150+
expect(content?.className).toContain(testClassNames.content);
50151
expect(list?.className).toContain(testClassNames.popup.list);
51152
expect(listItem?.className).toContain(testClassNames.popup.listItem);
153+
expect(item?.className).toContain(testClassNames.item);
154+
expect(itemContent?.className).toContain(testClassNames.itemContent);
155+
expect(itemRemove?.className).toContain(testClassNames.itemRemove);
52156
});
53157
});

0 commit comments

Comments
 (0)