absinthe_conn_test

Utilities for testing GraphQL APIs


Keywords
absinthe, elixir, graphql, phoenix, testing, uploads
License
MIT

Documentation

Absinthe.ConnTest

This package makes it really convenient to execute GraphQL queries and mutations against your Phoenix Endpoint.

Executing queries as HTTP requests helps to ensure that your application behaves the same way under test as it does under normal circumstances.

Installation

The package can be installed by adding absinthe_conn_test to your list of dependencies in mix.exs:

def deps do
  [
    {:absinthe_conn_test, "~> 0.1.0"}
  ]
end

Setup

You'll probably want to import this module in your ConnCase.

# test/support/conn_case.ex

defmodule MyAppWeb.ConnCase do
  use ExUnit.CaseTemplate

  using do
    quote do
      # ...etc, etc

      # Import this library
      import Absinthe.ConnTest

      # The default endpoint for testing
      @endpoint MyAppWeb.Endpoint

      # The default URL for your GraphQL API
      @graphql "/graphql"
    end
  end

  # ... etc, etc
end

Testing

A simple test might look something like this:

defmodule MyAppWeb.Schema.UsersTest do
  use MyAppWeb.ConnCase

  @say_hello """
  query SayHello($name: String!) {
    hello(name: $name)
  }
  """

  test "hello", %{conn: conn} do
    assert {:ok, %{"hello" => "Hello, Ray!"}} =
            graphql(conn, @say_hello, name: "Ray")
  end
end

Importing queries

Yuck, it's kind of annoying to write your queries in your test file. Let's move them to dedicated .graphql file:

# test/fixtures/queries.graphql

query SayHello($name: String!) {
  hello(name: $name)
}

Now, you can import those queries, and they'll become test functions!

defmodule MyAppWeb.Schema.UsersTest do
  use MyAppWeb.ConnCase

  import_queries "test/fixtures/queries.graphql"

  test "hello", %{conn: conn} do
    assert {:ok, %{"hello" => "Hello, Ray!"}} = say_hello(conn, name: "Ray")
  end
end

Note that in the example above the SayHello query became a function say_hello.

Errors

Errors are returned in a concise format:

test "produces an error message", %{conn: conn} do
  assert {:error, ["is invalid"]} = create_user(conn, data: %{})
end

If your error contains extensions, it'll look like this:

test "produces an error message with extensions", %{conn: conn} do
  assert {:error, [{"is invalid", %{"code" => "VALIDATION_ERROR"}}]} =
           create_user(conn, data: %{})
end

Fragments

Yup, they're supported too. It will also resolve #import expressions.

# test/fixtures/users.graphql

fragment User on User {
  id
  name
}
#import "./user.graphql"

query ListUsers {
  users {
    ...User
  }
}

File Uploads

If you attempt to send a %Plug.Upload{} to your API, this library will extract it for you in accordance with Absinthe's file upload specification.

# test/fixtures/queries.graphl

mutation UploadImage($image: Upload!) {
  uploadImage(image: $image)
}
import_queries "test/fixtures/queries.graphql"

test "uploading an image", %{conn: conn} do
  image = %Plug.Upload{
    filename: "foo.png",
    path: "test/fixtures/image.png"
  }

  assert {:ok, } = upload_image(conn, image: image)
end