Skip to content

Commit 1240881

Browse files
Refactor router store tests (#191)
1 parent 14aca40 commit 1240881

File tree

2 files changed

+470
-883
lines changed

2 files changed

+470
-883
lines changed

src/__tests__/integration.test.tsx

Lines changed: 167 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import { mount } from 'enzyme';
22
import { createMemoryHistory } from 'history';
3-
import React from 'react';
3+
import React, { Fragment } from 'react';
44
import { defaultRegistry } from 'react-sweet-state';
55

66
import { isServerEnvironment } from '../common/utils/is-server-environment';
77
import { createResource, ResourceStore } from '../controllers/resource-store';
88
import {
9+
Route,
910
RouteComponent,
1011
Router,
11-
RouterActions,
12-
RouterActionsType,
12+
RouteResource,
1313
StaticRouter,
14+
useResource,
1415
} from '../index';
1516

1617
jest.mock('../common/utils/is-server-environment');
@@ -22,55 +23,7 @@ describe('<Router /> client-side integration tests', () => {
2223

2324
afterEach(() => {
2425
defaultRegistry.stores.clear();
25-
});
26-
27-
describe('sends the expected path to history', () => {
28-
function renderRouter(basePath?: string) {
29-
const history = createMemoryHistory();
30-
const push = jest.spyOn(history, 'push');
31-
const replace = jest.spyOn(history, 'replace');
32-
33-
let routerActions = {} as RouterActionsType;
34-
mount(
35-
<Router basePath={basePath} history={history} routes={[]}>
36-
<RouterActions>
37-
{actions => {
38-
routerActions = actions;
39-
40-
return null;
41-
}}
42-
</RouterActions>
43-
</Router>
44-
);
45-
46-
return {
47-
history: {
48-
push,
49-
replace,
50-
},
51-
routerActions,
52-
};
53-
}
54-
55-
it('when basePath is set', async () => {
56-
const { history, routerActions } = renderRouter('/basepath');
57-
58-
routerActions.push('/push');
59-
expect(history.push).toHaveBeenCalledWith('/basepath/push');
60-
61-
routerActions.replace('/replace');
62-
expect(history.replace).toHaveBeenCalledWith('/basepath/replace');
63-
});
64-
65-
it('when basePath is not set', async () => {
66-
const { history, routerActions } = renderRouter();
67-
68-
routerActions.push('/push');
69-
expect(history.push).toBeCalledWith('/push');
70-
71-
routerActions.replace('/replace');
72-
expect(history.replace).toBeCalledWith('/replace');
73-
});
26+
jest.useRealTimers();
7427
});
7528

7629
it('re-triggers requests for timed out resources when mounted', async () => {
@@ -94,7 +47,7 @@ describe('<Router /> client-side integration tests', () => {
9447
const getTimeoutData = jest.spyOn(timeoutResource, 'getData');
9548

9649
const route = {
97-
component: () => <div>foo</div>,
50+
component: () => <div>test</div>,
9851
name: 'mock-route',
9952
path: location.substring(0, location.indexOf('?')),
10053
resources: [completedResource, timeoutResource],
@@ -110,6 +63,17 @@ describe('<Router /> client-side integration tests', () => {
11063
expect(getTimeoutData).toHaveBeenCalledTimes(1);
11164

11265
expect(serverData).toEqual({
66+
COMPLETED: {
67+
key: {
68+
data: 'completed',
69+
error: null,
70+
expiresAt: null,
71+
key: undefined,
72+
loading: false,
73+
promise: null,
74+
accessedAt: null,
75+
},
76+
},
11377
TIMEOUT: {
11478
key: {
11579
data: null,
@@ -125,17 +89,6 @@ describe('<Router /> client-side integration tests', () => {
12589
accessedAt: null,
12690
},
12791
},
128-
COMPLETED: {
129-
key: {
130-
data: 'completed',
131-
error: null,
132-
expiresAt: null,
133-
key: undefined,
134-
loading: false,
135-
promise: null,
136-
accessedAt: null,
137-
},
138-
},
13992
});
14093

14194
defaultRegistry.stores.clear();
@@ -165,9 +118,9 @@ describe('<Router /> client-side integration tests', () => {
165118
expect(resourceStore.storeState.getState()).toEqual({
166119
context: {},
167120
data: {
168-
TIMEOUT: {
121+
COMPLETED: {
169122
key: {
170-
data: 'timeout',
123+
data: 'completed',
171124
error: null,
172125
expiresAt: expect.any(Number),
173126
key: undefined,
@@ -176,9 +129,9 @@ describe('<Router /> client-side integration tests', () => {
176129
accessedAt: expect.any(Number),
177130
},
178131
},
179-
COMPLETED: {
132+
TIMEOUT: {
180133
key: {
181-
data: 'completed',
134+
data: 'timeout',
182135
error: null,
183136
expiresAt: expect.any(Number),
184137
key: undefined,
@@ -192,6 +145,148 @@ describe('<Router /> client-side integration tests', () => {
192145
prefetching: null,
193146
});
194147
});
148+
149+
describe('renders the next route with', () => {
150+
function renderRouter(routes: Route[]) {
151+
const history = createMemoryHistory({ initialEntries: [routes[0].path] });
152+
const push: any = jest.spyOn(history, 'push');
153+
const waitForData = () => new Promise(resolve => setTimeout(resolve));
154+
155+
const router = mount(
156+
<Router history={history} isGlobal routes={routes}>
157+
<RouteComponent />
158+
</Router>
159+
);
160+
161+
return {
162+
history: {
163+
push,
164+
},
165+
router,
166+
waitForData,
167+
};
168+
}
169+
170+
function createResources() {
171+
let cached = 0;
172+
let network = 0;
173+
174+
return {
175+
cacheResource: createResource({
176+
getData: () => {
177+
cached += 1;
178+
179+
return Promise.resolve(`cache-${cached}`);
180+
},
181+
getKey: () => 'cache',
182+
maxAge: Infinity,
183+
type: 'CACHE',
184+
}),
185+
networkResource: createResource({
186+
getData: () => {
187+
network += 1;
188+
189+
return Promise.resolve(`network-${network}`);
190+
},
191+
getKey: () => 'network',
192+
maxAge: 0,
193+
type: 'NETWORK',
194+
}),
195+
};
196+
}
197+
198+
function createResourceComponent(resource: RouteResource<string>) {
199+
return () => {
200+
const { data, error, loading } = useResource(resource);
201+
if (error) {
202+
return <>error:{error}</>;
203+
}
204+
205+
if (loading) {
206+
return <>loading:{resource.type.toLowerCase()}</>;
207+
}
208+
209+
return <>data:{data?.toString()}</>;
210+
};
211+
}
212+
213+
function createComponent(resources: RouteResource<string>[]) {
214+
const components = resources.map(createResourceComponent);
215+
216+
return () => {
217+
return (
218+
<>
219+
{components.map((Component, index) => (
220+
<Fragment key={index}>
221+
<Component />
222+
{index < components.length - 1 ? ' ' : ''}
223+
</Fragment>
224+
))}
225+
</>
226+
);
227+
};
228+
}
229+
230+
it('previous data when transitioning to the same route and resource keys', async () => {
231+
const { cacheResource, networkResource } = createResources();
232+
const route = {
233+
component: createComponent([cacheResource, networkResource]),
234+
name: 'page-1',
235+
path: '/pages/1',
236+
resources: [cacheResource, networkResource],
237+
};
238+
239+
const { history, router, waitForData } = renderRouter([route]);
240+
241+
expect(router.html()).toBe('loading:cache loading:network');
242+
await waitForData();
243+
router.update();
244+
expect(router.html()).toBe('data:cache-1 data:network-1');
245+
246+
history.push(route.path + '?query#hash');
247+
router.update();
248+
249+
expect(router.html()).toBe('data:cache-1 data:network-1');
250+
await waitForData();
251+
router.update();
252+
expect(router.html()).toBe('data:cache-1 data:network-1');
253+
});
254+
255+
it('fresh data when transitioning to a new route', async () => {
256+
const { cacheResource, networkResource } = createResources();
257+
const component = createComponent([cacheResource, networkResource]);
258+
259+
const routes = [
260+
{
261+
component,
262+
name: 'page-1',
263+
path: '/pages/1',
264+
resources: [cacheResource, networkResource],
265+
},
266+
{
267+
component,
268+
name: 'page-2',
269+
path: '/pages/2',
270+
resources: [cacheResource, networkResource],
271+
},
272+
];
273+
274+
const { history, router, waitForData } = renderRouter(routes);
275+
276+
expect(router.html()).toBe('loading:cache loading:network');
277+
await waitForData();
278+
router.update();
279+
expect(router.html()).toBe('data:cache-1 data:network-1');
280+
281+
history.push(routes[1].path);
282+
router.update();
283+
284+
expect(router.html()).toBe('data:cache-1 loading:network');
285+
await waitForData();
286+
router.update();
287+
expect(router.html()).toBe('data:cache-1 data:network-2');
288+
});
289+
});
195290
});
196291

197292
describe('<StaticRouter /> server-side integration tests', () => {
@@ -205,11 +300,11 @@ describe('<StaticRouter /> server-side integration tests', () => {
205300
(isServerEnvironment as any).mockReturnValue(true);
206301
});
207302

208-
it('should match the right route when basePath is set', async () => {
303+
it('renders the expected route when basePath is set', async () => {
209304
const wrapper = mount(
210305
<StaticRouter
211-
basePath="/basepath"
212-
location={`/basepath${route.path}`}
306+
basePath="/base-path"
307+
location={`/base-path${route.path}`}
213308
routes={[route]}
214309
>
215310
<RouteComponent />
@@ -219,7 +314,7 @@ describe('<StaticRouter /> server-side integration tests', () => {
219314
expect(wrapper.text()).toBe('route component');
220315
});
221316

222-
it('should match the right route when basePath is not set', async () => {
317+
it('renders the expected route when basePath is not set', async () => {
223318
const wrapper = mount(
224319
<StaticRouter location={route.path} routes={[route]}>
225320
<RouteComponent />

0 commit comments

Comments
 (0)