Skip to content

Commit cda10b2

Browse files
ElliotLuke Bowerman
andauthored
ActionList: Select Refactor (#1299)
* Added example of bug repro to playground * Refactored select on ActionList - Removed internal "allItems" state - Removed "allitems" state updates via useEffect from ActionListItem - Added "select" prop that accepts object of type "SelectConfig" * Moved itemsSelected into select prop * Updated ActionList - Selecting test suite - Now utilize select object prop * Updated ActionListControlBar to work with updated select prop * Updated Select test * Moved defaultSelectConfig outside of parent describe * Updated select all test suite * Updated Control Bar and Select All tests to use new select prop * Updated Bulk Actions example to use new select prop * Updated clicking bulk actions button test to use select prop * Updated ActionList docs to reflect new select prop * Updated CHANGELOG * Changed property names on select prop - itemsSelected => selectedItems - itemsVisible => pageItems - Creates more consistency with bulk prop naming convention * Removed mention of deprecated canSelect and canSelectAll props * Consolidate ActionList stories / knobs FTW * Restore playground Co-authored-by: Luke Bowerman <[email protected]>
1 parent 00d7b9c commit cda10b2

File tree

12 files changed

+204
-423
lines changed

12 files changed

+204
-423
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4646
- Remove arrow from `Tooltip`, `Popover` and `Menu` by default
4747
- Updates to how we apply colors to `ButtonOutline` and `ButtonTransparent` to be more inline with design spec
4848
- `neutral` intent color is now defaults to `charcoal500`
49+
- `ActionList`
50+
- Updated documentation to include info on control bar behavior
51+
- Refactored select behavior to flow from a single `select` prop object
4952
- Correlates use of color for `Chip`, `ButtonToggle` & `ButtonSet`
5053
- Consolidated `inputHeight` location and usage suite-wide
5154
- `InputChipsBase` updated to use styled() wrapped for Chip margin overrides

packages/components/src/ActionList/ActionList.test.tsx

Lines changed: 77 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,20 @@ const clickableItems = data.map(({ id, name, type }) => {
137137
</ActionListItem>
138138
)
139139
})
140+
140141
const actionListWithClickableRows = (
141142
<ActionList columns={columns}>{clickableItems}</ActionList>
142143
)
143144

145+
const onSelect = jest.fn()
146+
const onSelectAll = jest.fn()
147+
const defaultSelectConfig = {
148+
onSelect,
149+
onSelectAll,
150+
pageItems: ['1', '2'],
151+
selectedItems: [],
152+
}
153+
144154
describe('ActionList', () => {
145155
let rafSpy: jest.SpyInstance<number, [FrameRequestCallback]>
146156

@@ -154,6 +164,8 @@ describe('ActionList', () => {
154164
rafSpy.mockRestore()
155165
handleActionClick.mockClear()
156166
handleListItemClick.mockClear()
167+
onSelect.mockClear()
168+
onSelectAll.mockClear()
157169
})
158170

159171
describe('General Layout', () => {
@@ -277,35 +289,30 @@ describe('ActionList', () => {
277289
})
278290

279291
describe('Selecting', () => {
280-
const onSelect = jest.fn()
281292
const actionListWithSelect = (
282-
<ActionList columns={columns} canSelect onSelect={onSelect}>
293+
<ActionList columns={columns} select={defaultSelectConfig}>
283294
{items}
284295
</ActionList>
285296
)
286-
const actionListWithItemsSelected = (
297+
const actionListWithOnClickRowSelect = (
287298
<ActionList
288299
columns={columns}
289-
canSelect
290-
itemsSelected={['1']}
291-
onSelect={onSelect}
300+
select={{ ...defaultSelectConfig, onClickRowSelect: true }}
292301
>
293302
{items}
294303
</ActionList>
295304
)
296-
const onClickRowSelect = (
305+
const actionListWithSelectedItems = (
297306
<ActionList
298307
columns={columns}
299-
canSelect
300-
onSelect={onSelect}
301-
onClickRowSelect
308+
select={{
309+
...defaultSelectConfig,
310+
selectedItems: ['1'],
311+
}}
302312
>
303313
{items}
304314
</ActionList>
305315
)
306-
afterEach(() => {
307-
onSelect.mockClear()
308-
})
309316

310317
test('Checkbox click calls onSelect', () => {
311318
const { getAllByRole } = renderWithTheme(actionListWithSelect)
@@ -314,70 +321,74 @@ describe('ActionList', () => {
314321
})
315322

316323
test('Row click calls onSelect when onClickRowSelect is true', () => {
317-
const { getByText } = renderWithTheme(onClickRowSelect)
324+
const { getByText } = renderWithTheme(actionListWithOnClickRowSelect)
318325
const nameCell = getByText('Richard Garfield')
319326
fireEvent.click(nameCell)
320327
expect(onSelect).toHaveBeenCalledTimes(1)
321328
})
322329

323-
test('itemsSelected determines if a checkbox is checked', () => {
324-
const { getAllByRole } = renderWithTheme(actionListWithItemsSelected)
330+
test('selectedItems determines if a checkbox is checked', () => {
331+
const { getAllByRole } = renderWithTheme(actionListWithSelectedItems)
325332
const checkbox = getAllByRole('checkbox')[1]
326333
expect((checkbox as HTMLInputElement).checked).toEqual(true)
327334
})
328335
})
329336

330337
describe('Selecting All', () => {
331-
const onSelect = jest.fn()
332-
const onSelectAll = jest.fn()
333-
const props = {
334-
canSelect: true,
335-
canSelectAll: true,
336-
columns,
337-
onSelect,
338-
onSelectAll,
339-
}
340-
341-
const actionListWithSelectAll = <ActionList {...props}>{items}</ActionList>
342-
343338
const actionListWithNoItemsSelected = (
344-
<ActionList {...props} itemsSelected={[]}>
339+
<ActionList columns={columns} select={defaultSelectConfig}>
345340
{items}
346341
</ActionList>
347342
)
348343

349344
const actionListWithSomeItemsSelected = (
350-
<ActionList {...props} itemsSelected={['1']}>
345+
<ActionList
346+
columns={columns}
347+
select={{
348+
...defaultSelectConfig,
349+
selectedItems: ['2'],
350+
}}
351+
>
351352
{items}
352353
</ActionList>
353354
)
354355

355356
const actionListWithAllItemsSelected = (
356-
<ActionList {...props} itemsSelected={['1', '2']}>
357+
<ActionList
358+
columns={columns}
359+
select={{
360+
...defaultSelectConfig,
361+
selectedItems: ['1', '2'],
362+
}}
363+
>
357364
{items}
358365
</ActionList>
359366
)
360367

361-
test('Renders header checkbox that triggers onSelectAll on click when canSelect and canSelectAll are true', () => {
362-
const { getAllByRole } = renderWithTheme(actionListWithSelectAll)
368+
afterEach(() => {
369+
onSelect.mockClear()
370+
onSelectAll.mockClear()
371+
})
363372

373+
test('Renders header checkbox that triggers onSelectAll on click when select prop receives a valid object', () => {
374+
const { getAllByRole } = renderWithTheme(actionListWithNoItemsSelected)
364375
const headerCheckbox = getAllByRole('checkbox')[0]
365376
fireEvent.click(headerCheckbox)
366377
expect(onSelectAll).toHaveBeenCalledTimes(1)
367378
})
368379

369-
test('Header checkbox is unchecked when itemsSelected includes no row ids', () => {
380+
test('Header checkbox is unchecked when selectedItems includes no row ids', () => {
370381
const { getAllByRole } = renderWithTheme(actionListWithNoItemsSelected)
371382
const headerCheckbox = getAllByRole('checkbox')[0] as HTMLInputElement
372383
expect(headerCheckbox.checked).toEqual(false)
373384
})
374385

375-
test('Header checkbox is mixed when itemsSelected includes some row ids', () => {
386+
test('Header checkbox is mixed when selectedItems includes some row ids', () => {
376387
const { getByTitle } = renderWithTheme(actionListWithSomeItemsSelected)
377388
getByTitle('Check Mark Mixed')
378389
})
379390

380-
test('Header checkbox is mixed when itemsSelected includes all row ids', () => {
391+
test('Header checkbox is mixed when selectedItems includes all row ids', () => {
381392
const { getAllByRole } = renderWithTheme(actionListWithAllItemsSelected)
382393
const headerCheckbox = getAllByRole('checkbox')[0] as HTMLInputElement
383394
expect(headerCheckbox.checked).toEqual(true)
@@ -407,9 +418,13 @@ describe('ActionList', () => {
407418
totalCount: 4,
408419
}
409420

410-
test('Control bar is visible when bulk prop is provided and itemsSelected prop has length >0', () => {
421+
test('Control bar is visible when bulk prop is provided and selectedItems prop has length > 0', () => {
411422
const { getByText } = renderWithTheme(
412-
<ActionList columns={columns} bulk={bulk} itemsSelected={['1']}>
423+
<ActionList
424+
columns={columns}
425+
bulk={bulk}
426+
select={{ ...defaultSelectConfig, selectedItems: ['1'] }}
427+
>
413428
{items}
414429
</ActionList>
415430
)
@@ -421,17 +436,24 @@ describe('ActionList', () => {
421436

422437
test('Control bar is not visible when bulk prop is not provided', () => {
423438
const { queryByText } = renderWithTheme(
424-
<ActionList columns={columns} itemsSelected={['1']}>
439+
<ActionList
440+
columns={columns}
441+
select={{ ...defaultSelectConfig, selectedItems: ['1'] }}
442+
>
425443
{items}
426444
</ActionList>
427445
)
428446

429447
expect(queryByText('Bulk Actions')).not.toBeInTheDocument()
430448
})
431449

432-
test('Control bar is not visible when itemsSelected.length < 0', () => {
450+
test('Control bar is not visible when selectedItems.length < 0', () => {
433451
const { queryByText } = renderWithTheme(
434-
<ActionList columns={columns} bulk={bulk} itemsSelected={[]}>
452+
<ActionList
453+
columns={columns}
454+
bulk={bulk}
455+
select={{ ...defaultSelectConfig, selectedItems: [] }}
456+
>
435457
{items}
436458
</ActionList>
437459
)
@@ -441,7 +463,11 @@ describe('ActionList', () => {
441463

442464
test('Clicking the "Bulk Actions" button reveals elements passed via bulk prop', () => {
443465
const { getByText, queryByText } = renderWithTheme(
444-
<ActionList columns={columns} bulk={bulk} itemsSelected={['1']}>
466+
<ActionList
467+
columns={columns}
468+
bulk={bulk}
469+
select={{ ...defaultSelectConfig, selectedItems: ['1'] }}
470+
>
445471
{items}
446472
</ActionList>
447473
)
@@ -459,7 +485,11 @@ describe('ActionList', () => {
459485

460486
test('Pressing "Select all X Results" button triggers onTotalSelectAll', () => {
461487
const { getByText } = renderWithTheme(
462-
<ActionList columns={columns} bulk={bulk} itemsSelected={['1']}>
488+
<ActionList
489+
columns={columns}
490+
bulk={bulk}
491+
select={{ ...defaultSelectConfig, selectedItems: ['1'] }}
492+
>
463493
{items}
464494
</ActionList>
465495
)
@@ -474,7 +504,10 @@ describe('ActionList', () => {
474504
<ActionList
475505
columns={columns}
476506
bulk={bulk}
477-
itemsSelected={['1', '2', '3', '4']}
507+
select={{
508+
...defaultSelectConfig,
509+
selectedItems: ['1', '2', '3', '4'],
510+
}}
478511
>
479512
{items}
480513
</ActionList>

0 commit comments

Comments
 (0)