@@ -263,24 +263,32 @@ function Login() {
263263}
264264
265265export default Login
266+ ```
266267
268+ ```jsx
267269// __tests__/login.js
268270// again, these first two imports are something you' d normally handle in
269271// your testing framework configuration rather than importing them in every file.
270272import ' @testing-library/jest-dom'
271273import React from ' react'
274+ // import API mocking utilities from Mock Service Worker.
275+ import {rest } from ' msw'
276+ import {setupServer } from ' msw/node'
277+ // import testing utilities
272278import {render , fireEvent , screen } from ' @testing-library/react'
273279import Login from ' ../login'
274280
275- test (' allows the user to login successfully' , async () => {
276- // mock out window.fetch for the test
277- const fakeUserResponse = {token: ' fake_user_token' }
278- jest .spyOn (window , ' fetch' ).mockImplementationOnce (() => {
279- return Promise .resolve ({
280- json : () => Promise .resolve (fakeUserResponse),
281- })
281+ const server = setupServer (
282+ rest .post (' /api/login' , (req , res , ctx ) => {
283+ return res (ctx .json ({token: ' fake_user_token' }))
282284 })
285+ )
283286
287+ beforeAll (() => server .listen ())
288+ afterEach (() => server .resetHandlers ())
289+ afterAll (() => server .close ())
290+
291+ test (' allows the user to login successfully' , async () => {
284292 render (< Login / > )
285293
286294 // fill out the form
@@ -303,8 +311,42 @@ test('allows the user to login successfully', async () => {
303311 expect (alert).toHaveTextContent (/ congrats/ i )
304312 expect (window .localStorage .getItem (' token' )).toEqual (fakeUserResponse .token )
305313})
314+
315+ test (' handles server exceptions' , async () => {
316+ // mock the server error response for this test suite only.
317+ server .use (
318+ rest .post (' /' , (req , res , ctx ) => {
319+ return res (
320+ ctx .status (500 ),
321+ ctx .json ({message: ' Internal server error' }),
322+ )
323+ })
324+ )
325+
326+ render (< Login / > )
327+
328+ // fill out the form
329+ fireEvent .change (screen .getByLabelText (/ username/ i ), {
330+ target: {value: ' chuck' },
331+ })
332+ fireEvent .change (screen .getByLabelText (/ password/ i ), {
333+ target: {value: ' norris' },
334+ })
335+
336+ fireEvent .click (screen .getByText (/ submit/ i ))
337+
338+ // wait for the error message
339+ const alert = await screen .findByRole (' alert' )
340+
341+ expect (alert).toHaveTextContent (/ internal server error/ i )
342+ expect (window .localStorage .getItem (' token' )).toBeNull ()
343+ })
306344` ` `
307345
346+ > We recommend using [Mock Service Worker](https://github.com/mswjs/msw) library
347+ > to declaratively mock API communication in your tests instead of stubbing
348+ > ` window .fetch ` , or relying on third-party adapters.
349+
308350### More Examples
309351
310352> We're in the process of moving examples to the
0 commit comments