Error responses

Loading "Error Responses"
Right now, we are sending the exact successful JSON response that the getAuthToken() expects. That allows us to reproduce and test the happy path behavior.
But there are more behaviors that we intended for this function, and they happened to concern themselves with error handling.
First, there's the logic that throws an error if the server responds with a 401 response (i.e. we are sending invalid user credentials and the authorization fails):
if (response.status === 401) {
  throw new Error('Authentication failed: invalid credentials')
}
Then, there's another check for generic response errors as well:
if (!response.ok) {
  throw new Error('Authentication failed: network error')
}
Let's model both of these scenarios in tests with MSW!
The request handlers we write in handlers.ts are meant to describe the happy path behaviors. In order to test the error handling that we have, we will utilize something called runtime request handlers.
In simple terms, a runtime handler is a request handler you can add on runtime. It extends your network description and allows you to prepend new network behaviors to your happy paths from handlers.ts.
Runtime handlers can be added using the server.use() function:
import { http } from 'msw'
import { setupServer } from 'msw/node'

const server = setupServer(
  // This is a happy path handler.
  http.get('http://localhost/resource', () => {
    return Response.json({ response: 'happy' })
  }),
)
server.listen()

await fetch('http://localhost/resource').then((response) => response.json())
// {"response":"happy"}

server.use(
  // This is a runtime handler override. It has the same
  // predicate (request path) as the happy path handler
  // but returns a different mocked response.
  http.get('http://localhost/resource', () => {
    return Response.json({ response: 'override' })
  }),
)

await fetch('http://localhost/resource').then((response) => response.json())
// {"response":"override"}
Above is the example of adding a runtime handler for the GET http://localhost/resource endpoint. Notice how the response to the fetch() call changes based on whether the request has been made before or after the runtime handler has been added.
πŸ‘¨β€πŸ’Ό It's time you learned to use the power of runtime handlers! Rewrite the test to add new test cases for the error handling logic of the getAuthToken() function.
To achieve that, you'd have to reuse the server from both for the setup file and the test.
🐨 Move handlers.ts to ./mocks so it becomes ./mocks/handler.ts.
🐨 Move the server setup from to the new mocks/node.ts module.
import { setupServer } from 'msw/node'
import { handlers } from './handlers.js'

const server = setupServer(...handlers)
import { server } from './mocks/node.js'

beforeAll(() => {
  server.listen({
    onUnhandledRequest: 'error',
  })
})

afterEach(() => {
  server.resetHandlers()
})

afterAll(() => {
  server.close()
})
🐨 Then, head to the file and complete the new test cases. Verify your solution by running npm test.