You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: exercises/03.best-practices/03.problem.network-mocking/README.mdx
+12-12Lines changed: 12 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,28 +1,28 @@
1
1
# Network mocking
2
2
3
-
We've got quite far testing the `<DiscountCodeForm />` component but there's just one problem. The component has been a bit naive. It simply took the entered discount code and put it in internal state. That's not how things work in real life. In practice, it would likely send that code to some server to validate and apply. It would make a _network call_.
3
+
So far, our `<DiscountCodeForm />` component has been handling discount codes in a simplified way — just storing them in internal state. In a real application, the component would need to validate and apply these codes through a server, making a _network call_.
4
4
5
-
In fact, I went and refactored the discount code component to do just that! Now, submitting the form dispatches a `POST https://api.example.com/discount/code` request with the provided code. Only once the server sends back the confirmation will the component display the applied discount in the UI.
5
+
In fact, I went and refactored the discount code component to do just that! Now, submitting the form dispatches a `POST https://api.example.com/discount/code` request with the provided code. Only when the server sends back the confirmation will the component display the applied discount in the UI.
6
6
7
7
This poses a new challenge: that `POST` request _will actually happen during the test run_. That may be acceptable in end-to-end testing but never on the integration level.
8
8
9
9
<callout-success>Always mock HTTP requests in integration tests.</callout-success>
10
10
11
-
Leaving that request to fire during tests means that we are allowing the server's operability and behavior to influence the outcome of the test. This is a no-go as it violates :scroll:[The Golden Rule of Assertions](https://www.epicweb.dev/the-golden-rule-of-assertions):
11
+
Leaving that request to fire during tests means that we are allowing the server's operability and behavior to influence the outcome of the test. This is a problem, as it violates :scroll:[The Golden Rule of Assertions](https://www.epicweb.dev/the-golden-rule-of-assertions):
12
12
13
13
<callout-info>_A test must fail if, and only if, the intention behind the system is not met._</callout-info>
14
14
15
-
In other words, our component can be functioning perfectly but the test may still fail if the server is down or having trouble processing the request. The responsibility of the integration test is to assert the client-side code we've written, and never the server-side one.
15
+
In other words, even if our component works perfectly, the test could fail due to server issues. Integration tests should focus solely on client-side behavior, not server responses.
16
16
17
-
You have to draw the line. You have to draw a :scroll:[Test boundary](https://www.epicweb.dev/what-is-a-test-boundary).
17
+
You have to draw a line between these responsibilities. You have to draw a :scroll:[Test boundary](https://www.epicweb.dev/what-is-a-test-boundary).
18
18
19
-
When it comes to the network, you employ API mocking tools to establish that boundary and help your tests focus on the right thing, turning the dynamic and unpredictable thing such as network to fixed and given.
19
+
When it comes to the network, you employ API mocking tools to establish this boundary and help your tests focus on the right thing, turning the dynamic and unpredictable thing such as network to fixed and given.
20
20
21
-
In this exercise, we would have toto intercept and mock the `POST https://api.example.com/discount/code` that our component makes during tests. We will use the library called [Mock Service Worker](https://mswjs.io/) (MSW) to do that.
21
+
In this exercise, we have to intercept and mock the `POST https://api.example.com/discount/code` request that our component makes during tests. We will use the library called [Mock Service Worker](https://mswjs.io/) (MSW) to do that.
22
22
23
23
## Using MSW with Vitest Browser Mode
24
24
25
-
Integrating MSW with Vitest Browser Mode is a little different from the usual browser integration so let's go throuigh it together. Follow the instructions below.
25
+
Integrating MSW with Vitest Browser Mode is a little different from the usual browser integration so let's go through it together. Follow the instructions below.
26
26
27
27
### Installation and setup
28
28
@@ -190,7 +190,7 @@ export const test = testBase.extend({
190
190
})
191
191
```
192
192
193
-
> :owl: Passing `auto: true` to a fixture will make Vitest initialize it _automatically_, even if it's not explicitly referenced in the test.
193
+
> :owl: Passing `auto: true` to a fixture will make Vitest initialize it _automatically_, even if it's not explicitly referenced in a test.
194
194
195
195
With the setup finally done, let's move on to describing the network.
196
196
@@ -202,7 +202,7 @@ With the setup finally done, let's move on to describing the network.
202
202
import { http, HttpResponse } from'msw'
203
203
```
204
204
205
-
Now is the turn to _describe the network_ you want. In MSW, you do that using functions called [Request handlers](https://mswjs.io/docs/concepts/request-handler) that are responsible for two things: intercepting requests and deciding how to handle them.
205
+
Now is your turn to _describe the network_ you want. In MSW, you do that using functions called [Request handlers](https://mswjs.io/docs/concepts/request-handler) that are responsible for two things: intercepting requests and deciding how to handle them.
206
206
207
207
🐨 In `src/mocks/handlers.ts`, export an array called `handlers` and declare your first request handler for the `POSThttps://api.example.com/discount/code` request in it:
208
208
@@ -214,7 +214,7 @@ export const handlers = [
214
214
]
215
215
```
216
216
217
-
Thisrequesthandlerwillinterceptanymatchingrequestsandexecutethecallbackfunction you've provided as the second argument. That function—also called a _response resolver_—doesn't do anything thought! Let's fix that.
217
+
Thisrequesthandlerwillinterceptanymatchingrequestsandexecutethecallbackfunction you've provided as the second argument. That function—also called a _response resolver_—doesn't do anything, though! Let's fix that.
218
218
219
219
Our component expects a response from the server to have the following shape:
220
220
@@ -230,7 +230,7 @@ Our component expects a response from the server to have the following shape:
230
230
231
231
Since the `code` data comes from the client, let's read the intercepted request's body to retrieve the sent discount code.
232
232
233
-
🐨 In the response resolver function, access the `request` property on the argument object to the response resolver and read the reqest's body ...
233
+
🐨 In the response resolver function, access the `request` property on the argument object to the response resolver and read the request's body:
0 commit comments