Intercept and Mock GraphQL Queries in MSW

Share this video with your friends

Social Share Links

Send Tweet

Let's spice things up by adding GraphQL to our application.

Since you are prototyping mock-first, you don't have to write any GraphQL schemas or define any resolvers. Instead, you will utilize Mock Service Worker to intercept valid GraphQL queries by their type and name, and respond with the same semantic JSON responses matching the queries.

Instructor: [0:00] On the Movie Detail page, let's fetch a list of reviews for this movie using GraphQL. Although GraphQL requests on the web still use HTTP, I recommend using a designated GraphQL client like Apollo, URQL, or GraphQL request instead of plain fetch calls.

[0:16] This way, our prototypes stay specification-compliant from day one, and the code we write is the same code we would ship to production. In the reviews list component, we are sending a GraphQL query called listReviews that will fetch the list of reviews by the given movie ID.

[0:33] Each review will have the id, text, rating, and author fields in the response. This query definition is all we need to handle it with MSW. In our handlers, import the GraphQL object from MSW. We will use this object to describe GraphQL APIs.

[0:50] The way you model your GraphQL will be based on the queries and mutations that you're sending from the client, so I will copy the movieReviews query and put it next to the request handler for reference.

[1:07] To intercept a GraphQL request, we will type GraphQL and choose the right operation type from the methods on the subject. We want to intercept a query, so we will choose the GraphQL.query method.

[1:20] As the first argument to it, provide the query name, which in our case is listReviews. The second argument will be the response resolver function, the same as with the HTTP handlers.

[1:32] Our query sends a movieId variable to fetch the reviews for that particular movie. To access the variables of a GraphQL operation, use the variables key on the resolver argument.

[1:44] Variables is a plain object whose keys equal the variable names from the query definition, like movieId, and values equal to those variables' values. Knowing the right movieId, let's look it up in the list of all movies.

[2:02] Once we've got the movie, get its reviews property that will represent the list of all reviews this movie has. We will add the actual data later. GraphQL servers must return JSON responses, so let's return one using the httpResponse.json static method.

[2:22] GraphQL responses have a set of differences compared to regular HTTP responses. They must always return a 200 status code, even in case of errors, and their JSON body is restricted to the root-level data, errors, and extensions properties. We must respect these differences to produce valid GraphQL responses so that the client would handle them properly.

[2:44] To respond with data, add the data property on the response body. The shape of the data you return from GraphQL handlers should correspond to the fields described in the query. This means we will have the Reviews property that points to the list of movie reviews. Let's follow the structure of the Review fields and add a review to the existing movie.

[3:22] Now, when our application does a GraphQL request, MSW intercepts it and tries to find any matching GraphQL request handlers for its operation type and name. Once it does, it uses whichever response we return from the response resolver as the actual response our application receives.

[3:41] Notice that we haven't defined any types, schemas, or resolvers yet. MSW allows us to experiment with different APIs, both REST and GraphQL, without fully committing to either ecosystem while still writing production-ready code.