How to test your Apollo Links

If you are using Apollo Client, you are using Apollo Links.These powerful pieces of middleware / afterware allow you to augment requests in a variety of ways or help with authenticationhttps://www.apollographql.com/docs/react/networking/authentication.

I’m going to go through testing a basic authentication linkhttps://www.apollographql.com/docs/react/networking/advanced-http-networking#customizing-request-logic to show you how I’m maintaining confidence in this part of the application I’m working on.

Please note that the references are based on Apollo 3.0 documentation. While there are many changes between versions 2.x and 3.x, the ideas and APIs that will be used in this article are the same.

Basic authLink

We are going to follow the official Apollo docshttps://www.apollographql.com/docs/react/get-started and start with the basic localStorage based authentication link.

Here is the code:

import { ApolloLink } from "@apollo/client";
const authLink = new ApolloLink((operation, forward) => {
operation.setContext({
headers: {
Authorization: localStorage.getItem("token")
}
});
return forward(operation);
});

Nothing fancy here, we are just retrieving the token from the localStore and setting the Authorization header using the setContext API that is made to resemble the setState API from React class components.

The function that I passed to ApolloLink is the middleware itself. I’m using forward to pass the control of the execution to the next link in the chain.

Now, let’s get going with the tests.

Setup for the tests

First of all, we have to have a way to actually invoke our link; otherwise, we will not be able to set the Authorization header value.

Luckily, there is one utility Apollo Client exposes that can help us with that, a function called execute. This function allows us to execute GraphQL requests and pass a link(s) that will be invoked during that execution.

Let’s create a simple utility function that uses execute to trigger the link chain during the request.

import { execute, gql } from "@apollo/client";
const MockQuery = gql`
query {
foo
}
`;
function executeRequest(link) {
execute(link, { query: MockQuery }).subscribe(() => {
/* not our concern within this test */
});
}

The query itself does not matter, it is only there to trigger a request.I’ve also had to subscribe to the execute function. This part is really an implementation detail that you should not concern yourself with.

For the curious minds out there, Apollo uses Observables underneath. These are lazy by default; so, to trigger MockQuery, we had to use the subscribe function.

The next step is to create another link that will be used for making assertions.Since this will be the last link of the chain, it has to be a terminating link. This just means that we will not use the forward(operation) and will return null instead.

const assertLink = new ApolloLink(operation => {
const headers = operation.getContext().headers;
// we will make assertions here.
return null;
});

All we are doing here is getting the headers from the context and potentially making assertions on the headers object.

The actual test

With every piece of the puzzle ready to be put together, let’s write a test case that makes sure the authLink actually sets the Authorization header.

function executeRequest(link) {
// previous implementation
}
// const authLink = ... previous implementation
it("sets the `Authorization` header to the correct value", () => {
// remember to reset the value in-between tests!
localStorage.setItem("token", "token");
const lastLink = new ApolloLink(operation => {
const headers = operation.getContext().headers;
expect(headers.Authorization).toEqual("token");
return null;
});
// compose our links together
// .concat API might be an alternative, but I will stick with `.from` here.
const link = ApolloLink.from([authLink, lastLink]);
executeRequest(link);
});

The test itself is not very sophisticated, but it shouldn’t be;all we’re doing here is a simple assertion that gives us some confidence in how our authLink is working.

While this is only one test case, in my opinion, it showcases the steps you can take to test any kind of link you might use.

Free Resources