# MQTT

> Publish messages to MQTT topics, and check the messages your services publish there, over MQTT 5 (Mosquitto, EMQX, HiveMQ, RabbitMQ's MQTT plugin).

Source: https://axx.nimbusxr.us/references/packs/mqtt/

Publish messages to MQTT topics, and check the messages your services publish there, over MQTT 5 (Mosquitto, EMQX, HiveMQ, RabbitMQ's MQTT plugin).

Register the broker once, usually in the `Background`; every MQTT step of the scenario uses it:

```gherkin
Given the depots mqtt broker with the following properties:
  | url      | mqtt://localhost:1883    |
  | username | depot-scanners           |
  | password | ${env:MQTT_PASSWORD}     |
```

Steps name a **topic**: `the depots/LEJ/scans mqtt topic`. Messages carry user properties (`property <name>` rows), and are published at QoS 1, not retained, unless the `qos` and `retain` rows say otherwise.

- **A check subscribes for the run:** for the topics a run checks, Axx subscribes once the services are up, with a connection of its own. A topic in a check can be a filter with `+` and `#`: `the depots/+/alerts mqtt topic`, and a `topic` row checks the topic a message came on.
- **A check only looks at the messages received since its scenario started,** so scenarios running in parallel check their own messages, by data unique to them.
- **Retained messages from before never count:** Axx subscribes without the messages the broker keeps for new subscribers, which earlier runs may have left.
- **Secrets stay secret:** `${env:..}` values in the properties are masked in logs and failures.

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

## Steps

### `mqtt.broker`

```gherkin
Given the {word} mqtt broker 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 the MQTT broker the steps talk to.

- The first broker registered is the one the scenario's MQTT steps use.
- Values expand `${env:..}` and `${sys:..}`; `${env:..}` values are masked.

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

| Property | Takes | Default |
|---|---|---|
| `url` | the broker's URL: `mqtt://host:1883`, `mqtts://` for TLS, or `ws://` and `wss://` for MQTT over WebSockets | |
| `username` | the user Axx connects as | |
| `password` | its password, like `${env:MQTT_PASSWORD}` | |
| `client id` | the start of the client IDs Axx connects with, one per connection | ``axx-<run>`` |
| `asyncapi` | an AsyncAPI document, a file of the project or a URL, that the topics follow: every message a scenario sends there, and every message a check finds, is checked against it (with the asyncapi pack) | |

**Example:**

```gherkin
Given the depots mqtt broker with the following properties:
  | url | mqtt://localhost:1883 |
Given the depots mqtt broker with the following properties:
  | url      | mqtts://mqtt.parcels.example:8883 |
  | username | depot-scanners                   |
  | password | ${env:MQTT_PASSWORD}             |
```

_Since 0.1.5._

### `mqtt.send`

```gherkin
When a message is published to the {word} mqtt topic:
  """
  ...
  """
```

Send a message to the mqtt topic; the doc string is its body.

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

**Example:**

```gherkin
When a message is published to the depots/LEJ/scans mqtt topic:
  """
  {"scanId": "SC-8201-1", "parcelRef": "PX-8201", "status": "OUT_FOR_DELIVERY", "location": "Leipzig"}
  """
```

_Since 0.1.5._

### `mqtt.send.file`

```gherkin
When the {filepath} message is published to the {word} mqtt topic[[ with the following properties:]]
```

Send a message whose body is the file to the mqtt topic, with the properties of the table 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` |

| Name | Takes | Values | Default |
|---|---|---|---|
| `qos` | the quality of service it is published at | `0`, `1`, `2` | `1` |
| `retain` | whether the broker keeps it for new subscribers | `true`, `false` | `false` |
| `property <name>` | a user property sent with the message: its name after `property `, and its value |  | |
| `content type` | the body's media type |  | |
| `response topic` | the topic a reply goes to |  | |
| `correlation data` | what ties a reply to its request, as text |  | |

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

- `the {filepath} message is published to the {word} mqtt topic`
- `the {filepath} message is published to the {word} mqtt topic with the following properties:`

**Example:**

```gherkin
When the mqtt/scan-unknown.json message is published to the depots/LEJ/scans mqtt topic
When the mqtt/scan-unknown.json message is published to the depots/LEJ/scans mqtt topic with the following properties:
  | property scanner | LEJ-HANDHELD-7 |
  | qos              | 1              |
```

_Since 0.1.5._

### `mqtt.received`

```gherkin
Then [[within {duration} ]]the {word} mqtt topic has 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 mqtt topic has a message with those values, received since the scenario started.

- The check waits for it: 10 seconds, or `within {duration}`.
- Axx subscribes to a topic it checks for the run, without the retained messages earlier runs left.

| 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 JSON body (a field name, a dotted path or a JSONPath) and the value it has, compared as text: `null` for null and `undefined` for absent. A row `property <name>` is instead on the property of that name sent with the message: `undefined` when there is none. Rows `topic`, `content type`, `response topic` and `correlation data` are on the message itself, not its body.

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

- `the {word} mqtt topic has a message where:`
- `within {duration} the {word} mqtt topic has a message where:`

**Example:**

```gherkin
Then within 30s the depots/+/alerts mqtt topic has a message where:
  | topic            | depots/LEJ/alerts |
  | parcelRef        | PX-8299           |
  | property scanner | LEJ-HANDHELD-7    |
```

_Since 0.1.5._
