Skip to content

feat(cli): add --ui flag to inspect command for browser-based tree explorer#113

Open
farhanlabib wants to merge 3 commits into
mobile-next:mainfrom
farhanlabib:feat/inspect-ui
Open

feat(cli): add --ui flag to inspect command for browser-based tree explorer#113
farhanlabib wants to merge 3 commits into
mobile-next:mainfrom
farhanlabib:feat/inspect-ui

Conversation

@farhanlabib
Copy link
Copy Markdown
Contributor

@farhanlabib farhanlabib commented May 11, 2026

Depends on

#112 — adds the inspect command this builds on top of.

Motivation

The terminal tree from inspect is useful for quick lookups but hard to navigate on complex screens. A screen with 100+ nodes becomes a long flat list — you scroll, lose your place, and still have to manually type out the locator.

viewTree() inside a test has the same problem: it dumps a JSON blob to the console with no structure, no expand/collapse, and no way to copy a locator directly.

The --ui flag replaces that workflow with a browser panel that stays live as you use the app.

What changed

Added --ui flag to the inspect command (packages/mobilewright/src/commands/inspect-ui.ts):

npx mobilewright inspect --ui
┌─────────────────────────────────────────────────────────────────────┐
│ mobilewright inspect        [ ] Auto-refresh  [2s ▾]  [Refresh]     │
├───────────────────────────────────┬─────────────────────────────────┤
│ ▾ FrameLayout              visible│ LinearLayout                    │
│   ▾ RecyclerView           visible│ ─────────────────────────────   │
│     ▾ LinearLayout  ●      visible│ label      "Bike"               │
│         TextView  "Bike"  visible │ text       "Bike"               │
│     ▾ LinearLayout         visible│ visible    true                 │
│         TextView  "Car"   visible │ bounds     x:0 y:320 120×80     │
│   BottomNavigationView     visible│                                 │
│                                   │ LOCATORS                        │
│                                   │ screen.getByLabel("Bike") [Copy]│
│                                   │ screen.getByText("Bike")  [Copy]│
└───────────────────────────────────┴─────────────────────────────────┘

Left panel — collapsible accessibility tree. Click to expand a node, click the node itself to select it.

Right panel — properties of the selected node (type, label, text, bounds, visibility) and ready-to-use locator suggestions with a one-click Copy button.

Auto-refresh — toggle on to poll the device on a configurable interval (1s / 2s / 5s / 10s) so the tree updates live as you navigate the app. A manual Refresh button is always available when auto-refresh is off.

The server keeps a persistent WebSocket connection to mobilecli with automatic reconnect on error, so switching between screens stays fast.

Test plan

  • Run npx mobilewright inspect --ui — browser opens at localhost:9325, tree renders
  • Click on a node with children — expands; click — collapses
  • Click a node — right panel shows its properties and locator suggestions
  • Click Copy next to a locator — clipboard contains the correct screen.getBy*() call
  • Toggle Auto-refresh on at 2s — tree refreshes every 2s; navigate to a new screen and confirm tree updates
  • Toggle Auto-refresh off — polling stops; click Refresh manually — tree updates once
  • Change interval while auto-refresh is on — new interval takes effect immediately

No regression

  • Run npx mobilewright inspect (no flags) — terminal output unchanged
  • Run npx mobilewright inspect --json — JSON output unchanged

…ailure

Screenshots show what the screen looks like when a test fails, but not
why a locator didn't match. The accessibility tree carries that context —
element labels, types, visibility flags, and bounds — which is exactly
what you need to debug a failing getBy* call.

Add saveTreeOnFailure: boolean to MobilewrightConfig. When enabled, the
screen fixture calls viewTree() after a failure and attaches the result
as view-tree-on-failure (JSON) to the HTML report, next to the existing
screenshot. Opt-in, defaults to false, no impact on existing projects.
When writing tests, the main friction is not knowing the exact label,
text, or type of an element on screen. The only option was to add
screen.viewTree() inside a test and read the console output — which
requires running a test just to inspect the UI.

The inspect command solves this directly: run it with the app open on
the screen you want to target, and it prints the full accessibility tree
in the terminal with element types, labels, text, and visibility — no
test needed.

  npx mobilewright inspect

Supports --json to output raw ViewNode[] for piping to jq or saving as
a snapshot to diff between two app states:

  npx mobilewright inspect --json | jq '.[] | select(.label != null)'

Respects deviceName from config for automatic device resolution, and
accepts -d/--device to target a specific device when multiple are connected.
…plorer

The terminal tree from inspect is useful for quick lookups but hard to
navigate on complex screens with deep hierarchies. When a screen has
100+ nodes, scrolling through a flat terminal dump to find the right
element is slow.

The --ui flag opens a browser at localhost:9325 with a two-panel UI:
the left panel shows the collapsible accessibility tree, the right panel
shows the selected node's properties and ready-to-use locator code that
can be copied to the clipboard with one click.

Auto-refresh polls the device on a configurable interval (1s/2s/5s/10s)
so the tree stays live as you navigate the app — no need to re-run the
command for each screen. A manual Refresh button is always available when
auto-refresh is off.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant