Skip to content

Commit 6e65645

Browse files
feat(BulkSelect): extend onSelect with second parameter source (#913)
* feat(BulkSelect): extend onSelect API with source param * test(BulkSelect): add unit tests for source Assisted-by: Cursor * refactor: define BulkSelectSource as a value Co-authored-by: Karel Hala <ch4rlien@gmail.com> * refactor: use BulkSelectSource.dropdown instead of literal Co-authored-by: Karel Hala <ch4rlien@gmail.com> * refactor: use BulkSelectSource.checkbox instead of literal Co-authored-by: Karel Hala <ch4rlien@gmail.com> * refactor: add BulkSelectSource type * test: update BulkSelect unit tests --------- Co-authored-by: Karel Hala <ch4rlien@gmail.com>
1 parent 0da4098 commit 6e65645

2 files changed

Lines changed: 82 additions & 17 deletions

File tree

packages/module/src/BulkSelect/BulkSelect.test.tsx

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,22 @@
11
import { render, screen } from '@testing-library/react';
22
import userEvent from '@testing-library/user-event';
3-
import BulkSelect from './BulkSelect';
3+
import BulkSelect, { BulkSelectSource, BulkSelectValue } from './BulkSelect';
44

55
describe('BulkSelect component', () => {
66
test('should render', () => {
7-
expect(render(
8-
<BulkSelect
9-
canSelectAll
10-
pageCount={5}
11-
totalCount={10}
12-
selectedCount={2}
13-
pageSelected={false}
14-
pagePartiallySelected={true}
15-
onSelect={() => null}
16-
/>)).toMatchSnapshot();
7+
expect(
8+
render(
9+
<BulkSelect
10+
canSelectAll
11+
pageCount={5}
12+
totalCount={10}
13+
selectedCount={2}
14+
pageSelected={false}
15+
pagePartiallySelected={true}
16+
onSelect={() => null}
17+
/>
18+
)
19+
).toMatchSnapshot();
1720
});
1821

1922
test('should render with dropdownListProps', async () => {
@@ -121,6 +124,7 @@ describe('BulkSelect component', () => {
121124

122125
test('should enable Select none when at least one row is selected', async () => {
123126
const user = userEvent.setup();
127+
124128
render(
125129
<BulkSelect
126130
canSelectAll
@@ -136,4 +140,58 @@ describe('BulkSelect component', () => {
136140
await user.click(screen.getByLabelText('Bulk select toggle'));
137141
expect(screen.getByRole('menuitem', { name: 'Select none (0)' })).not.toBeDisabled();
138142
});
139-
});
143+
144+
test(`should call onSelect with source ${BulkSelectSource.dropdown} when choosing menu items`, async () => {
145+
const user = userEvent.setup();
146+
const onSelect = jest.fn();
147+
148+
render(
149+
<BulkSelect
150+
canSelectAll
151+
pageCount={5}
152+
totalCount={10}
153+
selectedCount={1}
154+
pageSelected={false}
155+
pagePartiallySelected={true}
156+
onSelect={onSelect}
157+
/>
158+
);
159+
160+
const openMenu = async () => {
161+
await user.click(screen.getByLabelText('Bulk select toggle'));
162+
};
163+
164+
await openMenu();
165+
await user.click(screen.getByRole('menuitem', { name: 'Select none (0)' }));
166+
expect(onSelect).toHaveBeenLastCalledWith(BulkSelectValue.none, BulkSelectSource.dropdown);
167+
168+
onSelect.mockClear();
169+
await openMenu();
170+
await user.click(screen.getByRole('menuitem', { name: 'Select page (5)' }));
171+
expect(onSelect).toHaveBeenLastCalledWith(BulkSelectValue.page, BulkSelectSource.dropdown);
172+
173+
onSelect.mockClear();
174+
await openMenu();
175+
await user.click(screen.getByRole('menuitem', { name: 'Select all (10)' }));
176+
expect(onSelect).toHaveBeenLastCalledWith(BulkSelectValue.all, BulkSelectSource.dropdown);
177+
});
178+
179+
test(`should call onSelect with source ${BulkSelectSource.checkbox} when using split checkbox`, async () => {
180+
const user = userEvent.setup();
181+
const onSelect = jest.fn();
182+
render(
183+
<BulkSelect
184+
canSelectAll
185+
pageCount={5}
186+
totalCount={10}
187+
selectedCount={0}
188+
pageSelected={false}
189+
pagePartiallySelected={false}
190+
onSelect={onSelect}
191+
/>
192+
);
193+
194+
await user.click(screen.getByRole('checkbox', { name: 'Select page' }));
195+
expect(onSelect).toHaveBeenCalledWith(BulkSelectValue.page, BulkSelectSource.checkbox);
196+
});
197+
});

packages/module/src/BulkSelect/BulkSelect.tsx

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ export const BulkSelectValue = {
2222

2323
export type BulkSelectValue = (typeof BulkSelectValue)[keyof typeof BulkSelectValue];
2424

25+
export const BulkSelectSource = {
26+
dropdown: 'dropdown',
27+
checkbox: 'checkbox'
28+
} as const;
29+
30+
export type BulkSelectSource = (typeof BulkSelectSource)[keyof typeof BulkSelectSource];
31+
2532
const defaultSelectPageLabel = (pageCount?: number) => `Select page${pageCount ? ` (${pageCount})` : ''}`;
2633
const defaultSelectAllLabel = (totalCount?: number) => `Select all${totalCount ? ` (${totalCount})` : ''}`;
2734
const defaultSelectedLabel = (selectedCount: number) => `${selectedCount} selected`;
@@ -45,7 +52,7 @@ export interface BulkSelectProps extends Omit<DropdownProps, 'toggle' | 'onSelec
4552
/** Indicates if ONLY some current page items are selected */
4653
pagePartiallySelected?: boolean;
4754
/** Callback called on item select */
48-
onSelect: (value: BulkSelectValue) => void;
55+
onSelect: (value: BulkSelectValue, source?: BulkSelectSource) => void;
4956
/** Custom OUIA ID */
5057
ouiaId?: string;
5158
/** Additional props for MenuToggleCheckbox */
@@ -119,12 +126,12 @@ export const BulkSelect: FC<BulkSelectProps> = ({
119126
const onToggleClick = () => setOpen(!isOpen);
120127

121128
return (
122-
(<Dropdown
129+
<Dropdown
123130
shouldFocusToggleOnSelect
124131
ouiaId={`${ouiaId}-dropdown`}
125132
onSelect={(_e, value) => {
126133
setOpen(!isOpen);
127-
onSelect?.(value as BulkSelectValue);
134+
onSelect?.(value as BulkSelectValue, BulkSelectSource.dropdown);
128135
}}
129136
isOpen={isOpen}
130137
onOpenChange={(isOpen: boolean) => setOpen(isOpen)}
@@ -147,7 +154,7 @@ export const BulkSelect: FC<BulkSelectProps> = ({
147154
? null
148155
: pageSelected || (selectedCount === totalCount && totalCount > 0)
149156
}
150-
onChange={(checked) => onSelect?.(!checked || checked === null ? noneOption : allOption)}
157+
onChange={(checked) => onSelect?.(!checked || checked === null ? noneOption : allOption, BulkSelectSource.checkbox)}
151158
{...menuToggleCheckboxProps}
152159
>
153160
{selectedCount > 0 ? (
@@ -163,7 +170,7 @@ export const BulkSelect: FC<BulkSelectProps> = ({
163170
{...props}
164171
>
165172
<DropdownList {...dropdownListProps}>{splitButtonDropdownItems}</DropdownList>
166-
</Dropdown>)
173+
</Dropdown>
167174
);
168175
};
169176

0 commit comments

Comments
 (0)