Error responses
Loading "Error Responses"
Run locally for transcripts
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 happen 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 our error handling, we will use a feature called runtime request handlers.In simple terms, a runtime request handler is a request handler you can add in individual tests. It extends your network description and allows you to add new network behaviors to your happy paths defined in
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 an example of adding a runtime handler for theGET http://localhost/resource
endpoint. Notice how the response to thefetch()
call changes based on whether the request was made before or after the runtime handler was 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.๐จ Move
handlers.ts
to ./mocks
so it becomes ./mocks/handler.ts
.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()
})