# WebSockets

> Open WebSocket connections to your services, send messages on them, and check the messages they receive and how they close.

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

Open WebSocket connections to your services, send messages on them, and check the messages they receive and how they close.

Register a connection with `the {word} websocket with the following properties:`: it opens there and then, with the headers and subprotocol the table gives, and belongs to the scenario, which closes it when it ends.

- **What is received** is checked like the messages of queues and topics: `received a message where:` takes a table of paths into a JSON message and the values they have, and `received a message containing {string}` looks for text in any message. The checks wait, 10 seconds unless `within {duration}` says otherwise, and look at every message the connection received.
- **A connection the server closes** fails a check that is still waiting at once, saying why; `was closed with code {int}` checks the code it closed with.
- **Secrets stay secret:** `${env:..}` values in the URL and the headers, such as a token, are masked in logs and failures.

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

## Steps

### `websocket.connect`

```gherkin
Given the {word} websocket with the following properties:
  | property | value |
```

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

Open a WebSocket connection under a name. It belongs to the scenario, which closes it when it ends.

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

| Property | Takes | Default |
|---|---|---|
| `url` | the address, `ws://` or `wss://` | _required_ |
| `header.<name>` | a header of the opening request, such as `header.Authorization` | |
| `subprotocol` | the subprotocols to offer, separated by commas | |
| `asyncapi` | an AsyncAPI document, a file of the project or a URL, that the messages both ways follow: every message a scenario sends there, and every message a check finds, is checked against it (with the asyncapi pack) | |

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

**Example:**

```gherkin
Given the tracking websocket with the following properties:
  | url | ws://localhost:8400/portal/track/PX-LIV-5701/live |
```

_Since 0.1.5._

### `websocket.send`

```gherkin
When a message is sent to the {word} websocket:
  """
  ...
  """
```

Send the doc string as a text message on the connection.

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

**Example:**

```gherkin
When a message is sent to the tracking websocket:
  """
  {"follow": "PX-LIV-5701"}
  """
```

_Since 0.1.5._

### `websocket.send.file`

```gherkin
When the {filepath} message is sent to the {word} websocket
```

Send the file of the project as a text message on the connection.

| 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` |

**Example:**

```gherkin
When the tracking/follow-PX-LIV-5701.json message is sent to the tracking websocket
```

_Since 0.1.5._

### `websocket.received`

```gherkin
Then [[within {duration} ]]the {word} websocket 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 connection received a JSON message with those values. The check waits for it: 10 seconds, or `within {duration}`.

| 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 (a field name, a dotted path or a JSONPath) and the value it has, compared as text: `null` for null and `undefined` for absent.

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

- `the {word} websocket received a message where:`
- `within {duration} the {word} websocket received a message where:`

**Example:**

```gherkin
Then within 20s the tracking websocket received a message where:
  | reference | PX-LIV-5701      |
  | status    | OUT_FOR_DELIVERY |
```

_Since 0.1.5._

### `websocket.received.text`

```gherkin
Then [[within {duration} ]]the {word} websocket received a message containing {string}
```

Check that the connection received a message containing the text. The check waits for it: 10 seconds, or `within {duration}`.

| Parameter | Takes | For example |
|---|---|---|
| `{duration}` | a duration in seconds (`s`) or minutes (`m`) | `5s`, `2m` |
| `{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'` |

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

- `the {word} websocket received a message containing {string}`
- `within {duration} the {word} websocket received a message containing {string}`

**Example:**

```gherkin
Then the tracking websocket received a message containing 'PX-LIV-5701'
```

_Since 0.1.5._

### `websocket.closed`

```gherkin
Then [[within {duration} ]]the {word} websocket was closed with code {int}
```

Check that the server closed the connection with that close code, such as 1000 (normal) or 1008 (a policy it breaks). The check waits for it: 10 seconds, or `within {duration}`.

| Parameter | Takes | For example |
|---|---|---|
| `{duration}` | a duration in seconds (`s`) or minutes (`m`) | `5s`, `2m` |
| `{word}` | one word, with no spaces | `parcels`, `PX-4101` |
| `{int}` | a whole number | `200`, `3` |

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

- `the {word} websocket was closed with code {int}`
- `within {duration} the {word} websocket was closed with code {int}`

**Example:**

```gherkin
Then the tracking websocket was closed with code 1008
```

_Since 0.1.5._
