Skip to content

Commit 2bb0400

Browse files
authored
#48 Upgrade MSW (#56)
* #48 upgrade msw * #48 upgrade deps * #48 upgrade deps * #48 test wrappers
1 parent e8518b2 commit 2bb0400

File tree

8 files changed

+602
-1147
lines changed

8 files changed

+602
-1147
lines changed

package-lock.json

Lines changed: 500 additions & 1106 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,51 +22,51 @@
2222
"test:ci": "vitest run --coverage --silent"
2323
},
2424
"dependencies": {
25-
"@codesandbox/sandpack-react": "2.13.5",
25+
"@codesandbox/sandpack-react": "2.14.0",
2626
"@leanstacks/react-common": "1.0.0",
2727
"@react-spring/web": "9.7.3",
28-
"@tanstack/react-query": "5.24.1",
29-
"@tanstack/react-query-devtools": "5.24.1",
30-
"@tanstack/react-table": "8.14.0",
31-
"axios": "1.6.7",
28+
"@tanstack/react-query": "5.40.1",
29+
"@tanstack/react-query-devtools": "5.40.1",
30+
"@tanstack/react-table": "8.17.3",
31+
"axios": "1.7.2",
3232
"classnames": "2.5.1",
33-
"dayjs": "1.11.10",
34-
"formik": "2.4.5",
33+
"dayjs": "1.11.11",
34+
"formik": "2.4.6",
3535
"i18next": "23.11.5",
3636
"i18next-browser-languagedetector": "8.0.0",
3737
"lodash": "4.17.21",
38-
"qs": "6.11.2",
38+
"qs": "6.12.1",
3939
"react": "18.3.1",
4040
"react-dom": "18.3.1",
4141
"react-i18next": "14.1.2",
42-
"react-router-dom": "6.22.1",
43-
"tailwindcss": "3.4.1",
42+
"react-router-dom": "6.23.1",
43+
"tailwindcss": "3.4.3",
4444
"uuid": "9.0.1",
45-
"yup": "1.3.3"
45+
"yup": "1.4.0"
4646
},
4747
"devDependencies": {
48-
"@testing-library/react": "15.0.7",
48+
"@testing-library/react": "16.0.0",
4949
"@testing-library/user-event": "14.5.2",
50-
"@types/lodash": "4.14.202",
51-
"@types/qs": "6.9.11",
52-
"@types/react": "18.3.2",
50+
"@types/lodash": "4.17.4",
51+
"@types/qs": "6.9.15",
52+
"@types/react": "18.3.3",
5353
"@types/react-dom": "18.3.0",
5454
"@types/uuid": "9.0.8",
55-
"@typescript-eslint/eslint-plugin": "7.9.0",
56-
"@typescript-eslint/parser": "7.9.0",
57-
"@vitejs/plugin-react": "4.2.1",
55+
"@typescript-eslint/eslint-plugin": "7.12.0",
56+
"@typescript-eslint/parser": "7.12.0",
57+
"@vitejs/plugin-react": "4.3.0",
5858
"@vitest/coverage-v8": "1.6.0",
5959
"autoprefixer": "10.4.19",
6060
"eslint": "8.57.0",
6161
"eslint-plugin-react-hooks": "4.6.2",
6262
"eslint-plugin-react-refresh": "0.4.7",
63-
"jsdom": "24.0.0",
64-
"msw": "1.3.2",
63+
"jsdom": "24.1.0",
64+
"msw": "2.3.1",
6565
"postcss": "8.4.38",
66-
"prettier": "3.2.5",
67-
"prettier-plugin-tailwindcss": "0.5.11",
68-
"typescript": "5.2.2",
69-
"vite": "5.2.11",
66+
"prettier": "3.3.0",
67+
"prettier-plugin-tailwindcss": "0.6.1",
68+
"typescript": "5.4.5",
69+
"vite": "5.2.12",
7070
"vitest": "1.6.0"
7171
}
7272
}

src/api/__tests__/useGetUserTokens.test.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
22
import dayjs from 'dayjs';
33

44
import { renderHook, waitFor } from 'test/test-utils';
5+
import WithQueryClientProvider from 'test/wrappers/WithQueryClientProvider';
56
import storage from 'utils/storage';
67
import { userTokensFixture } from '__fixtures__/tokens';
78

@@ -37,8 +38,9 @@ describe('useGetTokens', () => {
3738
expires_at: dayjs('2024-01-01').toISOString(),
3839
};
3940
getItemSpy.mockReturnValue(JSON.stringify(token));
40-
const { result } = renderHook(() => useGetUserTokens());
41-
await waitFor(() => expect(result.current.error).toBeDefined());
41+
// use a specific wrapper to avoid test side effects from "AuthProvider"
42+
const { result } = renderHook(() => useGetUserTokens(), { wrapper: WithQueryClientProvider });
43+
await waitFor(() => expect(result.current.isError).toBe(true));
4244

4345
// ASSERT
4446
expect(result.current.error).toBeInstanceOf(Error);
@@ -47,8 +49,9 @@ describe('useGetTokens', () => {
4749
it('should error if token is not found', async () => {
4850
// ARRANGE
4951
getItemSpy.mockReturnValue(null);
50-
const { result } = renderHook(() => useGetUserTokens());
51-
await waitFor(() => expect(result.current.error).toBeDefined());
52+
// use a specific wrapper to avoid test side effects from "AuthProvider"
53+
const { result } = renderHook(() => useGetUserTokens(), { wrapper: WithQueryClientProvider });
54+
await waitFor(() => expect(result.current.isError).toBe(true));
5255

5356
// ASSERT
5457
expect(result.current.error).toBeInstanceOf(Error);

src/test/mocks/handlers.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
1-
import { rest } from 'msw';
1+
import { HttpResponse, http } from 'msw';
22
import filter from 'lodash/filter';
33
import find from 'lodash/find';
44

55
import { usersFixture } from '__fixtures__/users';
66
import { todosFixture } from '__fixtures__/todos';
77

88
export const handlers = [
9-
rest.get('https://jsonplaceholder.typicode.com/users', (_req, res, ctx) => {
10-
return res(ctx.json(usersFixture));
9+
http.get('https://jsonplaceholder.typicode.com/users', () => {
10+
return HttpResponse.json(usersFixture);
1111
}),
12-
rest.get('https://jsonplaceholder.typicode.com/users/:userId', (req, res, ctx) => {
13-
const { userId } = req.params;
12+
http.get('https://jsonplaceholder.typicode.com/users/:userId', ({ params }) => {
13+
const { userId } = params;
1414
const user = find(usersFixture, { id: Number(userId) });
1515
if (user) {
16-
return res(ctx.json(user));
16+
return HttpResponse.json(user);
1717
}
18-
return res(ctx.status(404));
18+
return new HttpResponse(null, { status: 404 });
1919
}),
20-
rest.get('https://jsonplaceholder.typicode.com/users/:userId/todos', (req, res, ctx) => {
21-
const { userId } = req.params;
20+
http.get('https://jsonplaceholder.typicode.com/users/:userId/todos', ({ params }) => {
21+
const { userId } = params;
2222
const todos = filter(todosFixture, { userId: Number(userId) });
23-
return res(ctx.json(todos));
23+
return HttpResponse.json(todos);
2424
}),
2525
];

src/test/test-utils.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
} from '@testing-library/react';
99

1010
import 'utils/i18n';
11-
import WithAllProviders from './WithAllProviders';
11+
import WithAllProviders from './wrappers/WithAllProviders';
1212

1313
const customRender = (ui: React.ReactElement, options?: RenderOptions, { route = '/' } = {}) => {
1414
window.history.pushState({}, 'Test page', route);

src/test/AllProvidersExceptRouter.tsx renamed to src/test/wrappers/AllProvidersExceptRouter.tsx

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,33 @@ import SettingsContextProvider from 'providers/SettingsProvider';
66
import AuthContextProvider from 'providers/AuthProvider';
77
import ToastsProvider from 'providers/ToastsProvider';
88

9-
import { queryClient } from './query-client';
9+
import { queryClient } from '../query-client';
1010

11+
/**
12+
* A React test wrapper. Wraps the component under test with a bespoke set
13+
* of React components, typically providers.
14+
*
15+
* This test wrapper includes all of the providers except the Router.
16+
*
17+
* This component is useful when you want to render your own router component
18+
* as part of the test. For example, to test that some specific navigation is
19+
* triggered.
20+
*
21+
* Example:
22+
* ```
23+
* render(
24+
* <MemoryRouter>
25+
* <Routes>
26+
* <Route path="/" element={<MyForm />} />
27+
* <Route path="/route/under/test" element={<div data-testid="test-navigation" />} />
28+
* </Routes>
29+
* </MemoryRouter>,
30+
* { wrapper: AllProvidersExceptRouter },
31+
* );
32+
* ```
33+
* @param {PropsWithChildren} props - Component properties.
34+
* @returns {JSX.Element} JSX
35+
*/
1136
const AllProvidersExceptRouter = ({ children }: PropsWithChildren): JSX.Element => {
1237
return (
1338
<ConfigContextProvider>

src/test/WithAllProviders.tsx renamed to src/test/wrappers/WithAllProviders.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,16 @@ import SettingsContextProvider from 'providers/SettingsProvider';
77
import AuthContextProvider from 'providers/AuthProvider';
88
import ToastsProvider from 'providers/ToastsProvider';
99

10-
import { queryClient } from './query-client';
10+
import { queryClient } from '../query-client';
1111

12+
/**
13+
* The default React test wrapper. Wraps the component under test with a set
14+
* of React components, typically providers.
15+
*
16+
* This test wrapper includes all of the providers used in the application.
17+
* @param {PropsWithChildren} props - Component properties.
18+
* @returns {JSX.Element} JSX
19+
*/
1220
const WithAllProviders = ({ children }: PropsWithChildren): JSX.Element => {
1321
return (
1422
<ConfigContextProvider>
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { PropsWithChildren } from 'react';
2+
import { MemoryRouter } from 'react-router-dom';
3+
import { QueryClientProvider } from '@tanstack/react-query';
4+
5+
import { queryClient } from '../query-client';
6+
7+
/**
8+
* A React test wrapper. Wraps the component under test with a bespoke set
9+
* of React components, typically providers.
10+
*
11+
* Wraps the component with the React Query `QueryClientProvider` and a router,
12+
* but nothing more. Removes other providers to minimize side effects on the
13+
* component under test.
14+
* @param {PropsWithChildren} props - Component properties.
15+
* @returns {JSX.Element} JSX
16+
*/
17+
const WithQueryClientProvider = ({ children }: PropsWithChildren): JSX.Element => {
18+
return (
19+
<QueryClientProvider client={queryClient}>
20+
<MemoryRouter>{children}</MemoryRouter>
21+
</QueryClientProvider>
22+
);
23+
};
24+
25+
export default WithQueryClientProvider;

0 commit comments

Comments
 (0)