Skip to content

Commit 41372bf

Browse files
committed
test: add tests for select + multiselect renderOption
1 parent ab08df5 commit 41372bf

File tree

2 files changed

+285
-0
lines changed

2 files changed

+285
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import * as React from 'react';
4+
import { render } from '@testing-library/react';
5+
6+
import { KeyCode } from '@cloudscape-design/test-utils-core/utils';
7+
8+
import Multiselect, { MultiselectProps } from '../../../lib/components/multiselect';
9+
import createWrapper from '../../../lib/components/test-utils/dom';
10+
import { optionsWithGroups } from './common';
11+
12+
describe('Multiselect renderOption', () => {
13+
function renderMultiselect(props?: Partial<MultiselectProps>) {
14+
const { container } = render(
15+
<Multiselect selectedOptions={[]} onChange={() => {}} options={props?.options ?? []} {...props} />
16+
);
17+
return createWrapper(container).findMultiselect()!;
18+
}
19+
20+
test('renders custom option content', () => {
21+
const renderOption = jest.fn(item => <div data-testid="custom">{item.option.label}</div>);
22+
const wrapper = renderMultiselect({ options: optionsWithGroups, renderOption });
23+
wrapper.openDropdown();
24+
expect(renderOption).toHaveBeenCalled();
25+
expect(wrapper.findDropdown().getElement().querySelector('[data-testid="custom"]')).toBeTruthy();
26+
});
27+
28+
test('receives correct item properties for child option', () => {
29+
const renderOption = jest.fn(() => <div>Custom</div>);
30+
const childOption = { label: 'Test', value: '1' };
31+
const wrapper = renderMultiselect({
32+
options: [childOption],
33+
renderOption,
34+
});
35+
wrapper.openDropdown();
36+
expect(renderOption).toHaveBeenCalledWith(
37+
expect.objectContaining({
38+
option: expect.objectContaining(childOption),
39+
selected: false,
40+
highlighted: false,
41+
disabled: false,
42+
type: 'child',
43+
})
44+
);
45+
});
46+
47+
test('receives correct item properties for parent option', () => {
48+
const renderOption = jest.fn(() => <div>Custom</div>);
49+
const groupOption = { label: 'Group', value: 'g1', options: [{ label: 'Child', value: 'c1' }] };
50+
const wrapper = renderMultiselect({
51+
options: [groupOption],
52+
renderOption,
53+
});
54+
wrapper.openDropdown();
55+
expect(renderOption).toHaveBeenCalledWith(
56+
expect.objectContaining({
57+
option: expect.objectContaining(groupOption),
58+
selected: false,
59+
highlighted: false,
60+
disabled: false,
61+
type: 'parent',
62+
})
63+
);
64+
});
65+
66+
test('receives correct item properties for select-all option', () => {
67+
const renderOption = jest.fn(() => <div>Custom</div>);
68+
const wrapper = renderMultiselect({
69+
options: [{ label: 'Test', value: '1' }],
70+
renderOption,
71+
enableSelectAll: true,
72+
});
73+
wrapper.openDropdown();
74+
expect(renderOption).toHaveBeenCalledWith(
75+
expect.objectContaining({
76+
type: 'select-all',
77+
})
78+
);
79+
});
80+
81+
test('reflects highlighted state', () => {
82+
const renderOption = jest.fn(item => <div>{item.highlighted ? 'highlighted' : 'normal'}</div>);
83+
const wrapper = renderMultiselect({ options: [{ label: 'First', value: '1' }], renderOption });
84+
wrapper.openDropdown();
85+
wrapper.findDropdown().findOptionsContainer()!.keydown(KeyCode.down);
86+
expect(wrapper.findDropdown().getElement().textContent).toContain('highlighted');
87+
});
88+
89+
test('reflects disabled state', () => {
90+
const renderOption = jest.fn(item => <div>{item.disabled ? 'disabled' : 'enabled'}</div>);
91+
const wrapper = renderMultiselect({
92+
options: [{ label: 'Test', value: '1', disabled: true }],
93+
renderOption,
94+
});
95+
wrapper.openDropdown();
96+
expect(renderOption).toHaveBeenCalledWith(expect.objectContaining({ disabled: true }));
97+
});
98+
99+
test('reflects selected state', () => {
100+
const renderOption = jest.fn(item => <div>{item.selected ? 'selected' : 'unselected'}</div>);
101+
const option = { label: 'Test', value: '1' };
102+
const wrapper = renderMultiselect({
103+
options: [option],
104+
selectedOptions: [option],
105+
renderOption,
106+
});
107+
wrapper.openDropdown();
108+
expect(renderOption).toHaveBeenCalledWith(expect.objectContaining({ selected: true }));
109+
});
110+
111+
test('reflects partial selection state for parent option', () => {
112+
const renderOption = jest.fn(() => <div>Custom</div>);
113+
const groupOption = {
114+
label: 'Group',
115+
value: 'g1',
116+
options: [
117+
{ label: 'Child1', value: 'c1' },
118+
{ label: 'Child2', value: 'c2' },
119+
],
120+
};
121+
const wrapper = renderMultiselect({
122+
options: [groupOption],
123+
selectedOptions: [{ label: 'Child1', value: 'c1' }],
124+
renderOption,
125+
});
126+
wrapper.openDropdown();
127+
expect(renderOption).toHaveBeenCalledWith(
128+
expect.objectContaining({
129+
type: 'parent',
130+
selected: false,
131+
})
132+
);
133+
expect(renderOption).toHaveBeenCalledWith(
134+
expect.objectContaining({
135+
type: 'child',
136+
selected: true,
137+
})
138+
);
139+
});
140+
141+
test('allows selection with custom rendered options', () => {
142+
const onChange = jest.fn();
143+
const renderOption = jest.fn(item => <div>{item.option.value}</div>);
144+
const wrapper = renderMultiselect({
145+
options: [
146+
{ label: 'Test', value: '1' },
147+
{ label: 'Test 2', value: '2' },
148+
],
149+
renderOption,
150+
onChange,
151+
});
152+
wrapper.openDropdown();
153+
wrapper.selectOptionByValue('2');
154+
expect(onChange).toHaveBeenCalledWith(
155+
expect.objectContaining({ detail: { selectedOptions: [expect.objectContaining({ value: '2' })] } })
156+
);
157+
});
158+
});
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import * as React from 'react';
4+
import { render } from '@testing-library/react';
5+
6+
import { KeyCode } from '@cloudscape-design/test-utils-core/utils';
7+
8+
import Select, { SelectProps } from '../../../lib/components/select';
9+
import createWrapper from '../../../lib/components/test-utils/dom';
10+
import { defaultOptions } from './common';
11+
12+
describe('Select renderOption', () => {
13+
function renderSelect(props?: Partial<SelectProps>) {
14+
const { container } = render(
15+
<Select selectedOption={null} onChange={() => {}} options={props?.options ?? []} {...props} />
16+
);
17+
return createWrapper(container).findSelect()!;
18+
}
19+
20+
test('renders custom option content', () => {
21+
const renderOption = jest.fn(item => <div data-testid="custom">{item.option.label}</div>);
22+
const wrapper = renderSelect({ options: defaultOptions, renderOption });
23+
wrapper.openDropdown();
24+
expect(renderOption).toHaveBeenCalled();
25+
expect(wrapper.findDropdown().getElement().querySelector('[data-testid="custom"]')).toBeTruthy();
26+
});
27+
28+
test('receives correct item properties for child option', () => {
29+
const renderOption = jest.fn(() => <div>Custom</div>);
30+
const childOption = { label: 'Test', value: '1' };
31+
const wrapper = renderSelect({
32+
options: [childOption],
33+
renderOption,
34+
});
35+
wrapper.openDropdown();
36+
expect(renderOption).toHaveBeenCalledWith(
37+
expect.objectContaining({
38+
option: expect.objectContaining(childOption),
39+
selected: false,
40+
highlighted: false,
41+
disabled: false,
42+
type: 'child',
43+
})
44+
);
45+
});
46+
47+
test('receives correct item properties for parent option', () => {
48+
const renderOption = jest.fn(() => <div>Custom</div>);
49+
const groupOption = { label: 'Group', value: 'g1', options: [{ label: 'Child', value: 'c1' }] };
50+
const wrapper = renderSelect({
51+
options: [groupOption],
52+
renderOption,
53+
});
54+
wrapper.openDropdown();
55+
expect(renderOption).toHaveBeenCalledWith(
56+
expect.objectContaining({
57+
option: expect.objectContaining(groupOption),
58+
selected: false,
59+
highlighted: false,
60+
disabled: false,
61+
type: 'parent',
62+
})
63+
);
64+
});
65+
66+
test('reflects highlighted state', () => {
67+
const renderOption = jest.fn(item => <div>{item.highlighted ? 'highlighted' : 'normal'}</div>);
68+
const wrapper = renderSelect({ options: [{ label: 'First', value: '1' }], renderOption });
69+
wrapper.openDropdown();
70+
wrapper.findDropdown().findOptionsContainer()!.keydown(KeyCode.down);
71+
expect(wrapper.findDropdown().getElement().textContent).toContain('highlighted');
72+
});
73+
test('reflects selected state', () => {
74+
const renderOption = jest.fn(item => <div>{item.selected ? 'selected' : 'not-selected'}</div>);
75+
const option = { label: 'Test', value: '1' };
76+
const wrapper = renderSelect({
77+
options: [option],
78+
selectedOption: option,
79+
renderOption,
80+
});
81+
wrapper.openDropdown();
82+
expect(renderOption).toHaveBeenCalledWith(expect.objectContaining({ selected: true }));
83+
});
84+
85+
test('renders children within groups correctly', () => {
86+
const renderOption = jest.fn(item => (
87+
<div>
88+
{item.type}-{item.option.label}
89+
</div>
90+
));
91+
const wrapper = renderSelect({
92+
options: [{ label: 'Group', options: [{ label: 'Child', value: 'c1' }] }],
93+
renderOption,
94+
});
95+
wrapper.openDropdown();
96+
expect(renderOption).toHaveBeenCalledWith(expect.objectContaining({ type: 'child' }));
97+
});
98+
99+
test('reflects disabled state', () => {
100+
const renderOption = jest.fn(item => <div>{item.disabled ? 'disabled' : 'enabled'}</div>);
101+
const wrapper = renderSelect({
102+
options: [{ label: 'Test', value: '1', disabled: true }],
103+
renderOption,
104+
});
105+
wrapper.openDropdown();
106+
107+
expect(renderOption).toHaveBeenCalledWith(expect.objectContaining({ disabled: true }));
108+
});
109+
110+
test('allows selection with custom rendered options', () => {
111+
const onChange = jest.fn();
112+
const renderOption = jest.fn(item => <div>{item.option.value}</div>);
113+
const wrapper = renderSelect({
114+
options: [
115+
{ label: 'Test', value: '1' },
116+
{ label: 'Test 2', value: '2' },
117+
],
118+
renderOption,
119+
onChange,
120+
});
121+
wrapper.openDropdown();
122+
wrapper.selectOptionByValue('2');
123+
expect(onChange).toHaveBeenCalledWith(
124+
expect.objectContaining({ detail: { selectedOption: expect.objectContaining({ value: '2' }) } })
125+
);
126+
});
127+
});

0 commit comments

Comments
 (0)