-
Notifications
You must be signed in to change notification settings - Fork 0
/
IntegrationTests.jsx
197 lines (160 loc) · 7.7 KB
/
IntegrationTests.jsx
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
// With React Testing Library
/* As the developer for Little Lemon Restaurant application, how could you guarantee that the
app you created works as intended? Well, That's where automation tests come in. .
A well-designed suite of automation tests is particularly effective in allowing you to discover
defects or bugs before delivery to the client. In doing so, testing is important for guaranteeing
the quality of the software you develop. Further, by catching bugs before they find their way into
a live application, testing reduces the number of user complaints, and can ultimately save an
organization time and money. Now that you have an idea of why testing is important,
// what are the best practices when writing your tests? T
he first is that your tests need to avoid including implementation details of your components.
React is just a tool, and your final users will have no notion that React exists at all. Rather
than dealing with instances of rendered React components, your tests should work with actual DOM
nodes. Secondly, the more you test resemble the way your software is used, the more confidence they
can give you. Finally, you also want your tests to be maintainable in the long term. As long as you're
not changing functionality, any changes in the implementation of the component won't break your tests and
slow you and your team down. Now
// Testing React components with Jest and React Testing Library
/* Automation tests are crucial for ensuring software quality and catching bugs early. Jest,
a JavaScript test runner, provides an artificial DOM (JSDOM) and features like module mocking
for standalone unit testing. React Testing Library offers utilities to test components without
their implementation details, aligning with best practices.
When using Create React App, Jest and React Testing Library come pre-installed and pre-configured,
with an example test file (app.test.js) included. To test, import render and screen from React Testing
Library, use render to display the component, and screen to query the DOM. Jest's global test function
structures the test scenario. Use getByText to find elements by text, and expect to assert visibility.
An example test checks for the presence of a link with the text "Little Lemon Restaurant" in the app.
If the text is incorrect, the test fails, highlighting the error.
*/
function App() { // This is the component we want to test.
return (
<div className="app">
<a href="https:littlelemon.com">Little Orange Restaurant
</a>
</div>
)
}
// Below is the code in App.test.js that tests the component.
import {render, screen} from '@testing-library/react'
import App from './App'
test("renders a screen that points to little lemon's webpage", () => {
render(<App />)
const linkElement = screen.getByText("Little Lemon Restaurant")
expect(linkElement).toBeInTheDocument()
})
/*
Once corrected, the test passes,
confirming the app's functionality. This demonstrates the ease of writing tests that reflect real user
interactions and expected behaviors.
In summary, Jest and React Testing Library simplify React component testing, ensuring reliable and maintainable tests. */
/*
The Little Lemon Restaurant needed to ensure customers left detailed feedback when giving low scores.
They updated their feedback form to require a comment when the score is below five. To safeguard this
new feature, they implemented automated tests. These tests check that the form behaves as expected and
prevents submission without a comment for low scores. The tests use mock functions and React Testing
Library utilities to simulate user interaction and validate the form's functionality. With these tests,
the restaurant can confidently make changes to their app, knowing that any issues will be caught early.
This helps the restaurant improve based on customer feedback, such as adding more cheese to their pizzas.
*/
// This is the code in App.js
function FeedbackApp() {
const [score, setScore] = useState("10")
const [comment, setComment] = useState("")
const handleSubmit = (e) => {
e.preventDefault()
if(Number(score) <= 5 && comment.length <= 10) {
alert("Please provide a comment on why the experience was poor.");
return;
}
console.log("Form Submitted")
setComment("")
setScore("10");
}
return (
<div className="App">
<form onSubmit={handleSubmit}>
<fieldset>
<h2>Feedback Form</h2>
<div className='Field'>
<label
htmlFor="Feedback">
Score: {score} ⭐
</label>
<input
id="Feedback"
type="range"
min="0"
valeue={score}
max="10"
onChange={e => setScore(e.target.value)} />
</div>
<div className="Field">
<label
htmlFor="Comment">
Comment:
</label>
<textarea
name="comment"
id="Comment"
cols="30"
rows="5"
value={comment}
onChange={e => setComment(e.target.value)} />
</div>
</fieldset>
</form>
</div>
)
}
// This is code inside app.test.js
// Jest's describe function is used to group together related tests
describe("FeedbackApp", () => {
// Jest's test function defines an individual test case
test("prevents form submission if score is < 5 and comment is too short", () => {
const handleSubmit = jest.fn() // Mock function to simulate form submission
render(<FeedbackApp onSubmit={handleSubmit} />) // Renders the FeedbackApp component
// Simulate user input for score and comment
fireEvent.change(screen.getByLabelText(/score/i), {target: {value: '3'}})
fireEvent.change(screen.getByPlaceholderText("Additional feedback"), {target: {value: ''}})
// Simulate form submission
fireEvent.click(screen.getByRole('button', {name: /submit/i}))
// Assert that handleSubmit has not been called because of the validation logic
expect(handleSubmit).not.toHaveBeenCalled()
// Assert that the submit button is indeed disabled
expect(screen.getByRole('button', {name: /submit/i})).toHaveAttribute('disabled')
})
})
// Solutin of exercise: Writing more test scenarios
import { fireEvent, render, screen } from "@testing-library/react";
import FeedbackForm from "./FeedbackForm";
describe("Feedback Form", () => {
test("User is able to submit the form if the score is lower than 5 and additional feedback is provided", () => {
const score = "3";
const comment = "The pizza crust was too thick";
const handleSubmit = jest.fn();
render(<FeedbackForm onSubmit={handleSubmit} />);
const rangeInput = screen.getByLabelText(/Score:/);
fireEvent.change(rangeInput, { target: { value: score } });
const textArea = screen.getByLabelText(/Comments:/);
fireEvent.change(textArea, { target: { value: comment } });
const submitButton = screen.getByRole("button");
fireEvent.click(submitButton);
expect(handleSubmit).toHaveBeenCalledWith({
score,
comment,
});
});
test("User is able to submit the form if the score is higher than 5, without additional feedback", () => {
const score = "9";
const handleSubmit = jest.fn();
render(<FeedbackForm onSubmit={handleSubmit} />);
const rangeInput = screen.getByLabelText(/Score:/);
fireEvent.change(rangeInput, { target: { value: score } });
const submitButton = screen.getByRole("button");
fireEvent.click(submitButton);
expect(handleSubmit).toHaveBeenCalledWith({
score,
comment: ""
});
});
});