Skip to content

Commit 7afc76c

Browse files
committed
add stories and test for useList storeKey
1 parent 0444dd0 commit 7afc76c

File tree

2 files changed

+284
-0
lines changed

2 files changed

+284
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import * as React from 'react';
2+
import {
3+
render,
4+
fireEvent,
5+
screen,
6+
waitFor,
7+
act,
8+
} from '@testing-library/react';
9+
import {
10+
ListsWithoutStoreKeys,
11+
ListsWithStoreKeys,
12+
} from './useList.storekey.stories';
13+
import { TestMemoryRouter } from '../../routing';
14+
15+
beforeEach(() => {
16+
// Clear localStorage or mock store to reset state
17+
localStorage.clear();
18+
});
19+
20+
describe('useList', () => {
21+
describe('storeKey', () => {
22+
it('should keep distinct two lists of the same resource given different keys', async () => {
23+
render(
24+
<TestMemoryRouter initialEntries={['/top']}>
25+
<ListsWithStoreKeys />
26+
</TestMemoryRouter>
27+
);
28+
29+
// Wait for the initial state of perPage to stabilize
30+
await waitFor(() => {
31+
const perPageValue = screen
32+
.getByLabelText('perPage')
33+
.getAttribute('data-value');
34+
expect(perPageValue).toEqual('3');
35+
});
36+
37+
act(() => {
38+
fireEvent.click(screen.getByLabelText('incrementPerPage'));
39+
});
40+
41+
await waitFor(() => {
42+
const perPageValue = screen
43+
.getByLabelText('perPage')
44+
.getAttribute('data-value');
45+
expect(perPageValue).toEqual('4');
46+
});
47+
48+
// Navigate to "flop" list
49+
act(() => {
50+
fireEvent.click(screen.getByLabelText('flop'));
51+
});
52+
53+
await waitFor(() => {
54+
const perPageValue = screen
55+
.getByLabelText('perPage')
56+
.getAttribute('data-value');
57+
expect(perPageValue).toEqual('3');
58+
});
59+
});
60+
61+
it('should not use the store when storeKey is false', async () => {
62+
render(
63+
<TestMemoryRouter initialEntries={['/store']}>
64+
<ListsWithoutStoreKeys />
65+
</TestMemoryRouter>
66+
);
67+
68+
await waitFor(() => {
69+
expect(
70+
screen.getByLabelText('perPage').getAttribute('data-value')
71+
).toEqual('3');
72+
});
73+
74+
act(() => {
75+
fireEvent.click(screen.getByLabelText('incrementPerPage'));
76+
fireEvent.click(screen.getByLabelText('incrementPerPage'));
77+
});
78+
79+
await waitFor(() => {
80+
expect(
81+
screen.getByLabelText('perPage').getAttribute('data-value')
82+
).toEqual('5');
83+
});
84+
85+
act(() => {
86+
fireEvent.click(screen.getByLabelText('nostore'));
87+
});
88+
89+
await waitFor(() => {
90+
const storeKey = screen
91+
.getByLabelText('nostore')
92+
.getAttribute('data-value');
93+
expect(storeKey).toEqual(null);
94+
});
95+
96+
expect(
97+
screen.getByLabelText('perPage').getAttribute('data-value')
98+
).toEqual('3');
99+
100+
act(() => {
101+
fireEvent.click(screen.getByLabelText('incrementPerPage'));
102+
});
103+
104+
await waitFor(() => {
105+
expect(
106+
screen.getByLabelText('perPage').getAttribute('data-value')
107+
).toEqual('4');
108+
});
109+
110+
act(() => {
111+
fireEvent.click(screen.getByLabelText('store'));
112+
});
113+
// Shouldn't have changed the store list
114+
await waitFor(() => {
115+
const perPageValue = screen
116+
.getByLabelText('perPage')
117+
.getAttribute('data-value');
118+
expect(perPageValue).toEqual('5');
119+
});
120+
121+
act(() => {
122+
fireEvent.click(screen.getByLabelText('nostore'));
123+
});
124+
// Should have reset its parameters to their default
125+
expect(
126+
screen.getByLabelText('perPage').getAttribute('data-value')
127+
).toEqual('3');
128+
});
129+
});
130+
});
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import * as React from 'react';
2+
import { Route } from 'react-router';
3+
import { Link } from 'react-router-dom';
4+
import fakeDataProvider from 'ra-data-fakerest';
5+
6+
import {
7+
CoreAdminContext,
8+
CoreAdminUI,
9+
CustomRoutes,
10+
Resource,
11+
} from '../../core';
12+
import { localStorageStore } from '../../store';
13+
import { FakeBrowserDecorator } from '../../storybook/FakeBrowser';
14+
import { CoreLayoutProps, SortPayload } from '../../types';
15+
import { useList } from './useList';
16+
17+
export default {
18+
title: 'ra-core/controller/list/useList',
19+
decorators: [FakeBrowserDecorator],
20+
parameters: {
21+
initialEntries: ['/top'],
22+
},
23+
};
24+
25+
const styles = {
26+
mainContainer: {
27+
margin: '20px 10px',
28+
},
29+
ul: {
30+
marginTop: '20px',
31+
padding: '10px',
32+
},
33+
};
34+
35+
const dataProvider = fakeDataProvider({
36+
posts: [
37+
{ id: 1, title: 'Post #1', votes: 90 },
38+
{ id: 2, title: 'Post #2', votes: 20 },
39+
{ id: 3, title: 'Post #3', votes: 30 },
40+
{ id: 4, title: 'Post #4', votes: 40 },
41+
{ id: 5, title: 'Post #5', votes: 50 },
42+
{ id: 6, title: 'Post #6', votes: 60 },
43+
{ id: 7, title: 'Post #7', votes: 70 },
44+
],
45+
});
46+
47+
const OrderedPostList = ({
48+
storeKey,
49+
sort,
50+
}: {
51+
storeKey: string | false;
52+
sort?: SortPayload;
53+
}) => {
54+
const params = useList({
55+
resource: 'posts',
56+
perPage: 3,
57+
sort,
58+
storeKey,
59+
});
60+
61+
return (
62+
<div>
63+
<span aria-label="storeKey" data-value={storeKey}>
64+
storeKey: {storeKey}
65+
</span>
66+
<br />
67+
<span aria-label="perPage" data-value={params.perPage}>
68+
perPage: {params.perPage}
69+
</span>
70+
<br />
71+
<button
72+
aria-label="incrementPerPage"
73+
onClick={() => {
74+
return params.setPerPage(++params.perPage);
75+
}}
76+
>
77+
Increment perPage
78+
</button>
79+
<ul style={styles.ul}>
80+
{params.data?.map(post => (
81+
<li key={post.id}>
82+
{post.title} - {post.votes} votes
83+
</li>
84+
))}
85+
</ul>
86+
</div>
87+
);
88+
};
89+
90+
const Layout = (props: CoreLayoutProps) => (
91+
<div style={styles.mainContainer}>
92+
<Link aria-label="top" to={`/top`}>
93+
Go to Top Posts
94+
</Link>
95+
<Link aria-label="flop" to={`/flop`}>
96+
Go to Flop Posts
97+
</Link>
98+
<Link aria-label="store" to={`/store`}>
99+
Go to Store List
100+
</Link>
101+
<Link aria-label="nostore" to={`/nostore`}>
102+
Go to No-Store List
103+
</Link>
104+
105+
<br />
106+
{props.children}
107+
</div>
108+
);
109+
110+
const TopPosts = (
111+
<OrderedPostList
112+
storeKey="topPostsKey"
113+
sort={{ field: 'votes', order: 'DESC' }}
114+
/>
115+
);
116+
const FlopPosts = (
117+
<OrderedPostList
118+
storeKey="flopPostsKey"
119+
sort={{ field: 'votes', order: 'ASC' }}
120+
/>
121+
);
122+
const StorePosts = (
123+
<OrderedPostList
124+
storeKey="storeListKey"
125+
sort={{ field: 'votes', order: 'ASC' }}
126+
/>
127+
);
128+
const NoStorePosts = (
129+
<OrderedPostList storeKey={false} sort={{ field: 'votes', order: 'ASC' }} />
130+
);
131+
132+
export const ListsWithStoreKeys = () => (
133+
<CoreAdminContext store={localStorageStore()} dataProvider={dataProvider}>
134+
<CoreAdminUI layout={Layout}>
135+
<CustomRoutes>
136+
<Route path="/top" element={TopPosts} />
137+
<Route path="/flop" element={FlopPosts} />
138+
</CustomRoutes>
139+
<Resource name="posts" />
140+
</CoreAdminUI>
141+
</CoreAdminContext>
142+
);
143+
144+
export const ListsWithoutStoreKeys = () => (
145+
<CoreAdminContext store={localStorageStore()} dataProvider={dataProvider}>
146+
<CoreAdminUI layout={Layout}>
147+
<CustomRoutes>
148+
<Route path="/store" element={StorePosts} />
149+
<Route path="/nostore" element={NoStorePosts} />
150+
</CustomRoutes>
151+
<Resource name="posts" />
152+
</CoreAdminUI>
153+
</CoreAdminContext>
154+
);

0 commit comments

Comments
 (0)