Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a “SELECT ALL” button in the <BulkActionsToolbar> #10367

Merged
merged 147 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
147 commits
Select commit Hold shift + click to select a range
972e9dd
Add a "Select all" button + make it customizable + document jsDoc
erwanMarmelab Nov 20, 2024
9656803
add logic in useList
erwanMarmelab Nov 20, 2024
91b874f
wrap function with a useCallback
erwanMarmelab Nov 20, 2024
4cd44ea
add more data in the story to be able to test the "SELECT ALL" button
erwanMarmelab Nov 20, 2024
6178ee5
simplify the areAllSelected check
erwanMarmelab Nov 21, 2024
9e26228
add select all button on ReferenceManyField
erwanMarmelab Nov 21, 2024
dc18571
add a full app story with ReferenceManyField
erwanMarmelab Nov 21, 2024
426c9f5
remove the useless selectAllLimit prop from useList
erwanMarmelab Nov 21, 2024
5721ae9
add a SELECT ALL button for ReferenceArrayField
erwanMarmelab Nov 21, 2024
02eef0b
add SELECT ALL button on infiniteList + story + selectAllLimit
erwanMarmelab Nov 21, 2024
60b0b9a
change call on mount to mutation on callback
erwanMarmelab Nov 21, 2024
651ac4b
display error + fix getManyReference call
erwanMarmelab Nov 21, 2024
73f8e7e
add stories for ReferenceManyField for Pagination and selectAllLimit
erwanMarmelab Nov 21, 2024
d214481
add stories for List with selectAllLimit
erwanMarmelab Nov 21, 2024
76d9214
remove useless modification
erwanMarmelab Nov 21, 2024
1885e48
Fix Datagrid and ExpandAllButton tests
erwanMarmelab Nov 21, 2024
4c73b9c
Fix BulkUpdateButton test
erwanMarmelab Nov 21, 2024
548968d
add selectAllLimit to UseReferenceArrayFieldControllerParams to fix b…
erwanMarmelab Nov 21, 2024
dd7cf02
rename `areAllSelected` to `displaySelectAllButton`
erwanMarmelab Nov 22, 2024
9eb0f1c
test useListController
erwanMarmelab Nov 22, 2024
4546b6e
test useInfiniteListController
erwanMarmelab Nov 22, 2024
a374f05
test useReferenceArrayFieldController
erwanMarmelab Nov 22, 2024
38261a7
test useReferenceManyFieldController
erwanMarmelab Nov 22, 2024
7d73c0d
test useList
erwanMarmelab Nov 22, 2024
4182bb6
do not display "Select all" button if nb selected items > selectAllLimit
erwanMarmelab Nov 22, 2024
4f28a99
test `<List>`
erwanMarmelab Nov 22, 2024
c49c28c
test `<ReferenceManyField>` + fix ts issues
erwanMarmelab Nov 22, 2024
56db339
test `<ReferenceArrayField>` + fix ts issues
erwanMarmelab Nov 22, 2024
f82dd52
fix useInfiniteListController tests
erwanMarmelab Nov 25, 2024
db66a99
document `<List selectAllLimit>`
erwanMarmelab Nov 25, 2024
473a9f9
document `<ReferenceManyField selectAllLimit>`
erwanMarmelab Nov 25, 2024
0a6ff63
fix List tests
erwanMarmelab Nov 25, 2024
9162761
fix typos
erwanMarmelab Nov 26, 2024
cadc723
Simplify tests
erwanMarmelab Nov 26, 2024
538076c
simplify spacings in bulkActionToolbar
erwanMarmelab Nov 26, 2024
5b30150
rename displaySelectAllButton to areAllItemsSelected
erwanMarmelab Nov 26, 2024
a30dd17
create the `useSelectAll` hook
erwanMarmelab Nov 27, 2024
59024b4
fix ReferenceArrayInput
erwanMarmelab Nov 27, 2024
0846132
change `useMutation` to `queryClient.fetchQuery`
erwanMarmelab Nov 27, 2024
a3a9b8b
Isolate test components in stories-> `useReferenceArrayField`
erwanMarmelab Dec 2, 2024
30c1d28
Isolate test components in stories-> `useReferenceManyField`
erwanMarmelab Dec 2, 2024
7e0f92d
Isolate test components in stories-> `useInfiniteListController`
erwanMarmelab Dec 2, 2024
d9f1a59
Isolate test components in stories-> `useListController`
erwanMarmelab Dec 2, 2024
04ddc21
change `useMutation` to `queryClient.fetchQuery` in `useReferenceMany…
erwanMarmelab Dec 2, 2024
31c996b
change the structure
erwanMarmelab Dec 5, 2024
2b6e1d8
remove useless tests
erwanMarmelab Dec 5, 2024
f27f69b
remove useless stories
erwanMarmelab Dec 5, 2024
1b94c81
remove useless props + improve comments
erwanMarmelab Dec 6, 2024
af1427b
Add stories for SelectAllButton
erwanMarmelab Dec 6, 2024
52bcdd1
test SelectAllButton
erwanMarmelab Dec 6, 2024
1b0e974
add a name + support onClick
erwanMarmelab Dec 6, 2024
eb73fbd
document select all
erwanMarmelab Dec 6, 2024
e8f64e3
Fix SelectAllButton tests
erwanMarmelab Dec 6, 2024
97a338e
remove old structure with `selectAllLimit`
erwanMarmelab Dec 6, 2024
472b81b
change (again) the structure to have a button and logic in hooks
erwanMarmelab Dec 8, 2024
447d793
ReferenceArrayFieldController -> tests + stories
erwanMarmelab Dec 8, 2024
588767c
make the callback stronger
erwanMarmelab Dec 8, 2024
4573ae9
ReferenceManyFieldController -> tests + stories
erwanMarmelab Dec 8, 2024
98c48c7
moove useRecordSelection and useResourceContext logic
erwanMarmelab Dec 8, 2024
2f1f7db
InfiniteListController -> tests + stories
erwanMarmelab Dec 8, 2024
ad0a805
eListController -> tests + stories
erwanMarmelab Dec 8, 2024
c658335
test useList
erwanMarmelab Dec 8, 2024
420cfad
ReferenceManyField -> tests + stories
erwanMarmelab Dec 8, 2024
7401122
InfiniteList -> limit -> stories
erwanMarmelab Dec 8, 2024
1e41bc3
List -> tests + stories
erwanMarmelab Dec 8, 2024
c18a232
Improve documentation sentences
erwanMarmelab Dec 11, 2024
a4c7a82
Improve jsDoc of selectionModifiers
erwanMarmelab Dec 11, 2024
03d9afc
remove the duplicated `resource` from the query
erwanMarmelab Dec 11, 2024
f1b4091
add the missing frenc translation + reorder alphabetically the messages
erwanMarmelab Dec 11, 2024
6f8e99b
rename message `too_many_elements` into `select_all_limit_reached`
erwanMarmelab Dec 11, 2024
4e86cd8
Remove the `Warning` from the `select_all_limit_reached` message
erwanMarmelab Dec 11, 2024
755571e
Remove the `Warning` from the `select_all_limit_reached` message in t…
erwanMarmelab Dec 11, 2024
b8f8413
remove useless `console.error`
erwanMarmelab Dec 11, 2024
f1d4000
create a translation for the error message + add a type to the notif …
erwanMarmelab Dec 11, 2024
400d85f
rename `onSelectAllProps` into `onSelectAllParams`
erwanMarmelab Dec 11, 2024
bf47b5e
remove `selectionModifiers` from props to import it with a hook
erwanMarmelab Dec 11, 2024
8916730
apply the deletion of the `selectionMofifiers` prop
erwanMarmelab Dec 11, 2024
b56f600
apply the PREFIX to the CSS in JS instead of HTML attribute
erwanMarmelab Dec 11, 2024
7e7a05c
add a transated message dedicated for the select all button + fix Tra…
erwanMarmelab Dec 11, 2024
05dcd17
rename `onSelectAll` into `handleSelectAll` in `useSelectAll` (not in…
erwanMarmelab Dec 11, 2024
570170b
fix ts error
erwanMarmelab Dec 11, 2024
11b0422
use `useEvent` instead of `useCallback`
erwanMarmelab Dec 11, 2024
3da72ef
revert useless style changes
erwanMarmelab Dec 11, 2024
f02863b
group type imports
erwanMarmelab Dec 11, 2024
2f315dd
make data mare plausible
erwanMarmelab Dec 11, 2024
592824f
fix typo in `ListWithCheckboxes` title
erwanMarmelab Dec 11, 2024
14c3aa3
pass `{children}` as child instead of as prop
erwanMarmelab Dec 11, 2024
9dc0e64
stop using `act` in tests
erwanMarmelab Dec 13, 2024
4b53460
rename `spiedChildren` into `callback`
erwanMarmelab Dec 13, 2024
3e8272a
do write twice the spied func -> just spy it
erwanMarmelab Dec 13, 2024
b9142ae
pass children as child instead of prop
erwanMarmelab Dec 13, 2024
17b4b30
improve test names
erwanMarmelab Dec 13, 2024
0c25426
improve story label
erwanMarmelab Dec 13, 2024
8a647e5
isolate type imports
erwanMarmelab Dec 13, 2024
7f119de
adapt test with the new button label
erwanMarmelab Dec 13, 2024
605f303
moove the `SelectAllButton`
erwanMarmelab Dec 13, 2024
3563517
test the new `bulkActionsToolbar` Datagrid's prop
erwanMarmelab Dec 13, 2024
0f0b22e
Adapt SelectAllButton doc to the new place
erwanMarmelab Dec 13, 2024
4cfc3a2
Update Datagrid doc
erwanMarmelab Dec 13, 2024
92893c4
update screenshot
erwanMarmelab Dec 13, 2024
b2ed592
fix typo
erwanMarmelab Dec 13, 2024
aae3600
useSelectAll -> test + stories
erwanMarmelab Dec 13, 2024
7cf12a8
improve jsDoc
erwanMarmelab Dec 13, 2024
3f3cbfe
improve `SelectAllButton` introduction's doc
erwanMarmelab Dec 17, 2024
361153e
update the selection button name
erwanMarmelab Dec 17, 2024
68adcf9
rename stories
erwanMarmelab Dec 17, 2024
0231d03
fix ts errors + use story in tests
erwanMarmelab Dec 17, 2024
c8d447b
isolate tests into stories
erwanMarmelab Dec 17, 2024
ea989da
simplify tests (afterEach of Select All tests)
erwanMarmelab Dec 17, 2024
56f48a5
don't pass children to the tests -> `useReferenceArrayFieldController`
erwanMarmelab Dec 18, 2024
cb70247
don't pass children to the tests -> `useReferenceManyFieldController`
erwanMarmelab Dec 18, 2024
db74e83
don't pass children to the tests -> `useInfiniteListController`
erwanMarmelab Dec 18, 2024
8787f5b
don't pass children to the tests -> `useList`
erwanMarmelab Dec 18, 2024
122dae6
simplify tests
erwanMarmelab Dec 18, 2024
2abf955
don't pass children to the tests -> `useListController`
erwanMarmelab Dec 18, 2024
54c8e6e
clean file
erwanMarmelab Dec 18, 2024
ec85bf9
clean file
erwanMarmelab Dec 18, 2024
fbb290c
display SelectAllButton if all data are selected
erwanMarmelab Dec 18, 2024
4f4feff
adapt tests `SelectAllButton` + add a test on the new display condition
erwanMarmelab Dec 18, 2024
e5fdcb7
adapt tests `Datagrid`
erwanMarmelab Dec 18, 2024
2d9822d
simplify stories
erwanMarmelab Dec 18, 2024
1bd2dcb
adapt tests `List`
erwanMarmelab Dec 18, 2024
f5144e8
adapt tests `ReferenceManyField`
erwanMarmelab Dec 18, 2024
b300053
adapt tests `ReferenceArrayField`
erwanMarmelab Dec 18, 2024
65ad280
Merge branch 'next' into feat/next/select_all
erwanMarmelab Dec 18, 2024
614f4d1
improve buttons color
erwanMarmelab Dec 18, 2024
9df60b1
Adapt ExpandAllButton's test with the new story
erwanMarmelab Dec 19, 2024
969fd83
fix linter warning
erwanMarmelab Jan 2, 2025
832e4ba
add a usage section
erwanMarmelab Jan 2, 2025
3309535
remove the `bulkActionsToolbar` prop and create `selectAllButton`'s prop
erwanMarmelab Jan 2, 2025
75f21ef
improve jsDoc example
erwanMarmelab Jan 2, 2025
0a2399a
wrap tests in some `describe`
erwanMarmelab Jan 2, 2025
c5d2722
rename `handleSelectAll` into `handleClick`
erwanMarmelab Jan 2, 2025
781ab5a
fix typo
erwanMarmelab Jan 2, 2025
0bbb005
Rename `List` into `ListView`
erwanMarmelab Jan 2, 2025
ed4713a
rename story files
erwanMarmelab Jan 2, 2025
315b9a9
add `target` and `id` to the queryKey
erwanMarmelab Jan 2, 2025
6aac661
test the right spot for useSelectAll
erwanMarmelab Jan 2, 2025
d8c0992
use http_error instead of simple_error
erwanMarmelab Jan 2, 2025
b27fe7c
make test more logic
erwanMarmelab Jan 2, 2025
2f3ed8a
rename tests
erwanMarmelab Jan 2, 2025
002f485
fix tests
erwanMarmelab Jan 2, 2025
420ab1d
update the bulkActionsToolbar implementation
erwanMarmelab Jan 3, 2025
68fe92c
adapt stories with the last implem to fix stories
erwanMarmelab Jan 3, 2025
2ebbcad
Misc adjustments
fzaninotto Jan 3, 2025
b4c0f8d
Capitalize type name
fzaninotto Jan 3, 2025
31b3bd5
Fix TS compilation error
fzaninotto Jan 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions docs/Buttons.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ React-Admin provides button components for all the common uses.
- [`<BulkUpdateButton>`](#bulkupdatebutton)
- [`<BulkUpdateFormButton>`](#bulkupdateformbutton)
- [`<FilterButton>`](#filterbutton)
- [`<SelectAllButton>`](#selectallbutton)

- **Record Buttons**: To be used in detail views
- [`<UpdateButton>`](#updatebutton)
Expand Down Expand Up @@ -1010,6 +1011,79 @@ If your `authProvider` implements [Access Control](./Permissions.md#access-contr

## `<RefreshButton>`

## `<SelectAllButton>`

The `<SelectAllButton>` component allows users to select all items from a resource, no matter the pagination.

![SelectAllButton](./img/SelectAllButton.png)

### Usage

By default, react-admin's `<Datagrid>` displays a `<SelectAllButton>` in its `bulkActionsToolbar`. You can customize it by specifying your own `<BulkActionsToolbar selectAllButton>`:

{% raw %}

```jsx
import { List, Datagrid, BulkActionsToolbar, SelectAllButton, BulkDeleteButton } from 'react-admin';

const PostSelectAllButton = () => (
<SelectAllButton
label="Select all records"
queryOptions={{ meta: { foo: 'bar' } }}
/>
);

export const PostList = () => (
<List>
<Datagrid
bulkActionsToolbar={
<BulkActionsToolbar selectAllButton={PostSelectAllButton}>
<BulkDeleteButton />
</BulkActionsToolbar>
}
>
...
</Datagrid>
</List>
);
```

{% endraw %}

### `label`

By default, the `<SelectAllButton>` label is "Select all" (or the `ra.action.select_all_button` message translation). You can also pass a custom `label`:

```jsx
const PostSelectAllButton = () => <SelectAllButton label="Select all posts" />;
```

**Tip**: The label will go through [the `useTranslate` hook](./useTranslate.md), so you can use translation keys.

### `limit`

By default, `<SelectAllButton>` selects the 250 first items of your list. To customize this limit, you can use the `limit` prop:

```jsx
const PostSelectAllButton = () => <SelectAllButton limit={100} />;
```

### `queryOptions`

`<SelectAllButton>` calls a `get` method of your `dataProvider` via a react-query's `useQuery` hook. You can customize the options you pass to this hook, e.g. to pass [a custom `meta`](./Actions.md#meta-parameter) to the call.

{% raw %}

```jsx
const PostSelectAllButton = () => <SelectAllButton queryOptions={{ meta: { foo: 'bar' } }} />;
```

{% endraw %}

### `sx`: CSS API

To override the style of all instances of `<SelectAllButton>` components using the [application-wide style overrides](./AppTheme.md#theming-individual-components), use the `RaSelectAllButton` key.

## `<SkipNavigationButton>`

### `sx`: CSS API
Expand Down
36 changes: 18 additions & 18 deletions docs/Datagrid.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,24 +45,24 @@ Both are [Enterprise Edition](https://react-admin-ee.marmelab.com) components.

## Props

| Prop | Required | Type | Default | Description |
| ------------------- | -------- | ----------------------- | --------------------- | ------------------------------------------------------------- |
| `children` | Required | Element | n/a | The list of `<Field>` components to render as columns. |
| `body` | Optional | Element | `<Datagrid Body>` | The component used to render the body of the table. |
| `bulkActionButtons` | Optional | Element | `<BulkDelete Button>` | The component used to render the bulk action buttons. |
| `empty` | Optional | Element | `<Empty>` | The component used to render the empty table. |
| `expand` | Optional | Element | | The component used to render the expand panel for each row. |
| `expandSingle` | Optional | Boolean | `false` | Whether to allow only one expanded row at a time. |
| `header` | Optional | Element | `<Datagrid Header>` | The component used to render the table header. |
| `hover` | Optional | Boolean | `true` | Whether to highlight the row under the mouse. |
| `isRowExpandable` | Optional | Function | `() => true` | A function that returns whether a row is expandable. |
| `isRowSelectable` | Optional | Function | `() => true` | A function that returns whether a row is selectable. |
| `optimized` | Optional | Boolean | `false` | Whether to optimize the rendering of the table. |
| `rowClick` | Optional | mixed | | The action to trigger when the user clicks on a row. |
| `rowStyle` | Optional | Function | | A function that returns the style to apply to a row. |
| `rowSx` | Optional | Function | | A function that returns the sx prop to apply to a row. |
| `size` | Optional | `'small'` or `'medium'` | `'small'` | The size of the table. |
| `sx` | Optional | Object | | The sx prop passed down to the Material UI `<Table>` element. |
| Prop | Required | Type | Default | Description |
| -------------------- | -------- | ----------------------- | --------------------- | ------------------------------------------------------------- |
| `children` | Required | Element | n/a | The list of `<Field>` components to render as columns. |
| `body` | Optional | Element | `<Datagrid Body>` | The component used to render the body of the table. |
| `bulkActionButtons` | Optional | Element | `<BulkDelete Button>` | The component used to render the bulk action buttons. |
| `empty` | Optional | Element | `<Empty>` | The component used to render the empty table. |
| `expand` | Optional | Element | | The component used to render the expand panel for each row. |
| `expandSingle` | Optional | Boolean | `false` | Whether to allow only one expanded row at a time. |
| `header` | Optional | Element | `<Datagrid Header>` | The component used to render the table header. |
| `hover` | Optional | Boolean | `true` | Whether to highlight the row under the mouse. |
| `isRowExpandable` | Optional | Function | `() => true` | A function that returns whether a row is expandable. |
| `isRowSelectable` | Optional | Function | `() => true` | A function that returns whether a row is selectable. |
| `optimized` | Optional | Boolean | `false` | Whether to optimize the rendering of the table. |
| `rowClick` | Optional | mixed | | The action to trigger when the user clicks on a row. |
| `rowStyle` | Optional | Function | | A function that returns the style to apply to a row. |
| `rowSx` | Optional | Function | | A function that returns the sx prop to apply to a row. |
| `size` | Optional | `'small'` or `'medium'` | `'small'` | The size of the table. |
| `sx` | Optional | Object | | The sx prop passed down to the Material UI `<Table>` element. |

Additional props are passed down to [the Material UI `<Table>` element](https://mui.com/material-ui/api/table/).

Expand Down
1 change: 1 addition & 0 deletions docs/Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ title: "Index"
* [`<Search>`](./Search.md)<img class="icon" src="./img/premium.svg" />
* [`<SearchInput>`](./SearchInput.md)
* [`<SearchWithResult>`](./SearchWithResult.md)<img class="icon" src="./img/premium.svg" />
* [`<SelectAllButton>`](./Buttons.md#selectallbutton)
* [`<SelectArrayInput>`](./SelectArrayInput.md)
* [`<SelectColumnsButton>`](./SelectColumnsButton.md)
* [`<SelectField>`](./SelectField.md)
Expand Down
Binary file added docs/img/SelectAllButton.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as React from 'react';
import expect from 'expect';
import { render, waitFor } from '@testing-library/react';
import { render, waitFor, screen, fireEvent } from '@testing-library/react';

import { useReferenceArrayFieldController } from './useReferenceArrayFieldController';
import { testDataProvider } from '../../dataProvider';
import { CoreAdminContext } from '../../core';
import { Basic } from './useReferenceArrayFieldController.stories';

const ReferenceArrayFieldController = props => {
const { children, ...rest } = props;
Expand Down Expand Up @@ -166,4 +167,42 @@ describe('<useReferenceArrayFieldController />', () => {
})
);
});

describe('onSelectAll', () => {
it('should select all records', async () => {
render(<Basic />);
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: []'
);
});
fireEvent.click(await screen.findByText('Select All'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [1,2]'
);
});
});

it('should select all records even though some records are already selected', async () => {
render(<Basic />);
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: []'
);
});
fireEvent.click(await screen.findByTestId('checkbox-1'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [1]'
);
});
fireEvent.click(await screen.findByText('Select All'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [1,2]'
);
});
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import * as React from 'react';
import {
CoreAdminContext,
type GetManyResult,
type ListControllerResult,
testDataProvider,
useReferenceArrayFieldController,
} from '../..';

const dataProvider = testDataProvider({
getMany: (_resource, _params): Promise<GetManyResult> =>
Promise.resolve({
data: [
{ id: 1, title: 'bar1' },
{ id: 2, title: 'bar2' },
],
}),
});

/**
* Render prop version of the controller hook
*/
const ReferenceArrayFieldController = props => {
const { children, ...rest } = props;
const controllerProps = useReferenceArrayFieldController({
sort: {
field: 'id',
order: 'ASC',
},
...rest,
});
return children(controllerProps);
};

const defaultRenderProp = (props: ListControllerResult) => (
<div>
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '10px',
}}
>
<button
onClick={() => props.onSelectAll()}
disabled={props.total === props.selectedIds.length}
>
Select All
</button>
<button
onClick={props.onUnselectItems}
disabled={props.selectedIds.length === 0}
>
Unselect All
</button>
<p data-testid="selected_ids">
Selected ids: {JSON.stringify(props.selectedIds)}
</p>
</div>
<ul
style={{
listStyleType: 'none',
}}
>
{props.data?.map(record => (
<li key={record.id}>
<input
type="checkbox"
checked={props.selectedIds.includes(record.id)}
onChange={() => props.onToggleItem(record.id)}
style={{
cursor: 'pointer',
marginRight: '10px',
}}
data-testid={`checkbox-${record.id}`}
/>
{record.id} - {record.title}
</li>
))}
</ul>
</div>
);

export const Basic = ({ children = defaultRenderProp }) => (
<CoreAdminContext dataProvider={dataProvider}>
<ReferenceArrayFieldController
resource="foo"
reference="bar"
record={{ id: 1, barIds: [1, 2] }}
source="barIds"
>
{children}
</ReferenceArrayFieldController>
</CoreAdminContext>
);

export default {
title: 'ra-core/controller/useReferenceArrayFieldController',
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import { testDataProvider } from '../../dataProvider/testDataProvider';
import { CoreAdminContext } from '../../core';
import { useReferenceManyFieldController } from './useReferenceManyFieldController';
import { memoryStore } from '../../store';
import {
Basic,
defaultDataProvider,
} from './useReferenceManyFieldController.stories';

const ReferenceManyFieldController = props => {
const { children, page = 1, perPage = 25, ...rest } = props;
Expand Down Expand Up @@ -412,4 +416,70 @@ describe('useReferenceManyFieldController', () => {
);
});
});

describe('onSelectAll', () => {
it('should select all records', async () => {
render(<Basic />);
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: []'
);
});
fireEvent.click(await screen.findByText('Select All'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [0,1]'
);
});
});

it('should select all records even though some records are already selected', async () => {
render(<Basic />);
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: []'
);
});
fireEvent.click(await screen.findByTestId('checkbox-1'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [1]'
);
});
fireEvent.click(await screen.findByText('Select All'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [0,1]'
);
});
});

it('should not select more records than the provided limit', async () => {
const dataProvider = defaultDataProvider;
const getManyReference = jest.spyOn(
dataProvider,
'getManyReference'
);
render(<Basic dataProvider={dataProvider} />);
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: []'
);
});
fireEvent.click(await screen.findByText('Limited Select All'));
await waitFor(() => {
expect(screen.getByTestId('selected_ids').textContent).toBe(
'Selected ids: [0]'
);
});
await waitFor(() => {
expect(getManyReference).toHaveBeenCalledWith(
'books',
expect.objectContaining({
pagination: { page: 1, perPage: 1 },
})
);
});
});
});
});
Loading
Loading