[ANN] ergonomic MSW bindings for testing graphql-ppx operations

MSW is a fantastic testing utility library that has completely replaced my team’s usage of @apollo/client's MockedProvider. In my opinion, it’s a more “complete” test of your GraphQL operations, and it has been significantly less fussy in throwing spurious runtime errors or mysteriously not returning data during testing. My only complaint was that writing JSON encoders in ReScript was more effort than in TypeScript or JavaScript, and due to the way rescript-apollo-client + graphql-ppx parses GraphQL responses, writing tests in TypeScript for ReScript code while getting compiler errors is possible but tricky (would not recommend trying). Considering graphql-ppx already creates the parser/serializer functions, why not reuse them for these bindings.

This package is intended to be an ergonomic, data-first wrapper for ReScript bindings to msw, particularly for usage with graphql-ppx and rescript-apollo-client. Being data-first bindings, it also plays nicely with rescript-jest and rescript-promise. It can also be used for REST APIs.

Here’s an example of constructing a network mock:

open MSW
let server = setupServer()
server->Server.listenWithOptions({onUnhandledRequest: #error})
server->Server.use(
  GraphQL_PPX.operation(module(UserQuery), ({variables, _}, {once, _}, ctx) => {
    once()
    ->ctx.status(200)
    ->ctx.data({
      userById: Some({
        __typename: "foo",
        id: variables.id,
        avatarUrl: Some("http://test.com/avatar.png"),
        fullName: "John Doe",
      }),
    })
  }),
)

I’ve already got a branch for work with the ReScript 10 upgrade and converting over to these bindings from some in-house ones, and the difference is very noticeable on complex queries.

9 Likes

I’ve published an update 0.2.0 for compatibility with MSW 2. The API changes in MSW remove the need for the pipe-able wrapper I created for the initial release; the output is nearly zero-cost now and is nearly identical to what you would write in JavaScript. Additionally, I’ve been able to remove the single (type) dependency on rescript-apollo-client.

Due to the API changes in MSW, the graphql-ppx wrapper has been turned into a module function to create the responses for each operation–you just need to pass it the graphql ppx’s module output. Example here

@zth I’m not sure what the testing landscape looks like for rescript-relay but I’d be interested in supporting relay graphql operations as well

5 Likes

Would be awesome if you had a look at supporting relay as well! Nothing else exists, that I know of at least.

1 Like