> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobster.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Accessibility audit

> Audit every screen a check visits for missing labels, small tap targets and clipped text, and let CI fail only on new findings.

`mobster test --a11y` audits each screen your checks visit, from the accessibility tree Mobster already reads. It calls no model, sends nothing off your Mac and adds one tree read per step, about a second on a simulator (measured 28 Sep 2026: 0.8 to 1.6 s). A screen it has seen is audited once.

```sh theme={"theme":"css-variables"}
mobster test --a11y            # report findings as warnings; the checks still pass
mobster test --a11y=strict     # a new finding fails its check
```

A check turns it on by itself with `a11y: warn` or `a11y: strict` in its file. `--a11y` applies to every check; a check that says `strict` stays strict. The older `audit: a11y` also stays strict.

## The rules

| Finding | What it finds |
| - | - |
| `control-no-label` | A button, switch, link, slider, stepper or text field with no label. A text field's placeholder counts; an identifier doesn't, because VoiceOver doesn't read it |
| `label-unhelpful` | A control or image labelled `button`, `image`, `icon`, a file name such as `icon_close.png`, or a code name such as `ic_close` |
| `duplicate-label` | Two or more buttons, links or switches on one screen with the same label, so VoiceOver reads them alike |
| `image-no-label` | An image with no label that isn't inside a labelled control |
| `target-too-small` | A button, link or switch under 44 by 44 pt |
| `unreachable-element` | A labelled, enabled control whose frame is wholly off the screen and in no scroll view |
| `text-clipped` | Only when the check sets `conditions.content_size` to `extra-large` or larger: text whose frame crosses the screen's side edges or leaves its container |

`text-clipped` reads frames, not pixels. Text that truncates inside a frame of the right size isn't found, so a clean run is not proof that Dynamic Type works.

Mobster doesn't audit colour contrast. The tree has no colours, and the pixels of a screenshot under translucent bars, images and gradients don't give a foreground and background you can trust, so a number would be a guess.

## Warnings, failures and the baseline

Each finding has a `level` in `results.json`:

* `warn`: reported, the check passes. This is the level of `--a11y`.
* `fail`: with `--a11y=strict`, the check fails with `reason.class` `finding`.
* `known`: the finding is in the project's baseline. It is listed and never fails.

A project with existing problems starts clean by recording them:

```sh theme={"theme":"css-variables"}
mobster test --a11y --update-a11y-baseline
```

```text theme={"theme":"css-variables"}
Accessibility: 0 new, 14 warnings, 0 in the baseline
Wrote .mobster/a11y-baseline.json with 14 findings.
```

Commit `.mobster/a11y-baseline.json`. From then on `mobster test --a11y=strict` in CI fails only on a finding that isn't in it:

```text theme={"theme":"css-variables"}
Accessibility: 1 new, 0 warnings, 13 in the baseline
```

A baseline entry is a JSON-encoded tuple of the check's file, the rule, and the element's role, label and identifier. It ignores the element's position, so a layout shift doesn't make an old finding new. Fix an element and its finding disappears; the next `--update-a11y-baseline` drops its entry. A baseline file that isn't valid stops the run. Pass `--update-a11y-baseline` to replace it with the current findings.

## Where findings go

* **`results.json`**: each device result's `findings` lists `id`, `audit`, `guideline`, `level`, `key`, `message`, the `element` (`role`, `label`, `identifier`, `rect` in points) and the `frame` of the screen.
* **The HTML report**: a tag in the header counts new findings, warnings and baseline entries, and each check's page lists its findings with the frame.
* **`junit.xml`**: one extra `<testcase>` per finding in the device's `<testsuite>`, named `<check>: <rule>, <element>`. A `fail` finding has a `<failure type="accessibility">`; a `warn` finding passes and carries `Warning: …` in `<system-out>`; a `known` finding gets no case.
* **The terminal**: one `Accessibility:` line after the counts.

This page's commands run on simulators and on `--device` iPhones. `mobster test pr` doesn't take `--a11y`; put `a11y:` in the checks it runs.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.