Skip to content

Commit 3e360e7

Browse files
committed
Added unit tests examples
1 parent 8ec2cb8 commit 3e360e7

File tree

21 files changed

+252
-27
lines changed

21 files changed

+252
-27
lines changed

.vscode/launch.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"type": "node",
9+
"name": "vscode-jest-tests",
10+
"request": "launch",
11+
"args": ["test", "--runInBand"],
12+
"cwd": "${workspaceFolder}",
13+
"console": "integratedTerminal",
14+
"internalConsoleOptions": "neverOpen",
15+
"disableOptimisticBPs": true,
16+
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/react-scripts",
17+
"protocol": "inspector"
18+
},
19+
{
20+
"type": "node",
21+
"name": "Jest Current File",
22+
"request": "launch",
23+
"args": ["test", "${fileBasenameNoExtension}", "--runInBand"],
24+
"console": "integratedTerminal",
25+
"internalConsoleOptions": "neverOpen",
26+
"disableOptimisticBPs": true,
27+
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/react-scripts",
28+
"protocol": "inspector"
29+
}
30+
]
31+
}

src/apollo/cache.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { InMemoryCache } from "@apollo/client";
2+
3+
export const cache = new InMemoryCache();

src/apollo/client.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
1+
import { ApolloClient, HttpLink } from "@apollo/client";
2+
import { cache } from "./cache";
23

3-
const client = new ApolloClient({
4-
cache: new InMemoryCache(),
4+
export const client = new ApolloClient({
5+
cache,
56
link: new HttpLink({
6-
uri: 'http://localhost:4000',
7-
})
7+
uri: "http://localhost:4000",
8+
}),
89
});
9-
10-
export default client;

src/apollo/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from "./cache";
2+
export * from "./client";

src/components/TodoItem/TodoItem.spec.tsx

Whitespace-only changes.

src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { ApolloProvider } from '@apollo/client';
44
import './index.css';
55
import App from './App';
66
import * as serviceWorker from './serviceWorker';
7-
import client from './apollo/client';
7+
import { client } from './apollo/client';
88
import { Todos } from './pages';
99
import { AbilityContext } from './rules/Can'
1010
import ability from './rules/abilityBuilder'

src/pages/Todos/Todos.spec.tsx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,57 @@
11
import React from 'react';
2-
import { render } from '@testing-library/react';
2+
import { render } from '../../test-utils';
33
import { generateImage } from 'jsdom-screenshot';
44
import { axe } from '../../test-utils';
55
import { Todos } from './Todos';
6+
import { GET_TODOS, UPDATE_TODO } from './queries';
7+
import { todos } from './mocks';
8+
import { act, fireEvent, waitFor } from '@testing-library/react';
69

710
describe('Todos components', () => {
11+
const mocks = [{
12+
request: {
13+
query: GET_TODOS
14+
},
15+
result: {
16+
data: { todos }
17+
}
18+
}];
19+
820
it('should render snapshot', async () => {
9-
const { container } = render(<Todos />);
21+
const { container } = await render(<Todos />, { mocks });
1022
expect(container).toMatchSnapshot();
1123
});
1224

1325
it('should render visual snapshot', async () => {
14-
render(<Todos />);
26+
await render(<Todos />, { mocks });
1527

1628
const screenshot = await generateImage();
1729
expect(screenshot).toMatchImageSnapshot();
1830
});
1931

2032
it('should validate accessibility voilations', async () => {
21-
const { container } = render(<Todos />);
33+
const { container } = await render(<Todos />, { mocks });
2234
expect(await axe(container)).toHaveNoViolations();
2335
});
36+
37+
it('should update todo on toggle task selection', async () => {
38+
const mutationMock = [{
39+
request: {
40+
query: UPDATE_TODO,
41+
variables: { id: '1', completed: true }
42+
},
43+
result: jest.fn(() => ({
44+
data: {
45+
updateTodo: {
46+
...todos[0],
47+
completed: true
48+
}
49+
}
50+
}))
51+
}];
52+
const { getByLabelText } = await render(<Todos />, { mocks: mutationMock });
53+
fireEvent.click(getByLabelText(todos[0].title));
54+
const updateMutationMock = mutationMock[0].result;
55+
await waitFor(() => expect(updateMutationMock).toHaveBeenCalledWith());
56+
});
2457
});

src/pages/Todos/Todos.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,24 @@ export const Todos = () => {
1212
if (loading) return <p>Loading...</p>;
1313
if (error) return <p>Error :(</p>;
1414

15+
/**
16+
* Toggle Todo item.
17+
* @param todo todo item
18+
*/
19+
const onToggleTaskItem = ({ id, completed }): void => {
20+
updateTodo({ variables: { id, completed } });
21+
}
22+
1523
return (
1624
<form className="Todo">
17-
{
18-
data.todos.map((todo: ToDo) => {
19-
return (
20-
<div className="Todo__list">
21-
<TodoItem todo={todo} onChange={({ id, completed }) => updateTodo({ variables: { id, completed } })} />
22-
</div>
23-
);
24-
})
25-
}
25+
<div className="Todo__list">
26+
{
27+
data.todos.map((todo: ToDo) => {
28+
return (
29+
<TodoItem key={`item-${todo.id}`} todo={todo} onChange={onToggleTaskItem} />
30+
);
31+
})
32+
}
33+
</div>
2634
</form>);
2735
}
20.5 KB
Loading
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Todos components should render snapshot 1`] = `
4+
<div>
5+
<form
6+
class="Todo"
7+
>
8+
<div
9+
class="Todo__list"
10+
>
11+
<div
12+
class="Todo__item"
13+
>
14+
<label
15+
for="1-checkbox"
16+
>
17+
delectus aut autem
18+
</label>
19+
<input
20+
id="1-checkbox"
21+
type="checkbox"
22+
/>
23+
</div>
24+
<div
25+
class="Todo__item"
26+
>
27+
<label
28+
for="2-checkbox"
29+
>
30+
quis ut nam facilis et officia qui
31+
</label>
32+
<input
33+
id="2-checkbox"
34+
type="checkbox"
35+
/>
36+
</div>
37+
<div
38+
class="Todo__item"
39+
>
40+
<label
41+
for="3-checkbox"
42+
>
43+
fugiat veniam minus
44+
</label>
45+
<input
46+
id="3-checkbox"
47+
type="checkbox"
48+
/>
49+
</div>
50+
<div
51+
class="Todo__item"
52+
>
53+
<label
54+
for="4-checkbox"
55+
>
56+
et porro tempora
57+
</label>
58+
<input
59+
checked=""
60+
id="4-checkbox"
61+
type="checkbox"
62+
/>
63+
</div>
64+
<div
65+
class="Todo__item"
66+
>
67+
<label
68+
for="5-checkbox"
69+
>
70+
laboriosam mollitia et enim quasi adipisci quia provident illum
71+
</label>
72+
<input
73+
id="5-checkbox"
74+
type="checkbox"
75+
/>
76+
</div>
77+
</div>
78+
</form>
79+
</div>
80+
`;

0 commit comments

Comments
 (0)