Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
c3f8293
Fix keyboard detection returning wrong bounds on Android 13+
omnarayan Mar 9, 2026
d46e40f
feat: add REST API server for remote step execution via JSON
prabhash-nw Mar 9, 2026
ee2b59d
Fix keyboard detection on SDK 30 by using touchable region on all ver…
omnarayan Mar 9, 2026
dec9d6e
Fix keyboard detection across Android versions and vendor keyboards
omnarayan Mar 9, 2026
2e9ac37
test: improve test reliability and reduce flakiness
prabhash-nw Mar 9, 2026
a4a8db9
feat: add sleep step, hideKeyboard multi-strategy, and keyboard detec…
prabhash-nw Mar 9, 2026
9c5a796
feat: add isKeyboardVisible query, hideKeyboard strategy field, and c…
prabhash-nw Mar 9, 2026
00c09fa
feat: add Python client library for maestro-runner REST API
prabhash-nw Mar 9, 2026
d0a60be
feat: add TypeScript client library for maestro-runner REST API
prabhash-nw Mar 9, 2026
99acff4
chore(typescript): add ESLint config, enforce type-only imports, add …
prabhash-nw Mar 9, 2026
b320fe2
feat(python): add pytest-xdist parallel support and contact persisten…
prabhash-nw Mar 9, 2026
82f2d67
Add WebView CDP lifecycle management with visibility gating and timeo…
omnarayan Mar 9, 2026
0b98c2e
feat(clients): add parallel worker support, test reporters, and conta…
prabhash-nw Mar 9, 2026
41569fb
test(python): add None assertion for ElementInfo.from_dict partial co…
prabhash-nw Mar 9, 2026
3378da1
Fix Flutter reconnection to skip retries for non-Flutter apps
omnarayan Mar 9, 2026
7f2504d
Export CDP JS helper for WebView injection
omnarayan Mar 9, 2026
4ec8a91
Add ADB forwarding methods for CDP WebView connections
omnarayan Mar 9, 2026
ae38188
Add Element interface to abstract native and web elements
omnarayan Mar 9, 2026
9647cb6
Refactor DeviceLab commands to use Element interface and wire WebView…
omnarayan Mar 9, 2026
e2c461c
Add DeviceLab driver sources for Android and iOS
omnarayan Mar 9, 2026
3519cc7
chore(python): add ruff+mypy lint config, fix all violations, add DEV…
prabhash-nw Mar 10, 2026
41bfb29
docs(skills): update SKILL.md files with Anthropic guide best practices
prabhash-nw Mar 10, 2026
1de6fa9
Merge branch 'main' of https://github.com/devicelab-dev/maestro-runner
prabhash-nw Mar 10, 2026
4d6ed48
fix: test determinism and add merge-upstream skill
prabhash-nw Mar 11, 2026
5bd5ae0
chore(testing): update TS test split and refresh Python/TS test-runne…
prabhash-nw Mar 11, 2026
adfcfbe
test(go): harden emulator tests and add go-test-runner skill
prabhash-nw Mar 11, 2026
a311279
Add Appium-style worker-aware server traces for Python and TS tests
prabhash-nw Mar 11, 2026
c18050d
Merge upstream/main into main
prabhash-nw Mar 11, 2026
ef98d25
fix(input): harden keyboard focus retries and untrack server log
prabhash-nw Mar 11, 2026
c90b477
Complete Python logging hardening metadata and artifact summaries
prabhash-nw Mar 11, 2026
81feee5
Add TypeScript node-aware run logs and artifact summaries
prabhash-nw Mar 11, 2026
3df1fe5
test(e2e): rename add_contact flow to add_contact_android
prabhash-nw Mar 11, 2026
d5f428f
ci(hooks): add repository git hooks
prabhash-nw Mar 11, 2026
471c434
docs(contributing): document git hooks
prabhash-nw Mar 11, 2026
4d2e067
test(clients): add iOS contact test coverage and diagnostics hardening
prabhash-nw Mar 12, 2026
2f5a895
test(typescript): separate unit and device test suites
prabhash-nw Mar 12, 2026
e4fcdb6
chore(hooks): print message when there is nothing to push
prabhash-nw Mar 12, 2026
32cb9e6
chore: add post-merge client validation workflow
prabhash-nw Mar 12, 2026
1f039e4
feat: add configurable sleepMs/threshold to waitForAnimationToEnd
prabhash-nw Mar 13, 2026
48c432a
chore(skills): add git-commit skill and improve all existing skills
prabhash-nw Mar 13, 2026
84f16e5
Merge remote-tracking branch 'upstream/main'
prabhash-nw Mar 16, 2026
fec8636
ci(workflows): add unit test jobs and Android e2e workflow
prabhash-nw Mar 17, 2026
c289ba1
Merge pull request #1 from prabhash-nw/ci/github-actions-unit-e2e-and…
prabhash-nw Mar 17, 2026
730aa30
Merge remote-tracking branch 'origin/main'
prabhash-nw Mar 17, 2026
0745948
Merge upstream/main (v1.1.0): WebView CDP, evalWebViewScript, swipe f…
prabhash-nw Apr 2, 2026
4510cbc
Merge upstream/main into main
prabhash-nw Apr 8, 2026
df67c4c
Merge remote-tracking branch 'upstream/main'
prabhash-nw Apr 14, 2026
caa5653
chore(copilot): add copilot instructions to use rtk for shell commands
prabhash-nw Apr 14, 2026
141413b
chore(skills): migrate .github contents to repo root directory
pr4bh4sh May 11, 2026
469ed10
Merge upstream/main into main
pr4bh4sh Aug 23, 2026
474a4be
fix: align uiautomator2 keyboard handling and step tags post-merge
pr4bh4sh Aug 23, 2026
f63f51d
fix(animation): fail waitForAnimationToEnd on timeout across drivers
pr4bh4sh Aug 23, 2026
b97f263
fix(test): reuse conftest session in e2e android test
pr4bh4sh Aug 23, 2026
729a796
fix(test): unpipe server streams before closing log in TS teardown
pr4bh4sh Aug 23, 2026
0e1242d
chore(skills): track agent skills and add shared device-integration-t…
pr4bh4sh Aug 23, 2026
0ddbe47
chore(ci): relocate workflows to .github/workflows
pr4bh4sh Aug 23, 2026
532de90
chore(ci): add animation tests to E2E Android workflow
pr4bh4sh Aug 23, 2026
17311d6
test(animation): make never-ends tests hermetic so CI can guard the t…
pr4bh4sh Aug 23, 2026
2687297
test(animation): use camera preview as the infinite animation source
pr4bh4sh Aug 23, 2026
afa617c
Merge remote-tracking branch 'upstream/main'
pr4bh4sh Aug 27, 2026
5ba3981
docs(clients): document TypeScript and Python clients with tutorials
pr4bh4sh Aug 29, 2026
d655776
Merge upstream/main into main
pr4bh4sh Aug 29, 2026
bb6b96a
feat(clients): expand typed bindings with gesture, media, device and …
pr4bh4sh Aug 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .claude/skills/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Eval workspaces — local eval run artifacts, not part of the skills
*-workspace/
evals/
96 changes: 96 additions & 0 deletions .claude/skills/device-integration-testing/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Skill: device-integration-testing

# Device Integration Testing — shared harness guidance

Common pitfalls and error-handling for **any** maestro-runner integration
test that drives a real device/emulator (Python `conftest.py`, TypeScript
`setup.ts`, or the `maestro-runner test` YAML runner). Both the
`python-test-runner` and `typescript-test-runner` skills reuse this; keep the
duplicated knowledge HERE, not in each runner.

## The single-session device lock (uiautomator2)

The uiautomator2 driver locks the device **per server process**. On session
creation it writes a host-side guard:

- `/tmp/uia2-<serial>.sock` — Unix socket forward
- `/tmp/uia2-<serial>.pid` — owning process PID

`IsOwnerAlive()` returns true (→ "device … already in use") when that PID
file exists **and** the process is still alive. Because of this, **only one
session may be active against a device at a time** within a single server.

Consequences / rules:
- Don't open a *second* session in a test that already has one. The shared
harness fixtures already open one per test process:
- Python: the autouse `_track_client` → `client` fixture (session-scoped).
- TypeScript: `getClient()` in `setup.ts` (shared `MaestroClient`).
- If a test needs raw HTTP access, **reuse the existing session id**
(`client.session_id` / `client.sessionId`) instead of `POST /session`.
- Teardown of the session belongs to the shared fixture — tests must not
delete the session themselves.

## Clean slate between runs

Before starting a fresh server/run, clear any stale guard left by a crashed
or killed previous run:

```sh
# Kill whatever holds the server port (do NOT use `pkill -f maestro-runner`, see below)
lsof -ti tcp:9999 2>/dev/null | xargs -r kill -9

# Remove BOTH guard files — a leftover .pid pointing at a reused/alive PID
# trips IsOwnerAlive and fails session creation even with no server running.
rm -f /tmp/uia2-<serial>.sock /tmp/uia2-<serial>.pid

# Clear any adb forward leaked by the previous run
adb -s <serial> forward --remove-all
```

> **`pkill -f maestro-runner` is a trap.** The pattern matches the *shell*
> running the command (its argv contains "maestro-runner"), so it can kill its
> own shell and orphan the backgrounded server. Always kill **by port**
> (`lsof -ti tcp:<port> | xargs kill`) instead.

## Server auto-start

Both harnesses auto-start the maestro-runner server when none is reachable
(`MAESTRO_SERVER_URL`), so you usually **don't** start one by hand:

- Python: `maestro_server` session fixture.
- TypeScript: `ensureServer()` in `setup.ts`.

If you do start a server manually, give it a unique port and don't also let
the harness start a second one — two servers on the same port conflict.

## Emulator must be attached

```sh
adb devices # expect "<serial> device" (e.g. emulator-5554)
```

## Teardown stream race (child subprocess logs)

When the harness pipes a child server's stdout/stderr into a `WriteStream`
log file, **unpipe the child streams before ending the log stream**.
Killing the child and then immediately `stream.end()` lets the dying process
flush final output into an already-closed stream → `write after end` crash
*after tests passed*. Fix:

```ts
child.stdout?.unpipe(logStream);
child.stderr?.unpipe(logStream);
child.kill();
// …then later…
logStream.end();
```

## Quick diagnostic checklist

| Symptom | Cause | Fix |
|---------|-------|-----|
| `device … already in use` | Second session, or stale `.pid` guard | Reuse shared session; clear `/tmp/uia2-*` guard files |
| `Connection refused` | No server up | Let harness auto-start, or start one on a free port |
| Server crashes/orphaned | `pkill -f maestro-runner` killed its own shell | Kill by port instead |
| Hang at session create | Stale `.pid` with alive (reused) PID | `rm -f /tmp/uia2-<serial>.sock /tmp/uia2-<serial>.pid` |
| `write after end` at exit | Child log stream closed before child flushed | Unpipe child stdout/stderr before `stream.end()` |
Loading