GraphQL

Mirage ships with first-class helper functions for mocking RESTful APIs, but it doesn't currently have out-of-the-box support for GraphQL. This is where the Mirage GraphQL library comes in.

Mirage GraphQL provides helpful functions to create request handlers for your GraphQL endpoint(s), and to optionally create your own custom resolvers.

To get started, import the createGraphQLHandler function from Mirage GraphQL and pass in both your GraphQL and Mirage schemas. Mirage GraphQL will do as much work as possible to automatically resolve GraphQL queries for you.

In the following example, you don't need to supply your own resolvers for any of the queries or mutations. Additionally, you don't need to create any Mirage models. Mirage GraphQL will create models for you based on your GraphQL schema.

Try this example in the REPL!
import { createServer } from "miragejs"
import { createGraphQLHandler } from "@miragejs/graphql"

const graphQLSchema = `
  input MovieInput {
    title: String
  }

  type Movie {
    id: ID!
    title: String!
  }

  type Mutation {
    createMovie(input: MovieInput!): Movie
    deleteMovie(id: ID!): Movie
    updateMovie(id: ID!, input: MovieInput!): Movie
  }

  type Query {
    movies(title: String): [Movie]
    movie(id: ID, title: String): Movie
  }
`

createServer({
  routes() {
    this.post("/graphql", createGraphQLHandler(graphQLSchema, this.schema))
  },
  
  seeds(server) {
    server.create("Movie", {
      title: "The Lord of the Rings: The Fellowship of the Ring"
    })
    server.create("Movie", {
      title: "The Lord of the Rings: The Two Towers"
    })
    server.create("Movie", {
      title: "The Lord of the Rings: The Return of the King"
    })
  },
})

// Get a movie by its title
const movieQuery = `
query Movie($id: ID, $title: String) {
  movie(id: $id, title: $title) {
    id
    title
  }
}
`

request(
  "/graphql",
  movieQuery,
  { variables: { title: "The Lord of the Rings: The Two Towers" } }
).then(/* ... */)

// Add a movie
const createMovieMutation = `
mutation CreateMovie($input: MovieInput!) {
  createMovie(input: $input) {
    id
    title
  }
}
`

request(
  "/graphql",
  createMovieMutation,
  { variables: { title: "The Hobbit: An Unexpected Journey" } }
).then(/* ... */)

Note: This example is in a single file to keep things simple. In a real app, you should import your GraphQL schema from a separate file.

There are a lot more things Mirage GraphQL can do. For example, you can

  • supply your own resolvers, so you can do things like sort results or add three movies in one mutation
  • provide a context object to the handler so you can mock things like user auth
  • give the handler a root object for cases where your backend has one and you need to mock it

and more.

Mirage GraphQL is v0.1.x, but extracted from years of work on the ember-cli-mirage-graphql library.

To learn more, check out the README of Mirage GraphQL. Also check out the intergration tests for more in-depth examples of options, queries and mutations.

Mirage & graphql-mocks

As an unofficial community-based alternative to mocking with Mirage and GraphQL check out graphql-mocks and its Mirage middleware.

Consider using graphql-mocks with Mirage for:

  • Composable middlewares for managing and creating different scenarios and states
  • Resolver and resolver map abstractions for extending query resolutions
  • Mocking in Node environments
  • Mocking flexibly with different networks abstractions (Mock Service Worker, Nock, etc.)
  • Full typescript support and type compatability with graphql types