Skip to content

Commit ea10102

Browse files
committed
add some unit tests about store/code synchronization
1 parent f0f763a commit ea10102

File tree

2 files changed

+213
-4
lines changed

2 files changed

+213
-4
lines changed

packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.spec.tsx

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,13 @@ import {
88
PreferenceKey,
99
LabelElement,
1010
NullChildren,
11+
Wrapper,
12+
data,
1113
} from './DatagridConfigurable.stories';
14+
import { DatagridConfigurable } from './DatagridConfigurable';
15+
import { TextField } from '../../field';
16+
import { EditButton } from '../../button';
17+
import { memoryStore } from 'ra-core';
1218

1319
describe('<DatagridConfigurable>', () => {
1420
it('should render a datagrid with configurable columns', async () => {
@@ -103,4 +109,186 @@ describe('<DatagridConfigurable>', () => {
103109
expect(screen.queryAllByText('War and Peace')).toHaveLength(1);
104110
});
105111
});
112+
describe('store/code synchronization', () => {
113+
const storeDefaultValue = {
114+
preferences: {
115+
books1: {
116+
datagrid: {
117+
columns: ['0', '1', '2', '3', '4'],
118+
availableColumns: [
119+
{
120+
index: '0',
121+
source: 'id',
122+
},
123+
{
124+
index: '1',
125+
source: 'title',
126+
label: 'Original title',
127+
},
128+
{
129+
index: '2',
130+
source: 'author',
131+
},
132+
{
133+
index: '3',
134+
source: 'year',
135+
},
136+
{
137+
index: '4',
138+
label: 'Unlabeled column #4',
139+
},
140+
],
141+
},
142+
},
143+
},
144+
};
145+
146+
it('should preserve hidden columns from the store when column order is changed in the code', async () => {
147+
const store = memoryStore(storeDefaultValue);
148+
// hide the 'year' column
149+
store.setItem('preferences.books1.datagrid.columns', [
150+
'0',
151+
'1',
152+
'2',
153+
'4',
154+
]);
155+
const { rerender } = render(
156+
<Wrapper store={store}>
157+
<DatagridConfigurable
158+
resource="books1"
159+
data={data}
160+
sort={{ field: 'title', order: 'ASC' }}
161+
bulkActionButtons={false}
162+
>
163+
<TextField source="id" />
164+
<TextField source="title" label="Original title" />
165+
<TextField source="author" />
166+
<TextField source="year" />
167+
<EditButton />
168+
</DatagridConfigurable>
169+
</Wrapper>
170+
);
171+
172+
await screen.findByText('Leo Tolstoy');
173+
// Year column should be hidden
174+
expect(screen.queryByText('1869')).toBeNull();
175+
// Store value should be preserved
176+
expect(
177+
store.getItem('preferences.books1.datagrid.columns')
178+
).toEqual(['0', '1', '2', '4']);
179+
180+
// Render something else (to be able to tell when the next rerender is finished)
181+
rerender(<Wrapper store={store}>Something Else</Wrapper>);
182+
await screen.findByText('Something Else');
183+
184+
// Invert 'year' and 'author' columns
185+
rerender(
186+
<Wrapper store={store}>
187+
<DatagridConfigurable
188+
resource="books1"
189+
data={data}
190+
sort={{ field: 'title', order: 'ASC' }}
191+
bulkActionButtons={false}
192+
>
193+
<TextField source="id" />
194+
<TextField source="title" label="Original title" />
195+
<TextField source="year" />
196+
<TextField source="author" />
197+
<EditButton />
198+
</DatagridConfigurable>
199+
</Wrapper>
200+
);
201+
await screen.findByText('Leo Tolstoy');
202+
// Year column should still be hidden
203+
expect(screen.queryByText('1869')).toBeNull();
204+
// Store value should be updated
205+
expect(
206+
store.getItem('preferences.books1.datagrid.columns')
207+
).toEqual(['0', '1', '3', '4']);
208+
});
209+
210+
it('should preserve hidden columns from the store when a column is renamed in the code', async () => {
211+
const store = memoryStore(storeDefaultValue);
212+
// invert the 'year' and 'author' columns
213+
store.setItem('preferences.books1.datagrid.columns', [
214+
'0',
215+
'1',
216+
'3',
217+
'2',
218+
'4',
219+
]);
220+
store.setItem('preferences.books1.datagrid.availableColumns', [
221+
{
222+
index: '0',
223+
source: 'id',
224+
},
225+
{
226+
index: '1',
227+
source: 'title',
228+
label: 'Original title',
229+
},
230+
{
231+
index: '3',
232+
source: 'year',
233+
},
234+
{
235+
index: '2',
236+
source: 'author',
237+
},
238+
{
239+
index: '4',
240+
label: 'Unlabeled column #4',
241+
},
242+
]);
243+
const { rerender } = render(
244+
<Wrapper store={store}>
245+
<DatagridConfigurable
246+
resource="books1"
247+
data={data}
248+
sort={{ field: 'title', order: 'ASC' }}
249+
bulkActionButtons={false}
250+
>
251+
<TextField source="id" />
252+
<TextField source="title" label="Original title" />
253+
<TextField source="author" />
254+
<TextField source="year" />
255+
<EditButton />
256+
</DatagridConfigurable>
257+
</Wrapper>
258+
);
259+
260+
await screen.findByText('Leo Tolstoy');
261+
// Store value should be preserved
262+
expect(
263+
store.getItem('preferences.books1.datagrid.columns')
264+
).toEqual(['0', '1', '3', '2', '4']);
265+
266+
// Render something else (to be able to tell when the next rerender is finished)
267+
rerender(<Wrapper store={store}>Something Else</Wrapper>);
268+
await screen.findByText('Something Else');
269+
270+
// Rename the 'title' column
271+
rerender(
272+
<Wrapper store={store}>
273+
<DatagridConfigurable
274+
resource="books1"
275+
data={data}
276+
sort={{ field: 'title', order: 'ASC' }}
277+
bulkActionButtons={false}
278+
>
279+
<TextField source="id" />
280+
<TextField source="title" label="New title" />
281+
<TextField source="author" />
282+
<TextField source="year" />
283+
<EditButton />
284+
</DatagridConfigurable>
285+
</Wrapper>
286+
);
287+
await screen.findByText('Leo Tolstoy');
288+
// Store value should be preserved
289+
expect(
290+
store.getItem('preferences.books1.datagrid.columns')
291+
).toEqual(['0', '1', '3', '2', '4']);
292+
});
293+
});
106294
});

packages/ra-ui-materialui/src/list/datagrid/DatagridConfigurable.stories.tsx

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
StoreContextProvider,
66
PreferencesEditorContextProvider,
77
TestMemoryRouter,
8+
localStorageStore,
89
} from 'ra-core';
910

1011
import { DatagridConfigurable } from './DatagridConfigurable';
@@ -13,9 +14,12 @@ import { TextField } from '../../field';
1314
import { EditButton } from '../../button';
1415
import { createTheme, ThemeProvider } from '@mui/material/styles';
1516

16-
export default { title: 'ra-ui-materialui/list/DatagridConfigurable' };
17+
export default {
18+
title: 'ra-ui-materialui/list/DatagridConfigurable',
19+
excludeStories: ['data', 'Wrapper'],
20+
};
1721

18-
const data = [
22+
export const data = [
1923
{
2024
id: 1,
2125
title: 'War and Peace',
@@ -46,8 +50,8 @@ const AuthorField = () => <TextField label="Author" source="author" />;
4650

4751
const theme = createTheme();
4852

49-
const Wrapper = ({ children }) => (
50-
<StoreContextProvider value={memoryStore()}>
53+
export const Wrapper = ({ children, store = memoryStore() }) => (
54+
<StoreContextProvider value={store}>
5155
<ThemeProvider theme={theme}>
5256
<PreferencesEditorContextProvider>
5357
<TestMemoryRouter>
@@ -160,3 +164,20 @@ export const NullChildren = () => (
160164
</DatagridConfigurable>
161165
</Wrapper>
162166
);
167+
168+
export const LocalStorage = () => (
169+
<Wrapper store={localStorageStore()}>
170+
<DatagridConfigurable
171+
resource="books1"
172+
data={data}
173+
sort={{ field: 'title', order: 'ASC' }}
174+
bulkActionButtons={false}
175+
>
176+
<TextField source="id" />
177+
<TextField source="title" label="Original title" />
178+
<TextField source="author" />
179+
<TextField source="year" />
180+
<EditButton />
181+
</DatagridConfigurable>
182+
</Wrapper>
183+
);

0 commit comments

Comments
 (0)