GraphQL
This functionality is only available on paid plans. Check our plans here.
Tweak offers you two powerful features to work with GraphQL:
- Custom JavaScript snippets - write your own interception logic, access the request body to mock based on operation name and/or variables.
- Partial request payload matching - toggle that allows you to match partial content against a GraphQL request payload.
We cover both techniques below, but first, a small refresh on GraphQL queries - jump this part if you are very confortable with GraphQL.
GraphQL refresher
Let's use this prisma-labs/graphql-request query example to fetch a movie's details.
import { GraphQLClient } from 'graphql-request';
const client = new GraphQLClient(endpoint);
const query = gql`
query getMovie($title: String!) {
Movie(title: $title) {
title
releaseDate
actors {
name
}
}
}
`;
const variables = { title: 'Inception' };
const data = await client.request(query, variables);
There are two pieces of information convenient to intercept and mock this GraphQL query:
- The
variables
- sent in the request payload (i.e. thePOST
request body). - Operation name
getMovie
- the propertyoperationName
holds the stringgetMovie
, giving a meaning to the query. We can leverate this property to easily branch our interception logic.
Inspecting the devtools, you might find a similar object under the Request payload
tab:
{
"query": "... the raw query ...",
"variables": {
"title": "Inception"
},
"operationName": "getMovie"
}
👆 We can leverage this data to configure amazing tweak rules ✨.
Configuring tweak
Here are the recommended ways to intercept and mock GraphQL API calls. We use the above example in our demonstrations.
Using partial payload matching (low code)
If you want to avoid writting code, use partial request payload matching. What does it do? It partially compares the content you write on Request payload
against the actual request payload. If your small piece of JSON is a subset of the actual request payload, tweak intercepts the request. Here's an example:
- The URL is set to
/gql
- typically your server exposes a single GraphQL endpoint. - Select
POST
in the HTTP method (or just use the wildcard option). - Add the request payload, see example in the screenshot.
Full control with JavaScript
In case you need more flexibility to intercept a GraphQL query/mutation, you can write your own interception and mocking logic under the Response hook tab. Here's how to configure it:
- Setup the URL & HTTP similar to the above example.
- Empty the
Response paylaod
editor. - Empty the
Request payload
editor. - Write the following code in the
Response hook
editor.
// 💡 tweak makes the request body globally available in your script
const bodyObj = JSON.stringify(body);
if (bodyObj.operationName === 'getMovie' && bodyObj.variables.title === 'Inception') {
// 💡 forward your response mock
return {
data: {
title: 'Inception',
releaseDate: '2010-07-22',
actors: [
{ name: 'Leonardo DiCaprio' },
{ name: 'Joseph Gordon-Levitt' },
],
},
};
}
// 💡 forward other responses that you are not targetting for interception
return response;
Once more, for this JavaScript to kick in you need to empty both the Request payload
and Response payload
editors so that all requests go through your script, no matter their request payloads, and so that you don't override the output of your script with mock data (Response payload
takes precedence over Response hook
outputs).
One ring rule to rule them all, surgical modifications
The previous script targets a single query, but you can broaden the scope of your logic as you wish, it's just JavaScript!
Because most of the times you will work with existing GraphQL APIs deployed across different environments, one powerful technique is to use a Modify
rule to modify portions of the incoming server response. Instead of fully mocking the response you can modify particular values of the incoming server response payload.
Here's an example that appends the string | Popcorn
to the movie title
property, while keeping the rest of the data intact.
const bodyObj = JSON.stringify(body);
switch (bodyObj.operationName) {
case 'getMovie':
return {
// 💡 surgical modification of "title"
data: {
...response.data,
title: `${response.data.title} | Popcorn`,
},
};
case 'getActor':
return { ...response /* ... */ };
}
// 💡 forward other responses that you are not targetting for interception
return response;
Don't worry about errors, we got you covered, if your script breaks we catch
the error for you and log it in the devtools console.