# Mocks

> Verify the requests WireMock mocks received. Stubs are defined in WireMock mapping files; Axx only verifies.

Source: https://axx.nimbusxr.us/next/references/packs/mock/

Verify the requests WireMock mocks received. Stubs are defined in WireMock mapping files; Axx only verifies.

With the Axx WireMock image (`ghcr.io/nimbusxr/axx-wiremock`), every call to a mock is checked against the mocked service's OpenAPI contract. A step that checks a call that broke the contract fails; a call that broke it, and that no step checks, fails the run after the scenarios.

The image also mocks AI models, in the format of each request (OpenAI's API and the servers that speak it, Anthropic, Gemini, Bedrock, Ollama): its stubs answer with the `model-request` matcher and the `model-answer` transformer, and the `the mocked ... model ...` steps check what the service asked the model: the texts, the tools and the schema.

Add it to a project with `axx pack add mock`.

## Steps

### `mock.service`

```gherkin
Given the mocked {word} 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 WireMock server, to check the requests it received. The first mocked service registered in a scenario is the default one.

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

| Property | Takes | Default |
|---|---|---|
| `url` | the WireMock server's URL, with its admin API at `/__admin` below it; it can use `${env:…}` and `${sys:…}` | _required_ |

Any other property fails the step.

**Example:**

```gherkin
Given the mocked addresses service with the following properties:
  | url | http://localhost:8081 |
```

### `mock.received`

```gherkin
Then the mocked {word} request to {word} named {word} was received by {mockedService}
```

Check that the mocked service received a request at least once, and name it for the steps that follow.

- The request is its method and its exact URL, query string included.
- The method is `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `OPTIONS` or `HEAD`, in capitals.
- With the Axx WireMock image, a call that broke the service's OpenAPI contract fails the step.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

**Example:**

```gherkin
Then the mocked GET request to /v1/postcodes/DE/10115 named postcode-check was received by addresses
```

### `mock.received.path`

```gherkin
Then the mocked {word} request to path {word} named {word} was received by {mockedService}
```

Check that the mocked service received a request to a path at least once, whatever its query string, and name it for the steps that follow.

- For requests whose query changes from call to call, such as a request ID: check the query parameters that matter with `the query parameters for mocked request named ... are:`.
- The method is `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `OPTIONS` or `HEAD`, in capitals.
- With the Axx WireMock image, a call that broke the service's OpenAPI contract fails the step.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

**Example:**

```gherkin
Then the mocked POST request to path /v1/collections named collection was received by courier
```

### `mock.openapi.levels`

```gherkin
Given the OpenAPI validation levels for the mocked {mockedService} service are:
  | validation key | level |
```

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

Relax the mocked service's OpenAPI contract for this scenario: a finding that would fail the mock step that checks the call is reported at the level its row sets instead.

- `WARN` logs the finding; `INFO` and `IGNORE` drop it.
- A key also covers the keys below it: `validation.response.body` covers `validation.response.body.schema.required`.
- It applies to the calls this scenario's mock steps check. A scenario whose mock steps check no call to the service logs a warning.
- A stub that is off-contract on purpose is better relaxed in its own metadata (`openApiValidationLevels`), which applies wherever it answers.
- This is the dependency's contract: your own service's is relaxed with `the OpenAPI validation levels are:`.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

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

**Example:**

```gherkin
Given the OpenAPI validation levels for the mocked addresses service are:
  | validation.response.body.schema.additionalProperties | WARN |
```

### `mock.count.exactly`

```gherkin
Then the mocked request named {word}[[ on {mockedService}]] was received exactly {int} time(s)
```

Check that the mocked service received the named request exactly that many times.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{int}` | a whole number | `200`, `3` |

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

- `the mocked request named {word} was received exactly {int} time(s)`
- `the mocked request named {word} on {mockedService} was received exactly {int} time(s)`

**Example:**

```gherkin
Then the mocked request named postcode-check was received exactly 1 time
```

### `mock.count.atLeast`

```gherkin
Then the mocked request named {word}[[ on {mockedService}]] was received at least {int} time(s)
```

Check that the mocked service received the named request at least that many times.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{int}` | a whole number | `200`, `3` |

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

- `the mocked request named {word} was received at least {int} time(s)`
- `the mocked request named {word} on {mockedService} was received at least {int} time(s)`

**Example:**

```gherkin
Then the mocked request named postcode-check was received at least 1 time
```

### `mock.count.atMost`

```gherkin
Then the mocked request named {word}[[ on {mockedService}]] was received at most {int} time(s)
```

Check that the mocked service received the named request at most that many times.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{int}` | a whole number | `200`, `3` |

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

- `the mocked request named {word} was received at most {int} time(s)`
- `the mocked request named {word} on {mockedService} was received at most {int} time(s)`

**Example:**

```gherkin
Then the mocked request named postcode-check was received at most 1 time
```

### `mock.notReceived`

```gherkin
Then the mocked {word} request to {word} named {word}[[ on {mockedService}]] was not received
```

Check that the mocked service received no request with that method and exact URL, and name it for the steps that follow.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

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

- `the mocked {word} request to {word} named {word} was not received`
- `the mocked {word} request to {word} named {word} on {mockedService} was not received`

**Example:**

```gherkin
Then the mocked GET request to /v1/postcodes/DE/12489 named skipped-check was not received
```

### `mock.notReceived.path`

```gherkin
Then the mocked {word} request to path {word} named {word}[[ on {mockedService}]] was not received
```

Check that the mocked service received no request with that method to a path, whatever its query string, and name it for the steps that follow.

- Every request the mocked service received counts, other scenarios' too: the path must be the scenario's own, like one with its parcel's reference. For a path every scenario calls, check that none of its requests has the scenario's data with `none of the mocked ... requests to path ... have ...`.
- The method is `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `OPTIONS` or `HEAD`, in capitals.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

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

- `the mocked {word} request to path {word} named {word} was not received`
- `the mocked {word} request to path {word} named {word} on {mockedService} was not received`

**Example:**

```gherkin
Then the mocked POST request to path /v1/parcels/PX-WEB-5302/returns named no-return on courier was not received
```

### `mock.header.is`

```gherkin
Then the header {word} for mocked request named {word}[[ on {mockedService}]] is {string}
```

Check that the named request was received with a header of that value. Later steps on the named request check this header too.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

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

- `the header {word} for mocked request named {word} is {string}`
- `the header {word} for mocked request named {word} on {mockedService} is {string}`

**Example:**

```gherkin
Then the header X-Api-Key for mocked request named postcode-check is 'example-address-key'
```

### `mock.headers.are`

```gherkin
Then the headers for mocked request named {word} on {mockedService} are:
  | header | value |
```

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

Check that the named request was received with every header of the table, each with its value. Later steps on the named request check these headers too.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a header's name and the value it must have.

**Example:**

```gherkin
Then the headers for mocked request named postcode-check on addresses are:
  | X-Api-Key | example-address-key |
  | Accept    | application/json    |
```

### `mock.header.matches`

```gherkin
Then the header {word} for mocked request named {word} on {mockedService} matches {pattern}
```

Check that the named request was received with a header that matches a regular expression.

- WireMock evaluates the expression, in Java syntax; it must match the whole value.
- Later steps on the named request check this header too.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{pattern}` | a regular expression (Java syntax) with no spaces, which matches the whole value | `PX-\d{4}`, `[A-Z]{2}-\d+` |

**Example:**

```gherkin
Then the header Accept for mocked request named postcode-check on addresses matches ^application/json$
```

### `mock.headers.match`

```gherkin
Then the headers for mocked request named {word} on {mockedService} match:
  | header | regular expression |
```

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

Check that the named request was received with headers that match regular expressions, a row each.

- WireMock evaluates the expressions, in Java syntax; each must match the whole value.
- Later steps on the named request check these headers too.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a header's name and a regular expression its value must match.

**Example:**

```gherkin
Then the headers for mocked request named postcode-check on addresses match:
  | X-Api-Key | example-.+         |
  | Accept    | application/json.* |
```

### `mock.header.missing`

```gherkin
Then the header {word} for mocked request named {word} on {mockedService} is missing
```

Check that the named request was received without that header. Later steps on the named request check this header too.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

**Example:**

```gherkin
Then the header Authorization for mocked request named postcode-check on addresses is missing
```

### `mock.headers.missing`

```gherkin
Then the headers for mocked request named {word} on {mockedService} are missing:
  | header |
```

Check that the named request was received without any of the headers the table names. Later steps on the named request check these headers too.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row names a header, in the table's only column.

**Example:**

```gherkin
Then the headers for mocked request named postcode-check on addresses are missing:
  | Authorization |
  | Cookie        |
```

### `mock.properties.are`

```gherkin
Then the payload properties for mocked request named {word}[[ on {mockedService}]] are:
  | property | value |
```

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

Check that the named request was received with a JSON body that has every property of the table, each with its value.

- A property is a JSONPath, like `deliverTo.postcode` or `$.lines[0].reference`; WireMock reads it.
- Values compare as text: `800` matches the number 800, and `"10115"` the string 10115. `undefined` means the body has no such property, to check that a request leaves something out.
- Later steps on the named request check these too, so its counts count only the requests that have them.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a property's JSONPath and the value it must have, or `undefined`.

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

- `the payload properties for mocked request named {word} are:`
- `the payload properties for mocked request named {word} on {mockedService} are:`

**Example:**

```gherkin
Then the payload properties for mocked request named collection on courier are:
  | reference          | PX-REG-1401 |
  | deliverTo.postcode | "10115"     |
  | recipient          | undefined   |
```

### `mock.query.are`

```gherkin
Then the query parameters for mocked request named {word}[[ on {mockedService}]] are:
  | parameter | value |
```

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

Check that the named request was received with every query parameter of the table, each with its value.

- Name the request by its path (`the mocked ... request to path ...`): a request named by its whole URL matches its query already.
- `undefined` means the query has no such parameter.
- Later steps on the named request check these too, so its counts count only the requests that have them.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a query parameter's name and the value it must have, or `undefined`.

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

- `the query parameters for mocked request named {word} are:`
- `the query parameters for mocked request named {word} on {mockedService} are:`

**Example:**

```gherkin
Then the query parameters for mocked request named collection on courier are:
  | slot      | same-day  |
  | reference | undefined |
```

### `mock.form.are`

```gherkin
Then the form fields for mocked request named {word}[[ on {mockedService}]] are:
  | field | value |
```

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

Check that the named request was received with a form-encoded body that has every field of the table, each with its value.

- `undefined` means the form has no such field.
- Later steps on the named request check these too, so its counts count only the requests that have them.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a field's name and the value it must have, or `undefined`.

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

- `the form fields for mocked request named {word} are:`
- `the form fields for mocked request named {word} on {mockedService} are:`

**Example:**

```gherkin
Then the form fields for mocked request named pickup-notice on courier are:
  | reference | PX-WEB-5401 |
  | day       | Friday      |
```

### `mock.query.none`

```gherkin
Then none of the mocked {word} requests to path {word}[[ on {mockedService}]] have the query parameters:
  | parameter | value |
```

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

Check that the mocked service received no request with that method to a path, whatever its query string, that has every query parameter of the table, each with its value.

- Every request the mocked service received counts, other scenarios' too: put the scenario's own data in the table, like its parcel's reference, next to what must not be there.
- A check that something did not happen proves little on its own: check what the scenario did send, too.
- `undefined` means the request has no such parameter.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a query parameter's name and the value it has, or `undefined`.

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

- `none of the mocked {word} requests to path {word} have the query parameters:`
- `none of the mocked {word} requests to path {word} on {mockedService} have the query parameters:`

**Example:**

```gherkin
Then none of the mocked POST requests to path /v1/collections on courier have the query parameters:
  | slot      | same-day    |
  | reference | PX-REG-1402 |
```

### `mock.properties.none`

```gherkin
Then none of the mocked {word} requests to path {word}[[ on {mockedService}]] have the payload properties:
  | property | value |
```

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

Check that the mocked service received no request with that method to a path, whatever its query string, that has every payload property of the table, each with its value.

- Every request the mocked service received counts, other scenarios' too: put the scenario's own data in the table, like its parcel's reference, next to what must not be there.
- A check that something did not happen proves little on its own: check what the scenario did send, too.
- `undefined` means the request has no such property.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a property's JSONPath, like `deliverTo.postcode`, and the value it has, or `undefined`.

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

- `none of the mocked {word} requests to path {word} have the payload properties:`
- `none of the mocked {word} requests to path {word} on {mockedService} have the payload properties:`

**Example:**

```gherkin
Then none of the mocked POST requests to path /v1/collections on courier have the payload properties:
  | reference | PX-REG-1301 |
```

### `mock.form.none`

```gherkin
Then none of the mocked {word} requests to path {word}[[ on {mockedService}]] have the form fields:
  | field | value |
```

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

Check that the mocked service received no request with that method to a path, whatever its query string, that has every form field of the table, each with its value.

- Every request the mocked service received counts, other scenarios' too: put the scenario's own data in the table, like its parcel's reference, next to what must not be there.
- A check that something did not happen proves little on its own: check what the scenario did send, too.
- `undefined` means the request has no such field.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

A row is a form field's name and the value it has, or `undefined`.

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

- `none of the mocked {word} requests to path {word} have the form fields:`
- `none of the mocked {word} requests to path {word} on {mockedService} have the form fields:`

**Example:**

```gherkin
Then none of the mocked POST requests to path /v1/pickups on courier have the form fields:
  | reference | PX-WEB-5302 |
```

### `mock.signed`

```gherkin
Then the mocked request named {word}[[ on {mockedService}]] is signed in the {word} header with the following properties:
  | property | value |
```

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

Check that the named request was received, and that every request it names is signed in the header: an HMAC of its body, or of what the `signs` template gives, made with the key.

- Axx signs what the mock received, byte for byte, its method and its path with the query, and compares the signatures.
- `{timestamp}` is read from the header's value, or from the timestamp header.
- The key expands `${env:..}`, and is masked.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |

| Property | Takes | Values | Default |
|---|---|---|---|
| `key` | the secret the signature is made with, like `${env:COURIER_WEBHOOK_KEY}` |  | _required_ |
| `algorithm` | the HMAC | `hmac-sha256`, `hmac-sha1`, `hmac-sha512` | `hmac-sha256` |
| `signs` | what is signed: a template of `{body}`, `{timestamp}` (Unix seconds), `{method}` and `{path}` (with the query), like `{timestamp}.{body}` |  | ``{body}`` |
| `encoding` | how the signature is written | `hex`, `base64` | `hex` |
| `value` | the header's value: a template of `{signature}` and `{timestamp}`, like `sha256={signature}` or `t={timestamp},v1={signature}` |  | ``{signature}`` |
| `timestamp header` | a header that also carries `{timestamp}`, as Slack's `X-Slack-Request-Timestamp` does |  | |

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

- `the mocked request named {word} is signed in the {word} header with the following properties:`
- `the mocked request named {word} on {mockedService} is signed in the {word} header with the following properties:`

**Example:**

```gherkin
Then the mocked request named status-callback on shops is signed in the X-Parcels-Signature header with the following properties:
  | key   | ${env:SHOP_WEBHOOK_KEY} |
  | value | sha256={signature}      |
```

_Since 0.1.5._

### `mock.webhook`

```gherkin
Then the mocked request named {word}[[ on {mockedService}]] is signed as a standard webhook with the key {string}
```

Check that the named request was received, and that every request it names is a Standard Webhook (standardwebhooks.com) signed with the key: its `webhook-signature` has the signature of its `webhook-id`, `webhook-timestamp` and body.

- The key is `whsec_` and the key in base64, as Standard Webhooks give it; it expands `${env:..}`, and is masked.

| Parameter | Takes | For example |
|---|---|---|
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

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

- `the mocked request named {word} is signed as a standard webhook with the key {string}`
- `the mocked request named {word} on {mockedService} is signed as a standard webhook with the key {string}`

**Example:**

```gherkin
Then the mocked request named delivered on shops is signed as a standard webhook with the key '${env:SHOP_WEBHOOK_KEY}'
```

_Since 0.1.5._

### `mock.model.asked`

```gherkin
Then the mocked {mockedService} model was asked about {string}[[ {int} time(s)]]
```

Check that the mocked model was asked about a text: that a request to it had the text in its conversation, at least once, or as many times as the step says.

- The model is a WireMock with the Axx image's model mock: its stubs are mapping files, and it answers in the format of the request, whichever provider's API the service speaks (OpenAI's and the servers that speak it, Anthropic, Gemini, Bedrock, Ollama). Register it as any mocked service.
- A request is about a text when its conversation has it: its system prompt, its messages, and the tools' calls and results, JSON-escaped text included. Every request since the run started counts, other scenarios' too: name the scenario's own data, like its parcel's reference.
- A request that continues an earlier response of OpenAI's Responses API (`previous_response_id`) is about what that response's requests were about too.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |
| `{int}` | a whole number | `200`, `3` |

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

- `the mocked {mockedService} model was asked about {string}`
- `the mocked {mockedService} model was asked about {string} {int} time(s)`

**Example:**

```gherkin
Then the mocked models model was asked about 'PX-AI-8102'
Then the mocked models model was asked about 'PX-AI-8104' 2 times
```

_Since 0.1.5._

### `mock.model.contains`

```gherkin
Then the mocked {mockedService} model's request about {string} contains {string}
```

Check that a request the mocked model was asked about a text sent another: in its messages, its tools' results, its tools or its settings.

- The model is a WireMock with the Axx image's model mock: its stubs are mapping files, and it answers in the format of the request, whichever provider's API the service speaks (OpenAI's and the servers that speak it, Anthropic, Gemini, Bedrock, Ollama). Register it as any mocked service.
- A request is about a text when its conversation has it: its system prompt, its messages, and the tools' calls and results, JSON-escaped text included. Every request since the run started counts, other scenarios' too: name the scenario's own data, like its parcel's reference.
- A request that continues an earlier response of OpenAI's Responses API (`previous_response_id`) is about what that response's requests were about too.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

**Example:**

```gherkin
Then the mocked models model's request about 'PX-AI-8102' contains 'OUT_FOR_DELIVERY'
```

_Since 0.1.5._

### `mock.model.notContains`

```gherkin
Then the mocked {mockedService} model's request about {string} does not contain {string}
```

Check that no request the mocked model was asked about a text sent another, anywhere: in its messages, its tools' results, its tools or its settings. The model must have been asked about the text, or the check proves nothing and fails.

- The model is a WireMock with the Axx image's model mock: its stubs are mapping files, and it answers in the format of the request, whichever provider's API the service speaks (OpenAI's and the servers that speak it, Anthropic, Gemini, Bedrock, Ollama). Register it as any mocked service.
- A request is about a text when its conversation has it: its system prompt, its messages, and the tools' calls and results, JSON-escaped text included. Every request since the run started counts, other scenarios' too: name the scenario's own data, like its parcel's reference.
- A request that continues an earlier response of OpenAI's Responses API (`previous_response_id`) is about what that response's requests were about too.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

**Example:**

```gherkin
Then the mocked models model's request about 'PX-AI-8102' does not contain 'Lindenweg 14'
```

_Since 0.1.5._

### `mock.model.tool`

```gherkin
Then the mocked {mockedService} model was offered the {word} tool in the request about {string}
```

Check that a request the mocked model was asked about a text offered it the tool, by its name.

- The model is a WireMock with the Axx image's model mock: its stubs are mapping files, and it answers in the format of the request, whichever provider's API the service speaks (OpenAI's and the servers that speak it, Anthropic, Gemini, Bedrock, Ollama). Register it as any mocked service.
- A request is about a text when its conversation has it: its system prompt, its messages, and the tools' calls and results, JSON-escaped text included. Every request since the run started counts, other scenarios' too: name the scenario's own data, like its parcel's reference.
- A request that continues an earlier response of OpenAI's Responses API (`previous_response_id`) is about what that response's requests were about too.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

**Example:**

```gherkin
Then the mocked models model was offered the track_parcel tool in the request about 'PX-AI-8102'
```

_Since 0.1.5._

### `mock.model.schema`

```gherkin
Then the mocked {mockedService} model was asked for the {filepath} schema in the request about {string}
```

Check that a request the mocked model was asked about a text asked for its answer in the JSON Schema of a file of the project (JSON or YAML): the structured output the request asks for is that schema, whatever the order of its keys.

- The model is a WireMock with the Axx image's model mock: its stubs are mapping files, and it answers in the format of the request, whichever provider's API the service speaks (OpenAI's and the servers that speak it, Anthropic, Gemini, Bedrock, Ollama). Register it as any mocked service.
- A request is about a text when its conversation has it: its system prompt, its messages, and the tools' calls and results, JSON-escaped text included. Every request since the run started counts, other scenarios' too: name the scenario's own data, like its parcel's reference.
- A request that continues an earlier response of OpenAI's Responses API (`previous_response_id`) is about what that response's requests were about too.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{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` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |

**Example:**

```gherkin
Then the mocked models model was asked for the schemas/address.json schema in the request about 'Lindenweg 14'
```

_Since 0.1.5._

### `mock.mcp.called`

```gherkin
Then the mocked {mockedService} mcp server's {word} tool was called[[ {int} time(s)]] with the following arguments:
  | argument | value |
```

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

Check that the service called the tool of a mocked MCP server with the table's arguments: at least once, or as many times as the step says.

- Every call since the run started counts, other scenarios' too: put the scenario's own data in the table, like its parcel's reference.
- Paths are dotted (`address.postcode`) or JSONPath, and values compare as text; `null` and `undefined` work as in the other property steps.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{int}` | a whole number | `200`, `3` |

A row is a path into the call's arguments, and its value.

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

- `the mocked {mockedService} mcp server's {word} tool was called with the following arguments:`
- `the mocked {mockedService} mcp server's {word} tool was called {int} time(s) with the following arguments:`

**Example:**

```gherkin
Then the mocked partner-carrier mcp server's shipment_status tool was called with the following arguments:
  | reference | PX-MCP-9301 |
Then the mocked partner-carrier mcp server's shipment_status tool was called 1 time with the following arguments:
  | reference | PX-MCP-9301 |
```

_Since 0.1.5._

### `mock.a2a.sent`

```gherkin
Then the mocked {mockedService} a2a agent was sent a message containing {string}[[ {int} time(s)]]
```

Check that the service sent the mocked A2A agent a message whose text has the text (its text parts, and its data parts as JSON): at least once, or as many times as the step says.

- Every message since the run started counts, other scenarios' too: look for the scenario's own data, like its parcel's reference.
- Messages sent and streamed count alike, over JSON-RPC or HTTP+JSON.

| Parameter | Takes | For example |
|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered | `addresses` |
| `{string}` | text in double or single quotes, which the step leaves out | `"Get a quote"`, `'Express'` |
| `{int}` | a whole number | `200`, `3` |

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

- `the mocked {mockedService} a2a agent was sent a message containing {string}`
- `the mocked {mockedService} a2a agent was sent a message containing {string} {int} time(s)`

**Example:**

```gherkin
Then the mocked partner-carrier a2a agent was sent a message containing 'PX-A2A-9301'
Then the mocked partner-carrier a2a agent was sent a message containing 'PX-A2A-9301' 1 time
```

_Since 0.1.5._

## Parameter types

| Parameter | Takes | Values | For example |
|---|---|---|---|
| `{mockedService}` | the name of a mocked service the scenario registered |  | `addresses` |
