-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathApp.test.tsx
112 lines (89 loc) · 4.85 KB
/
App.test.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import * as React from 'react';
import { render, screen, userEvent } from '@testing-library/react-native';
import App from '../App';
jest.useFakeTimers();
/**
* A good place to start is having a tests that your component renders correctly.
*/
test('renders correctly', () => {
// Idiom: no need to capture render output, as we will use `screen` for queries.
render(<App />);
// Idiom: `getBy*` queries are predicates by themselves, but we will use it with `expect().toBeOnTheScreen()`
// to clarify our intent.
expect(screen.getByRole('header', { name: 'Sign in to Example App' })).toBeOnTheScreen();
});
/**
* Hint: It's best when your tests are similar to what a manual test scenarions would look like,
* i.e. a series of actions taken by the user, followed by a series of assertions verified from
* his point of view.
*/
test('User can sign in successully with correct credentials', async () => {
// Setup User Event instance for realistic simulation of user interaction.
const user = userEvent.setup();
// Idiom: no need to capture render output, as we will use `screen` for queries.
render(<App />);
// Idiom: `getBy*` queries are predicates by themselves, but we will use it with `expect().toBeOnTheScreen()`
// to clarify our intent.
expect(screen.getByRole('header', { name: 'Sign in to Example App' })).toBeOnTheScreen();
// Hint: we can use `getByLabelText` to find our text inputs using their labels.
await user.type(screen.getByLabelText('Username'), 'admin');
await user.type(screen.getByLabelText('Password'), 'admin1');
// Hint: we can use `getByRole` to find our button with given text.
await user.press(screen.getByRole('button', { name: 'Sign In' }));
// Idiom: since pressing button triggers async operation we need to use `findBy*` query to wait
// for the action to complete.
// Hint: subsequent queries do not need to use `findBy*`, because they are used after the async action
// already finished
expect(await screen.findByRole('header', { name: 'Welcome admin!' })).toBeOnTheScreen();
// Idiom: use `queryBy*` with `expect().not.toBeOnTheScreen()` to assess that element is not present.
expect(screen.queryByRole('header', { name: 'Sign in to Example App' })).not.toBeOnTheScreen();
expect(screen.queryByLabelText('Username')).not.toBeOnTheScreen();
expect(screen.queryByLabelText('Password')).not.toBeOnTheScreen();
});
/**
* Another test case based on manual test scenario.
*
* Hint: Try to tests what a user would see and do, instead of assering internal component state
* that is not directly reflected in the UI.
*
* For this reason prefer quries that correspond to things directly observable by the user like:
* `getByRole`, `getByText`, `getByLabelText`, `getByPlaceholderText, `getByDisplayValue`, etc.
* over `getByTestId` which is not directly observable by the user.
*
* Note: that some times you will have to resort to `getByTestId`, but treat it as a last resort.
*/
test('User will see errors for incorrect credentials', async () => {
const user = userEvent.setup();
render(<App />);
expect(screen.getByRole('header', { name: 'Sign in to Example App' })).toBeOnTheScreen();
await user.type(screen.getByLabelText('Username'), 'admin');
await user.type(screen.getByLabelText('Password'), 'qwerty123');
await user.press(screen.getByRole('button', { name: 'Sign In' }));
// Hint: you can use custom Jest Native matcher to check text content.
expect(await screen.findByRole('alert')).toHaveTextContent('Incorrect username or password');
expect(screen.getByRole('header', { name: 'Sign in to Example App' })).toBeOnTheScreen();
expect(screen.getByLabelText('Username')).toBeOnTheScreen();
expect(screen.getByLabelText('Password')).toBeOnTheScreen();
});
/**
* Do not be afraid to write longer test scenarios, with repeating act and assert statements.
*/
test('User can sign in after incorrect attempt', async () => {
const user = userEvent.setup();
render(<App />);
expect(screen.getByRole('header', { name: 'Sign in to Example App' })).toBeOnTheScreen();
const usernameInput = screen.getByLabelText('Username');
const passwordInput = screen.getByLabelText('Password');
await user.type(usernameInput, 'admin');
await user.type(passwordInput, 'qwerty123');
await user.press(screen.getByRole('button', { name: 'Sign In' }));
expect(await screen.findByRole('alert')).toHaveTextContent('Incorrect username or password');
// Clear password field
await user.clear(passwordInput);
await user.type(passwordInput, 'admin1');
await user.press(screen.getByRole('button', { name: 'Sign In' }));
expect(await screen.findByText('Welcome admin!')).toBeOnTheScreen();
expect(screen.queryByRole('header', { name: 'Sign in to Example App' })).not.toBeOnTheScreen();
expect(screen.queryByLabelText('Username')).not.toBeOnTheScreen();
expect(screen.queryByLabelText('Password')).not.toBeOnTheScreen();
});