Skip to content

Commit 00f77f5

Browse files
committed
Merge branch 'main' into feat/tracing
2 parents 65ef51a + ffce24f commit 00f77f5

75 files changed

Lines changed: 4746 additions & 1054 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/CLAUDE.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Mobilewright — Claude Code rules
2+
3+
## Commits & branches
4+
5+
- Branch names must follow conventional format: `feat/…`, `fix/…`, `chore/…`, `ci/…`, `docs/…`, `refactor/…`, `test/…`
6+
- Commit messages must follow Conventional Commits: `feat:`, `fix:`, `chore:`, etc. — single line, no body
7+
- Always run `npm run lint` and confirm it passes before committing
8+
- Stage only the files required for the change — never `git add -A` or `git add .`
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
Prepare a mobilewright release by updating CHANGELOG.md with the next patch version.
2+
3+
## Steps
4+
5+
### 1. Verify version consistency
6+
7+
- Run `git tag --sort=-version:refname | head -1` to get the latest git tag (e.g. `v0.0.35`)
8+
- Read the first line of `CHANGELOG.md` to extract the version there (e.g. `## [0.0.35]`)
9+
- If they do not match, stop and report the mismatch. Do not proceed.
10+
11+
### 2. Compute next version
12+
13+
- Strip the `v` prefix from the latest tag, split on `.`, increment the patch segment by 1
14+
- Example: `v0.0.35``0.0.36`
15+
16+
### 3. Collect changes since last tag
17+
18+
- Run `git log v<LAST_VERSION>..HEAD --oneline` to list commits
19+
- For each commit, try to find an associated PR number:
20+
- Look for `(#NNN)` in the commit message, or
21+
- Run `gh pr list --state merged --search "<commit sha>" --json number,title,author` via the GitHub API
22+
- For each PR found, fetch the author: `gh pr view <NNN> --repo mobile-next/mobilewright --json author --jq '.author.login'`
23+
24+
### 4. Determine contributor credit
25+
26+
- Read `.github/CODEOWNERS` to get the list of maintainer GitHub logins
27+
- For each change, if the PR author is **not** in the CODEOWNERS maintainers list, append:
28+
`thanks to [@<login>](https://github.com/<login>)`
29+
30+
### 5. Format the CHANGELOG entry
31+
32+
Use the existing CHANGELOG.md format:
33+
34+
```
35+
## [0.0.36] (YYYY-MM-DD)
36+
* Feat: description ([#NNN](https://github.com/mobile-next/mobilewright/pull/NNN))
37+
* Fix: description ([#NNN](https://github.com/mobile-next/mobilewright/pull/NNN)), thanks to [@login](https://github.com/login)
38+
```
39+
40+
- Use today's date for the release date
41+
- Capitalise the type prefix (`Feat`, `Fix`, `Chore`, etc.) from the conventional commit prefix
42+
- Omit chore/ci/docs commits that are not user-facing unless they are significant
43+
- Prepend the new entry at the top of CHANGELOG.md, above the previous `## [...]` line
44+
45+
### 6. Stop — do not commit
46+
47+
Display the new CHANGELOG.md entry and remind the human to review and commit manually when ready.
48+
The suggested commit and tag commands to show the user:
49+
50+
```
51+
git add CHANGELOG.md
52+
git commit -m "chore: update changelog for v0.0.36"
53+
git tag v0.0.36
54+
git push && git push --tags
55+
```
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Bug Report
2+
description: Report a bug or unexpected behavior in Mobilewright
3+
labels: ["bug"]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
Before opening a bug report, please [search existing issues](https://github.com/mobile-next/mobilewright/issues) to avoid duplicates.
9+
10+
- type: input
11+
id: version
12+
attributes:
13+
label: Mobilewright version
14+
placeholder: "e.g. 1.2.3"
15+
validations:
16+
required: true
17+
18+
- type: input
19+
id: os
20+
attributes:
21+
label: Operating system
22+
placeholder: "e.g. macOS 15.4, Ubuntu 24.04"
23+
validations:
24+
required: true
25+
26+
- type: dropdown
27+
id: platform
28+
attributes:
29+
label: Target platform
30+
options:
31+
- iOS
32+
- Android
33+
- Both
34+
validations:
35+
required: true
36+
37+
- type: input
38+
id: device
39+
attributes:
40+
label: Device or simulator
41+
placeholder: "e.g. iPhone 16 Pro (simulator), Pixel 8 (real device)"
42+
validations:
43+
required: true
44+
45+
- type: textarea
46+
id: reproduction
47+
attributes:
48+
label: Minimal reproduction
49+
description: Smallest possible code or steps to reproduce the issue.
50+
placeholder: |
51+
1. ...
52+
2. ...
53+
validations:
54+
required: true
55+
56+
- type: textarea
57+
id: actual
58+
attributes:
59+
label: Actual behavior
60+
description: What happened?
61+
validations:
62+
required: true
63+
64+
- type: textarea
65+
id: expected
66+
attributes:
67+
label: Expected behavior
68+
description: What did you expect to happen?
69+
validations:
70+
required: true
71+
72+
- type: textarea
73+
id: extra
74+
attributes:
75+
label: Additional context
76+
description: Logs, screenshots, or anything else that may be relevant.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: Feature Request
2+
description: Propose a new feature or enhancement
3+
labels: ["enhancement"]
4+
body:
5+
- type: markdown
6+
attributes:
7+
value: |
8+
For larger feature proposals, please open this issue to discuss the design **before** sending a PR. This helps avoid wasted effort and keeps changes aligned with the project direction.
9+
10+
- type: textarea
11+
id: problem
12+
attributes:
13+
label: Problem or motivation
14+
description: What problem does this feature solve? What use case does it unlock?
15+
validations:
16+
required: true
17+
18+
- type: textarea
19+
id: solution
20+
attributes:
21+
label: Proposed solution
22+
description: Describe the feature you'd like, including any API or behavior changes.
23+
validations:
24+
required: true
25+
26+
- type: dropdown
27+
id: platform
28+
attributes:
29+
label: Target platform
30+
options:
31+
- iOS
32+
- Android
33+
- Both
34+
- Platform-agnostic
35+
validations:
36+
required: true
37+
38+
- type: textarea
39+
id: alternatives
40+
attributes:
41+
label: Alternatives considered
42+
description: Any other approaches you've thought of, and why you prefer this one.
43+
44+
- type: textarea
45+
id: extra
46+
attributes:
47+
label: Additional context
48+
description: Mockups, screenshots, references, related issues, or anything else that would help.

.github/workflows/ci.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,17 @@ on:
44
push:
55
branches:
66
- main
7+
paths-ignore:
8+
- 'README.md'
9+
- 'CHANGELOG.md'
10+
- 'ROADMAP.md'
11+
- 'docs/**'
712
pull_request:
13+
paths-ignore:
14+
- 'README.md'
15+
- 'CHANGELOG.md'
16+
- 'ROADMAP.md'
17+
- 'docs/**'
818

919
jobs:
1020
test:
@@ -19,4 +29,5 @@ jobs:
1929
- run: npm ci --ignore-scripts
2030
- run: npm audit
2131
- run: npm run build
32+
- run: npm run lint
2233
- run: npm test

.github/workflows/publish.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ jobs:
3838
working-directory: packages/test
3939
- run: npm publish --access public --provenance
4040
working-directory: packages/test
41-
- name: Create GitHub release
41+
- name: Create or update GitHub release
4242
run: |
4343
VERSION=${GITHUB_REF_NAME#v}
4444
sed -n "/^## \[$VERSION\]/,/^## \[/{ /^## \[$VERSION\]/p; /^## \[/!p; }" CHANGELOG.md > release-notes.md
45-
gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file release-notes.md
45+
if gh release view "$GITHUB_REF_NAME" &>/dev/null; then
46+
gh release edit "$GITHUB_REF_NAME" --notes-file release-notes.md
47+
else
48+
gh release create "$GITHUB_REF_NAME" --title "$GITHUB_REF_NAME" --notes-file release-notes.md
49+
fi
4650
env:
4751
GH_TOKEN: ${{ github.token }}

.gitignore

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,30 @@ test-results/
2020
.env.*
2121
*.log
2222

23+
# Hand-written declaration files — keep these
24+
!packages/*/src/playwright.d.ts
25+
2326
# TypeScript build artifacts emitted outside dist/
2427
packages/*/src/**/*.js
2528
packages/*/src/**/*.js.map
2629
packages/*/src/**/*.d.ts
2730
packages/*/src/**/*.d.ts.map
31+
packages/*/templates/**/*.js
32+
packages/*/templates/**/*.js.map
33+
packages/*/templates/**/*.d.ts
34+
packages/*/templates/**/*.d.ts.map
2835
e2e/**/*.js
2936
e2e/**/*.js.map
3037
e2e/**/*.d.ts
3138
e2e/**/*.d.ts.map
32-
33-
# Hand-written declaration files — keep these
34-
!packages/*/src/playwright.d.ts
35-
3639
scripts/**/*.js
3740
scripts/**/*.js.map
3841
scripts/**/*.d.ts
3942
scripts/**/*.d.ts.map
43+
tests/**/*.js
44+
tests/**/*.js.map
45+
tests/**/*.d.ts
46+
tests/**/*.d.ts.map
4047
examples/**/*.js
4148
examples/**/*.js.map
4249
examples/**/*.d.ts

CHANGELOG.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,75 @@
1+
## [0.0.38] (2026-05-17)
2+
* Fix(ios): call `getForegroundApp()` before `launchApp()` in mobilecli driver to ensure DeviceKit is running first, preventing a race where its startup minimizes the newly-launched app ([#89](https://github.com/mobile-next/mobilewright/issues/89))
3+
* Fix(android): using instruments to get view tree, solves bug when constant UI change would fail "uiautomator dump" (fix is in mobilecli 0.3.74)
4+
* General: skip redundant `mobilecli devices` shell-outs in `connect()` and `installApp()` when device type is already known, reducing test startup time by ~4s
5+
* General: break early if installApps points to non-zip containers, before allocating devices
6+
* General: added plenty of verbose logs when `DEBUG=mw:*`
7+
8+
## [0.0.37] (2026-05-16)
9+
* Feat: add installApps to per-project overrides ([#133](https://github.com/mobile-next/mobilewright/pull/133))
10+
* Feat: export HardwareButton from @mobilewright/core and add LOCK button ([#132](https://github.com/mobile-next/mobilewright/pull/132))
11+
* Fix: use Number.NaN and String.raw in tests ([#93](https://github.com/mobile-next/mobilewright/pull/93)), thanks to [@khanhdodang](https://github.com/khanhdodang)
12+
13+
## [0.0.36] (2026-05-16)
14+
* Feat: add toHaveCount and toBeEmpty assertions ([#122](https://github.com/mobile-next/mobilewright/pull/122)), thanks to [@alexC2K](https://github.com/alexC2K)
15+
* Feat: add device info annotations to test report ([#125](https://github.com/mobile-next/mobilewright/pull/125))
16+
* Feat(test): attach accessibility tree on test failure via saveTreeOnFailure ([#111](https://github.com/mobile-next/mobilewright/pull/111)), thanks to [@farhanlabib](https://github.com/farhanlabib)
17+
* Feat: add eslint with @typescript-eslint and @stylistic rules ([#127](https://github.com/mobile-next/mobilewright/pull/127))
18+
* Fix(driver): reject .ipa installs on iOS simulators with a clear error ([#74](https://github.com/mobile-next/mobilewright/pull/74)), thanks to [@krismuhi](https://github.com/krismuhi)
19+
* Fix: only catch LocatorError in expect assertions, rethrow unexpected errors ([#126](https://github.com/mobile-next/mobilewright/pull/126))
20+
* Fix: respect autoAppLaunch config option in test fixture ([#110](https://github.com/mobile-next/mobilewright/pull/110)), thanks to [@farhanlabib](https://github.com/farhanlabib)
21+
22+
## [0.0.35] (2026-05-12)
23+
* Fix(android): updated mobilecli to 0.3.73 to fix missing elements that had non-null resource-id ([#120](https://github.com/mobile-next/mobilewright/pull/120))
24+
25+
## [0.0.34] (2026-05-12)
26+
* Feat(locator): `locator.exists()` is now available — returns `true` if the element is present in the view tree
27+
* Fix: `--config` flag is now correctly honored in fixtures and device-pool setup ([#109](https://github.com/mobile-next/mobilewright/pull/109))
28+
* Fix(android): moved away from monkey to run apps, fixes apks compiled with 'test' flag
29+
30+
## [0.0.33] (2026-05-07)
31+
* Fix(android): warn and continue when foreground app check fails on launch instead of throwing error, thanks [@farhanlabib](https://github.com/farhanlabib) ([#102](https://github.com/mobile-next/mobilewright/pull/102))
32+
33+
## [0.0.32] (2026-05-05)
34+
* Fix: updated mobilecli to fix 'SYS_KEYS has no physical keys but with factor 2.0%' error on certain Android devices
35+
36+
## [0.0.31] (2026-05-04)
37+
* Feat: `screen.getByPlaceholder()` is now available ([#84](https://github.com/mobile-next/mobilewright/pull/84))
38+
* Feat: `launchApp()` now waits for the app to reach the foreground before continuing; pass `noWaitAfter: true` to skip ([#80](https://github.com/mobile-next/mobilewright/pull/80))
39+
* Feat: Add anonymous telemetry for `test`, `doctor`, and `init` commands - see README for opt-out ([#79](https://github.com/mobile-next/mobilewright/pull/79))
40+
* Feat: `init` example test template now includes a `device` param and doc comments ([#86](https://github.com/mobile-next/mobilewright/pull/86))
41+
* Fix: mobilewright --version now reads from `package.json` instead of the hardcoded `'0.0.1'` ([#78](https://github.com/mobile-next/mobilewright/pull/78))
42+
43+
## [0.0.30] (2026-05-01)
44+
* Fix(config): `loadConfig()` now uses `pathToFileURL` for dynamic import — fixes config not loading on Windows
45+
* Fix(doctor): Suggest `Microsoft.OpenJDK.17` instead of Azul Zulu for Windows JDK installs
46+
* Feat(test): `swipe` on a locator — e.g. swipe left on a list item
47+
* Docs: Added Windows instructions for enabling debug logs (`$env:DEBUG` / `set DEBUG`)
48+
49+
## [0.0.29] (2026-04-30)
50+
* General: mobilecli agent is automatically installed on simulators and emulators at connect time — no manual `mobilewright install` step needed
51+
* Fix(cli): `npx mobilewright init` now works correctly — templates were missing from the published dist
52+
* Fix(driver-mobilecli): Windows 11 is now supported — `win32-x64` resolves to `mobilecli-windows-amd64.exe`
53+
54+
## [0.0.28] (2026-04-29)
55+
* Fix(test): Stream cloud recordings to disk instead of loading into memory — safe for large video files
56+
* Fix(test): Video attachments now work with the cloud drivers
57+
* Fix(cli): Fixed HTML report branding so it now applies when the `html` reporter is configured
58+
59+
## [0.0.27] (2026-04-28)
60+
* General: New worker/device-pool architecture: workers acquire devices from a shared pool instead of each worker owning a dedicated device
61+
* General: Track installed apps per slot to skip re-install when the same worker reuses a device
62+
* General: Per-allocation timeouts via `AbortSignal`; pool shutdown drains waiters and releases all slots
63+
* General: Stack traces from `expect()` failures now omit mobilewright frames — set `MWDEBUGIMPL=1` to see them
64+
* General: Upgrade mobilecli to `0.3.67`
65+
* CLI: Add `--shard` option to the `test` command for multi-host sharding of tests
66+
* CLI: Add `mobilewright merge-reports` command, needed for sharding
67+
* Fix: Fix 'text' field from viewTree to fetch from dump's 'text' instead of 'label', thanks to [emor](https://github.com/emor)
68+
* Fix(allocator-factory): Throw on unknown driver type instead of silently falling back to mobile-use
69+
* Fix(driver-mobile-use): Only call `fleet.release` on disconnect when this instance owns the lease
70+
* Fix(device-pool): Re-queue waiters on `NoDeviceAvailableError`; treat `NaN` `--workers` as 1
71+
* Fix(rpc-client): Close WebSocket nicely with code 1000 and await the close handshake on `disconnect()`
72+
173
## [0.0.26] (2026-04-22)
274
* Fix(driver-mobile-use): Device allocation now correctly waits for provisioning to complete
375
* Fix(driver-mobile-use): `devices.list` response properly unwrapped from `{ devices: [...] }` envelope

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Framework for mobile device automation, inspired by Playwright's architecture an
88

99
**Mobilewright** targets iOS and Android devices, simulators, and emulators through a clean, auto-waiting API built on top of [mobilecli](https://github.com/mobile-next/mobilecli).
1010

11-
[Get Started](#quick-start) · [API Docs](#api-reference) · [Cloud (mobile-use.com)](https://mobile-use.com)
11+
[Get Started](#quick-start) · [API Docs](#api-reference) · [Roadmap](ROADMAP.md) · [Cloud (mobile-use.com)](https://mobile-use.com)
1212

1313
## Why Mobilewright?
1414

@@ -144,6 +144,7 @@ screen.getByText(/welcome/i) // RegExp match
144144
screen.getByText('welcome', { exact: false }) // substring match
145145
screen.getByType('TextField') // element type
146146
screen.getByRole('button', { name: 'Sign In' }) // semantic role + name filter
147+
screen.getByPlaceholder('Search...') // placeholder text
147148
```
148149

149150
**Direct actions:**
@@ -168,6 +169,8 @@ await locator.tap()
168169
await locator.doubleTap()
169170
await locator.longPress({ duration: 1000 })
170171
await locator.fill('hello@example.com') // tap to focus + type text
172+
await locator.swipe({ direction: 'left' }) // swipe on a specific element
173+
await locator.scrollIntoViewIfNeeded() // scroll until element is visible
171174
```
172175

173176
**Queries:**
@@ -218,7 +221,8 @@ await device.goto('myapp://settings');
218221
await device.openUrl('https://example.com');
219222

220223
// App lifecycle
221-
await device.launchApp('com.example.app', { locale: 'fr_FR' });
224+
await device.launchApp('com.example.app', { locale: 'fr_FR' }); // waits until app is in foreground
225+
await device.launchApp('com.example.app', { noWaitAfter: true }); // skip foreground wait
222226
await device.terminateApp('com.example.app');
223227
const apps = await device.listApps();
224228
const foreground = await device.getForegroundApp();
@@ -390,6 +394,16 @@ Need real phones in the cloud? [mobile-use.com](https://mobile-use.com) gives yo
390394

391395
mobile-use.com is the only device cloud with native Mobilewright support.
392396

397+
## Telemetry
398+
399+
Mobilewright collects anonymous usage telemetry via PostHog. To disable it, set the `MOBILEWRIGHT_DISABLE_TELEMETRY` environment variable:
400+
401+
```bash
402+
MOBILEWRIGHT_DISABLE_TELEMETRY=1 npx mobilewright test
403+
```
404+
405+
When telemetry is enabled, a random identifier is generated and stored in `~/.config/mobilenext/mobilewright/config.json`. No personal information or test data is ever collected.
406+
393407
## Contributing
394408

395409
```bash

0 commit comments

Comments
 (0)