Tags outgoing requests with their originating defgql operation so that
multiple requests can be told apart — most usefully inside Req.Test stubs.
This is a Req plugin: attach it to opt in, then read the info back from the
test conn.
Opt in
Attach from your client's prepare_req/1 callback. Define it conditionally
so it only takes effect in the environments you want (e.g. :test):
defmodule MyApp.GitHub do
use TypedGql, otp_app: :my_app, source: "priv/schemas/github.json"
if Mix.env() == :test do
def prepare_req(req), do: TypedGql.OperationInfo.attach(req)
end
defgql :get_user, "query GetUser($id: ID!) { user(id: $id) { name } }"
endRead it back
Req.Test.stub(MyApp.GitHub, fn conn ->
case TypedGql.OperationInfo.get(conn) do
%{function: "get_user"} -> # ...
end
end)Use in tests
The main use is telling apart multiple operations that share one Req.Test
stub/expect, so a single mock can answer each defgql function differently:
test "page renders user and their posts" do
Req.Test.expect(MyApp.GitHub, 2, fn conn ->
case TypedGql.OperationInfo.get(conn).function do
"get_user" -> Req.Test.json(conn, %{"data" => %{"user" => %{"name" => "Alice"}}})
"list_posts" -> Req.Test.json(conn, %{"data" => %{"posts" => []}})
end
end)
# ... exercise code that calls both MyApp.GitHub.get_user/1 and list_posts/1
endWithout it, a shared stub cannot distinguish requests whose only difference
is which defgql function produced them (anonymous operations have no
operationName in the body to branch on).
When attached, every request carries up to three headers:
x-typed-gql-function— thedefgqlfunction name (e.g.get_user)x-typed-gql-client— the client module (e.g.MyApp.GitHub)x-typed-gql-operation— the GraphQL operation name (omitted for anonymous operations)
Summary
Functions
Attaches the operation-info request step. Opt in from prepare_req/1.
Functions
@spec attach(Req.Request.t()) :: Req.Request.t()
Attaches the operation-info request step. Opt in from prepare_req/1.