Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions data/runs.json
Original file line number Diff line number Diff line change
Expand Up @@ -674,5 +674,45 @@
"verbatim": true,
"exit": 0,
"output": "the Download folder holds 1 file\n mobium-report.txt 44 bytes 2026-09-29 03:41"
},
"app_press[2]": {
"tool": "app_press",
"index": 2,
"command": "mobium press dpad-down",
"verbatim": true,
"exit": 0,
"output": "pressed dpad-down — focus moved to homepage_container"
},
"app_press[3]": {
"tool": "app_press",
"index": 3,
"command": "mobium press back --gesture",
"verbatim": true,
"exit": 0,
"output": "swiped back from the left edge, halfway down — com.android.settings is still in the foreground; app_map shows which screen"
},
"app_upload[1]": {
"tool": "app_upload",
"index": 1,
"command": "mobium upload ./seed --device-path /sdcard/seed",
"verbatim": true,
"exit": 0,
"output": "uploaded …/seed to /sdcard/seed (a folder of 2 files, 8 bytes) — confirmed by each of its 2 files' sizes read back on the device"
},
"app_download[2]": {
"tool": "app_download",
"index": 2,
"command": "mobium download --device-path /sdcard/seed -o seed-copy",
"verbatim": true,
"exit": 0,
"output": "downloaded seed from /sdcard/seed to …/seed-copy (a folder of 2 files, 8 bytes) — confirmed by each of its 2 files' sizes read back against the device's"
},
"app_fill[1]": {
"tool": "app_fill",
"index": 1,
"command": "mobium fill label=Volume 0.3",
"verbatim": true,
"exit": 0,
"output": "moved label=Volume to position 0.3 — it reads \"3.0\", was \"5.0\""
}
}
39 changes: 39 additions & 0 deletions examples/canonical.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,14 @@
"title": "List what the folder holds",
"cli": "mobium download",
"args": {}
},
{
"title": "Bring back a folder from a path on the device",
"cli": "mobium download --device-path /sdcard/seed -o seed-copy",
"args": {
"device_path": "/sdcard/seed",
"path": "seed-copy"
}
}
],
"app_drag": [
Expand Down Expand Up @@ -259,6 +267,14 @@
"target": "testid=search",
"text": "coffee"
}
},
{
"title": "Move a slider to a position",
"cli": "mobium fill label=Volume 0.3",
"args": {
"target": "label=Volume",
"text": "0.3"
}
}
],
"app_find": [
Expand Down Expand Up @@ -468,6 +484,21 @@
"args": {
"button": "home"
}
},
{
"title": "Move focus with a TV remote's D-pad",
"cli": "mobium press dpad-down",
"args": {
"button": "dpad-down"
}
},
{
"title": "Go back with a swipe in from the edge",
"cli": "mobium press back --gesture",
"args": {
"button": "back",
"gesture": true
}
}
],
"app_press_drag": [
Expand Down Expand Up @@ -763,6 +794,14 @@
"args": {
"path": "invoice-42.txt"
}
},
{
"title": "Send a folder to a path on the device",
"cli": "mobium upload ./seed --device-path /sdcard/seed",
"args": {
"path": "./seed",
"device_path": "/sdcard/seed"
}
}
],
"app_wait_for": [
Expand Down
15 changes: 15 additions & 0 deletions examples/dotnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
},
{
"code": "foreach (var f in device.Downloads())\n{\n Console.WriteLine($\"{f[\"name\"]} {f[\"bytes\"]}\");\n}"
},
{
"code": "var got = device.PullPath(\"/sdcard/seed\", \"seed-copy\");\nConsole.WriteLine($\"{got[\"files\"]} {got[\"path\"]}\");"
}
],
"app_drag": [
Expand All @@ -135,6 +138,9 @@
"app_fill": [
{
"code": "device.Fill(\"testid=search\", \"coffee\");"
},
{
"code": "device.Fill(\"label=Volume\", \"0.3\"); // a slider: its position, from 0 to 1"
}
],
"app_find": [
Expand Down Expand Up @@ -241,6 +247,12 @@
},
{
"code": "device.Press(\"home\");"
},
{
"code": "device.Press(\"dpad-down\");"
},
{
"code": "var went = device.Back(gesture: true);\nConsole.WriteLine($\"{went[\"foreground\"]} {went[\"confirmed\"]}\");"
}
],
"app_press_drag": [
Expand Down Expand Up @@ -393,6 +405,9 @@
"app_upload": [
{
"code": "var sent = device.Upload(\"invoice-42.txt\");\nConsole.WriteLine($\"{sent[\"where\"]} {sent[\"bytes\"]}\");"
},
{
"code": "var sent = device.PushPath(\"seed\", \"/sdcard/seed\");\nConsole.WriteLine($\"{sent[\"files\"]} {sent[\"checked\"]}\");"
}
],
"app_wait_for": [
Expand Down
15 changes: 15 additions & 0 deletions examples/go.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
},
{
"code": "files, err := dev.Downloads(ctx, \"\")\nif err != nil {\n\treturn err\n}\nfor _, f := range files {\n\tfmt.Println(f.Name, f.Bytes)\n}"
},
{
"code": "got, err := dev.PullPath(ctx, \"/sdcard/seed\", \"seed-copy\", \"\")\nif err != nil {\n\treturn err\n}\nfmt.Println(got.Files, got.Path)"
}
],
"app_drag": [
Expand All @@ -135,6 +138,9 @@
"app_fill": [
{
"code": "if err := dev.Fill(ctx, \"testid=search\", \"coffee\"); err != nil {\n\treturn err\n}"
},
{
"code": "// A slider: its position, from 0 to 1.\nif err := dev.Fill(ctx, \"label=Volume\", \"0.3\"); err != nil {\n\treturn err\n}"
}
],
"app_find": [
Expand Down Expand Up @@ -241,6 +247,12 @@
},
{
"code": "if err := dev.Press(ctx, \"home\"); err != nil {\n\treturn err\n}"
},
{
"code": "if err := dev.Press(ctx, \"dpad-down\"); err != nil {\n\treturn err\n}"
},
{
"code": "went, err := dev.Back(ctx, true)\nif err != nil {\n\treturn err\n}\nfmt.Println(went.Foreground, went.Confirmed)"
}
],
"app_press_drag": [
Expand Down Expand Up @@ -393,6 +405,9 @@
"app_upload": [
{
"code": "sent, err := dev.Upload(ctx, \"invoice-42.txt\", nil)\nif err != nil {\n\treturn err\n}\nfmt.Println(sent.Where, sent.Bytes, sent.Checked)"
},
{
"code": "sent, err := dev.PushPath(ctx, \"seed\", \"/sdcard/seed\", \"\")\nif err != nil {\n\treturn err\n}\nfmt.Println(sent.Files, sent.Checked)"
}
],
"app_wait_for": [
Expand Down
15 changes: 15 additions & 0 deletions examples/java.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
},
{
"code": "for (Map<String, Object> f : device.downloads()) {\n System.out.println(f.get(\"name\") + \" \" + f.get(\"bytes\"));\n}"
},
{
"code": "Map<String, Object> got = device.pullPath(\"/sdcard/seed\", \"seed-copy\");\nSystem.out.println(got.get(\"files\") + \" \" + got.get(\"path\"));"
}
],
"app_drag": [
Expand All @@ -135,6 +138,9 @@
"app_fill": [
{
"code": "device.fill(\"testid=search\", \"coffee\");"
},
{
"code": "device.fill(\"label=Volume\", \"0.3\"); // a slider: its position, from 0 to 1"
}
],
"app_find": [
Expand Down Expand Up @@ -241,6 +247,12 @@
},
{
"code": "device.press(\"home\");"
},
{
"code": "device.press(\"dpad-down\");"
},
{
"code": "Map<String, Object> went = device.back(true);\nSystem.out.println(went.get(\"foreground\") + \" \" + went.get(\"confirmed\"));"
}
],
"app_press_drag": [
Expand Down Expand Up @@ -393,6 +405,9 @@
"app_upload": [
{
"code": "Map<String, Object> sent = device.upload(\"invoice-42.txt\");\nSystem.out.println(sent.get(\"where\") + \" \" + sent.get(\"bytes\"));"
},
{
"code": "Map<String, Object> sent = device.pushPath(\"seed\", \"/sdcard/seed\");\nSystem.out.println(sent.get(\"files\") + \" \" + sent.get(\"checked\"));"
}
],
"app_wait_for": [
Expand Down
15 changes: 15 additions & 0 deletions examples/javascript.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
},
{
"code": "for (const f of await device.downloads()) {\n console.log(f.name, f.bytes)\n}"
},
{
"code": "const got = await device.pullPath('/sdcard/seed', { path: 'seed-copy' })\nconsole.log(got.files, got.path)"
}
],
"app_drag": [
Expand All @@ -135,6 +138,9 @@
"app_fill": [
{
"code": "await device.fill('testid=search', 'coffee')"
},
{
"code": "await device.fill('label=Volume', '0.3') // a slider: its position, from 0 to 1"
}
],
"app_find": [
Expand Down Expand Up @@ -241,6 +247,12 @@
},
{
"code": "await device.press('home')"
},
{
"code": "await device.press('dpad-down')"
},
{
"code": "const went = await device.back({ gesture: true })\nconsole.log(went.foreground, went.confirmed)"
}
],
"app_press_drag": [
Expand Down Expand Up @@ -393,6 +405,9 @@
"app_upload": [
{
"code": "const sent = await device.upload('invoice-42.txt')\nconsole.log(sent.where, sent.bytes, sent.checked)"
},
{
"code": "const sent = await device.pushPath('seed', '/sdcard/seed')\nconsole.log(sent.files, sent.checked)"
}
],
"app_wait_for": [
Expand Down
15 changes: 15 additions & 0 deletions examples/python.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@
},
{
"code": "for f in device.downloads():\n print(f[\"name\"], f[\"bytes\"])"
},
{
"code": "got = device.pull_path(\"/sdcard/seed\", path=\"seed-copy\")\nprint(got[\"files\"], got[\"path\"])"
}
],
"app_drag": [
Expand All @@ -135,6 +138,9 @@
"app_fill": [
{
"code": "device.fill(\"testid=search\", \"coffee\")"
},
{
"code": "device.fill(\"label=Volume\", \"0.3\") # a slider: its position, from 0 to 1"
}
],
"app_find": [
Expand Down Expand Up @@ -241,6 +247,12 @@
},
{
"code": "device.press(\"home\")"
},
{
"code": "device.press(\"dpad-down\")"
},
{
"code": "went = device.back(gesture=True)\nprint(went[\"foreground\"], went[\"confirmed\"])"
}
],
"app_press_drag": [
Expand Down Expand Up @@ -393,6 +405,9 @@
"app_upload": [
{
"code": "sent = device.upload(\"invoice-42.txt\")\nprint(sent[\"where\"], sent[\"bytes\"], sent[\"checked\"])"
},
{
"code": "sent = device.push_path(\"seed\", \"/sdcard/seed\")\nprint(sent[\"files\"], sent[\"checked\"])"
}
],
"app_wait_for": [
Expand Down
17 changes: 13 additions & 4 deletions scripts/capture.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Emulators only. It changes settings — appearance, orientation, locale,
timezone, the clipboard — and puts each back, but it is not for a phone.

python3 scripts/capture.py --bin ./mobium --device emulator-5554 [--only app_tap]
python3 scripts/capture.py --bin ./mobium --device emulator-5554 [--only app_tap] [--only 'app_press[2]']
"""

import argparse
Expand Down Expand Up @@ -113,7 +113,7 @@ def app_screen(name):
pause=3.0, restore=[f"reset-permissions {APP}"]),
dict(tool="app_location", i=1),
# The Clock app's big digits, not Settings' Date & time: there the zone
# and the time are grey text, and the two pictures looked the same.
# and the time are gray text, and the two pictures looked the same.
dict(tool="app_timezone", i=0,
setup=["terminate com.google.android.deskclock", "launch com.google.android.deskclock", "tap testid=tab_menu_clock",
"wait 'label=Add city'"],
Expand Down Expand Up @@ -219,6 +219,13 @@ def app_screen(name):
restore=["$adb shell rm -f /sdcard/Download/mobium-report.txt",
"$adb shell content delete --uri content://media/external/downloads "
"--where \"\\\"_display_name='mobium-report.txt'\\\"\""]),
# Since 2026-10-05: the D-pad and an edge-swipe back, a folder to and from a
# device path, and a slider. Output only: each page already has its picture.
dict(tool="app_press", i=2, setup=settings_root()),
dict(tool="app_press", i=3, setup=settings_root() + ["tap 'text=Network & internet'", "wait text=Internet"]),
dict(tool="app_upload", i=1, setup=["$mkdir -p seed && printf 'one\\n' > seed/a.txt && printf 'two\\n' > seed/b.txt"]),
dict(tool="app_download", i=2, setup=["$rm -rf seed-copy"], restore=["$adb shell rm -rf /sdcard/seed"]),
dict(tool="app_fill", i=1, setup=app_screen("Slider Demo")),
dict(tool="app_session", i=0),
dict(tool="app_session", i=1),
]
Expand Down Expand Up @@ -262,9 +269,11 @@ def save(png, name):
timezone = json.loads(tz).get("timezone", "") if tz.strip().startswith("{") else ""
for p in PLAN:
tool, i = p["tool"], p["i"]
if a.only and tool not in a.only:
continue
key = f"{tool}[{i}]" if i is not None else f"{tool}:{p['cmd']}"
# --only takes a tool (every run of it) or one run's key, app_press[2],
# so adding a scenario does not re-take the pictures beside it.
if a.only and tool not in a.only and key not in a.only:
continue
def steps(ss):
for s in ss:
if s.startswith("$"):
Expand Down
Loading