Skip to content
axxbetadocs
nextv0.2.26
GitHub
These are the docs of main, not released yet. See the docs of v0.2.26, the latest release.

GraphQL

View .mdOpen in Claude

Send queries, mutations and subscriptions to GraphQL services, and check their data and their errors, against the services’ schemas. A federated graph’s gateway and a subgraph alone are GraphQL services alike: register each at its URL.

Given the parcels graphql service with the following properties:
| url | http://localhost:8400/graphql |
| schema | introspection |
  • Operations come from a file of the project (.graphql) or a doc string, with variables from a table: a variable takes the type the operation declares for it, so 10115 is text for a String!.
  • The checks read the service’s last answer in the scenario. An answer with errors does not fail the step that sends the operation: check its errors.
  • Subscriptions go over graphql-ws (the graphql-transport-ws protocol, on the url with ws:// or wss://) or over server-sent events, and belong to the scenario, which ends them when it ends.
  • The schema is the contract: with a schema row (an SDL file of the project, a URL, or introspection), every operation and its variables are checked against it before they are sent, and every answer’s data against the operation’s types. A subgraph’s SDL may use the federation directives (@key, @link…).

Findings have keys and levels, like the REST pack’s OpenAPI findings:

Key Found when
validation.operation.<rule> the operation breaks a validation rule of the GraphQL spec (FieldsOnCorrectType, KnownArgumentNames, ProvidedRequiredArguments…)
validation.variables.missing a required variable is missing
validation.variables.type a variable is not of its type
validation.response.nonNull a non-null field is null, without an error that explains it
validation.response.type a field’s value is not of its type
validation.response.enum a value is not one of its enum’s
validation.response.missingField a field the operation selects is missing
validation.response.unknownField the data has a field the operation does not select
  • Levels: ERROR (or FAIL) fails the step, WARN and INFO log the finding, IGNORE drops it. Every finding is an ERROR unless packs.graphql.levels in axx.yaml, or the scenario’s the GraphQL validation levels are:, says otherwise.
  • Keys cover the keys below them: validation.operation sets every operation finding; the most specific key set wins.
  • Secrets stay secret: ${env:..} values in the properties are masked in logs and failures, and ${token:..} names a token of the scenario.

Add it to a project with axx pack add graphql.

In axx.yaml, under packs.graphql:

Setting Takes Values
levels Validation key -> ERROR (or FAIL), WARN, INFO or IGNORE, for every scenario. names and values
Given the {word} graphql service with the following properties:
| property | value |

The table may start with the row naming its columns, as above, or go straight to its rows.

Register a GraphQL service under a name: a federated graph’s gateway, a subgraph, or any GraphQL API.

Parameter Takes For example
{word} one word, with no spaces parcels, PX-4101
Property Takes Values Default
url the URL operations are posted to required
schema its schema, which operations and answers are checked against: an SDL file of the project, a URL, or introspection to ask the service
header.<name> a header sent with every operation, such as header.Authorization
timeout how long an operation may take, like 5s 10s
subscriptions how subscriptions go graphql-ws, sse graphql-ws
subscriptions url where subscriptions go the url, with ws://orwss:// for graphql-ws

Values are expanded (${env:..}, ${sys:..}, ${token:..}); what ${env:..} references expand to is masked everywhere.

Example:

Given the parcels graphql service with the following properties:
| url | http://localhost:8400/graphql |
| schema | introspection |
Given the graph graphql service with the following properties:
| url | https://graph.parcels.example/graphql |
| schema | graphql/supergraph.graphql |
| header.Authorization | Bearer ${token:shop} |

Since 0.1.5.

When the {filepath} query/mutation is sent to the {word} graphql service[[ with the following variables:]]

Send the query or the mutation of a file of the project, with the table’s variables when the step has one.

Parameter Takes For example
{filepath} a file of the project: a path relative to the feature file’s directory, the resources directories or axx.yaml’s directory (looked for in that order), or an absolute path, quoted when it has a space seeds/parcels.yaml, kafka/scan-delivered.json
{word} one word, with no spaces parcels, PX-4101

Each row is a variable, or a path into one (address.postcode), and its value: a value takes the type the operation declares for its variable, double quotes make it text, null is null and undefined leaves it out.

Variants, the parts in [[...]] said or left out:

  • the {filepath} query/mutation is sent to the {word} graphql service
  • the {filepath} query/mutation is sent to the {word} graphql service with the following variables:

Example:

When the graphql/parcel.graphql query is sent to the parcels graphql service with the following variables:
| reference | PX-GQL-7201 |
When the graphql/hold-parcel.graphql mutation is sent to the parcels graphql service with the following variables:
| reference | PX-GQL-7202 |
| until | 2026-10-05 |

Since 0.1.5.

When a query/mutation is sent to the {word} graphql service:
"""
...
"""

Send the query or the mutation of the doc string.

Parameter Takes For example
{word} one word, with no spaces parcels, PX-4101

Example:

When a query is sent to the parcels graphql service:
"""
{ parcel(reference: "PX-GQL-7201") { status } }
"""

Since 0.1.5.

When the {filepath} subscription is started on the {word} graphql service[[ with the following variables:]]

Start the subscription of a file of the project, with the table’s variables when the step has one. It belongs to the scenario, which ends it when it ends.

Parameter Takes For example
{filepath} a file of the project: a path relative to the feature file’s directory, the resources directories or axx.yaml’s directory (looked for in that order), or an absolute path, quoted when it has a space seeds/parcels.yaml, kafka/scan-delivered.json
{word} one word, with no spaces parcels, PX-4101

Each row is a variable, or a path into one (address.postcode), and its value: a value takes the type the operation declares for its variable, double quotes make it text, null is null and undefined leaves it out.

Variants, the parts in [[...]] said or left out:

  • the {filepath} subscription is started on the {word} graphql service
  • the {filepath} subscription is started on the {word} graphql service with the following variables:

Example:

When the graphql/parcel-scanned.graphql subscription is started on the parcels graphql service with the following variables:
| reference | PX-GQL-7203 |

Since 0.1.5.

Then the {word} graphql service answered without errors

Check that the service’s last answer has no errors.

Parameter Takes For example
{word} one word, with no spaces parcels, PX-4101

Example:

Then the parcels graphql service answered without errors

Since 0.1.5.

Then the {word} graphql service's data has the following properties:
| path | value |

The table may start with the row naming its columns, as above, or go straight to its rows.

Check the data of the service’s last answer.

Parameter Takes For example
{word} one word, with no spaces parcels, PX-4101

Each row is a path into the data (a field, a dotted path like parcel.shop.name, or a JSONPath) and its value, compared as text: null for null and undefined for absent.

Example:

Then the parcels graphql service's data has the following properties:
| parcel.status | IN_TRANSIT |
| parcel.shop.name | Maple Home |

Since 0.1.5.

Then the {word} graphql service answered an error where:
| path | value |

The table may start with the row naming its columns, as above, or go straight to its rows.

Check that the service’s last answer has an error with those values.

Parameter Takes For example
{word} one word, with no spaces parcels, PX-4101

Each row is a path into the error (message, path, extensions.code) and its value, compared as text; the error’s path is its fields and indexes joined with dots, like parcel.shop or parcels.0.reference.

Example:

Then the parcels graphql service answered an error where:
| path | holdParcel |
| extensions.code | NOT_HOLDABLE |

Since 0.1.5.

Then [[within {duration} ]]the {word} graphql service's subscription received a message where:
| path | value |

The table may start with the row naming its columns, as above, or go straight to its rows.

Check that the service’s subscription received a message whose data has those values.

  • The check waits for it: 10 seconds, or within {duration}.
  • When the subscription has ended, it fails at once, saying why.
Parameter Takes For example
{duration} a duration in seconds (s) or minutes (m) 5s, 2m
{word} one word, with no spaces parcels, PX-4101

Each row is a path into the message’s data and its value, compared as text: null for null and undefined for absent.

Variants, the parts in [[...]] said or left out:

  • the {word} graphql service's subscription received a message where:
  • within {duration} the {word} graphql service's subscription received a message where:

Example:

Then within 20s the parcels graphql service's subscription received a message where:
| parcelScanned.reference | PX-GQL-7203 |
| parcelScanned.status | OUT_FOR_DELIVERY |

Since 0.1.5.

Given the GraphQL validation levels are:
| validation key | level |

The table may start with the row naming its columns, as above, or go straight to its rows.

Set the level of GraphQL validation findings for this scenario, on every GraphQL service it sends operations to.

  • A key also sets the keys below it: validation.operation relaxes validation.operation.FieldsOnCorrectType too. The most specific key set wins.
  • The rows are merged over packs.graphql.levels of axx.yaml.
  • The pack’s documentation lists the keys, and what each level does.

A row is a validation key and its level: ERROR (or FAIL), WARN, INFO or IGNORE. The key must be one the pack reports, or a prefix of such keys, like validation.operation: any other fails the step, which names the closest keys.

Example:

Given the GraphQL validation levels are:
| validation.operation.FieldsOnCorrectType | IGNORE |

Since 0.1.5.