This recipe covers accessibility spot-checking for native mobile. For operationalized a11y monitoring — scheduled runs, trend tracking, aggregated reports, and stakeholder dashboards — talk to your QA Wolf team about full-service accessibility testing.
Examples
Verify a screen’s key elements are reachable via accessibility semantics:
const email = await driver.$("~Email");
const password = await driver.$("~Password");
const loginBtn = await driver.$("~Log in");
await expect(email).toBeDisplayed();
await expect(password).toBeDisplayed();
await expect(loginBtn).toBeEnabled();
await email.setValue(process.env.USER_EMAIL);
await password.setValue(process.env.USER_PASSWORD);
await loginBtn.click();
const homeHeader = await driver.$("~Home");
await expect(homeHeader).toBeDisplayed();
If you can’t locate an element using ~, that element is likely missing an accessibility label entirely — an accessibility bug worth raising with your dev team before writing the test.
Assert that icon buttons have meaningful accessible names:
const menuIcon = await driver.$("~Main menu");
await expect(menuIcon).toBeDisplayed();
const label = await menuIcon.getAttribute("content-desc");
if (!label || label.trim().length < 3) {
throw new Error("A11y: menu icon accessible label is missing or too short");
}
When to use
- You want to verify that a screen’s key interactive elements are exposed to VoiceOver (iOS) or TalkBack (Android)
- You need to catch regressions where a developer removed or renamed an accessibility label
- Your team wants a lightweight proxy for accessibility hygiene without a full WCAG audit
- You want to confirm that icon-only buttons have meaningful accessible names, not blank or placeholder labels
How it works
Tests locate elements using accessibility identifiers — attributes set by your developers that expose UI components to the OS accessibility layer.
| Platform | Attribute | WebdriverIO selector |
|---|
| Android | content-desc | driver.$('~your-label') |
| iOS | accessibilityIdentifier / accessible name | driver.$('~your-id') |
The ~ prefix is the WebdriverIO shorthand for locating an element by its accessibility ID. This is a double win: it proves the element is correctly exposed to the accessibility layer, and it keeps your tests stable across visual refactors.
Quick reference
| Goal | How to do it |
|---|
| Prove an element is on the accessibility layer | Locate it with driver.$('~accessibility-id') |
| Assert a screen is navigable via accessibility semantics | Use ~ selectors throughout the full flow |
| Assert an icon button has a meaningful label | getAttribute('content-desc') and check length |
| Assert an error or toast is readable | await expect($('~error-id')).toHaveText('...') |
Notes
QA Wolf does not run a WCAG rules engine against native app views. Native apps don’t have a DOM, so axe-core style scanning isn’t available for native iOS or Android.
For deeper audits — color contrast, touch target size, reading order — supplement these tests with manual testing using VoiceOver on iOS, TalkBack on Android, or the Xcode Accessibility Inspector and Android Studio Layout Inspector.