# Actions and targets

> Every action a shot can perform on screen (show, click, type, scroll, wait, check), and how to target an element reliably with an element id or text.

## Shot actions

| Action | On screen |
|---|---|
| `show: <target>` | The camera zooms in on the target, the cursor moves to it and a ring appears. |
| `click: <target>` | The cursor clicks, followed by a cross-fade. `film: true` films the animation instead. Add `count: 3` to the target for a triple-click (to select a paragraph), or `button: right` for the context menu. |
| `type: { target, text, clear? }` | The typing is filmed. Date and time fields receive their ISO value. |
| `select: { target, option }` | Picks an option in a `<select>`, by value or label. Shown like a click. |
| `scroll: <target>` | A filmed scroll, then a zoom. |
| `hover: <target>` | The mouse rests on the target, for menus that open on hover. |
| `hold: { target, ms }` | A long press, filmed. |
| `attach: { target, file }` | Chooses a file (`files: [...]` for several). Files must come from `.ondaclip/fixtures/`. Also works in `setup`. |

If a click opens a new tab (a payment page, for example), add
`newTab: true` to its shot. The following shots run and are filmed in that
tab. A later shot with `back: true` closes it and continues in your app.

```yaml
- say: { en-US: The payment page opens. }
  click: { id: pay-button }
  newTab: true
- say: { en-US: Back in the app, the invoice is paid. }
  back: true
  show: { id: invoice-status }
```

## Other actions

These work in `setup`, `cleanup` and shots.

| Action | What it does |
|---|---|
| `wait: { url, text, target, ms, timeout }` | Waits for a page, some text, an element or a set time. |
| `check: { target, contains }` | Checks some text. A tutorial doubles as an end-to-end test. |
| `check: { target, value }` | Checks the exact value of a field. |
| `remember: { name, target, pattern }` | Saves text from the screen; use it later as `{name}`. `attribute: href` saves a link instead. |
| `remember: { name, url }` | Saves part of the URL. |

In any text, `{date+N}` is the ISO date N days from today. `{run}` is a value unique to each run (letters and digits), for an email or name the app must never see twice: `client-{run}@example.com`.

In `setup:` and `cleanup:`, `ifPresent: true` skips an action when its target isn't there. `ifPresent: 5000` first waits up to 5 seconds for it (for example, a welcome window that appears after loading). For a radio button without its own id, use `{ role: radio, name: <its label> }`.

## A command in setup and cleanup

`run: "node <file> [arguments]"` runs a script from your repository off
screen, before the first step or after the last one. For example, use it to
give the demo account a role, or to save and restore the demo workspace's
settings.

```yaml
setup:
  - run: node scripts/demo-role.cjs member
cleanup:
  - run: node scripts/demo-role.cjs admin
```

- It runs from the repository root (the folder that contains
  `.ondaclip/`), for 120 seconds at most.
- It receives `TUTORIAL_ID`, `TUTORIAL_OUTPUT` (a folder for any files it
  writes) and `TUTORIAL_APP_URL`.
- It's deliberately narrow: `node`, a file inside the repository and plain
  arguments. No shell characters (`; | & $ > <`, quotes).
- If it fails, the shoot stops and shows the last lines the script printed.
- It only works when shoots run on your own infrastructure. On Ondaclip
  Cloud, none of your code runs.

## Mock responses for a step

`mock` on a step answers GET requests while the step plays. Use it to show a
state without changing your demo data (for example, an integration shown as
not connected):

```yaml
steps:
  - id: connect
    mock:
      - { url: "/api/integrations/status", json: { connected: false } }
```

## Targets

A target points to a single element. From most stable to least stable:

```yaml
{ id: orders-search-input }                        # best: a data-ondaclip-id
{ id: orders-row, contains: Brunch }               # an id with this text
{ role: button, name: Save }                       # an accessible role and name
{ text: Save }                                     # a visible text
{ css: ".orders > li:first-child" }                # last resort
```

Prefer `id`: it doesn't change when the wording or layout changes, and it's
the same in every language. It matches `data-ondaclip-id`, then
`data-testid`. The old `testid` key still works and means the same thing. See [make your app filmable](/docs/filmable-app/).

Source: https://ondaclip.com/docs/actions/
