feat(inspect): add --disable-animations flag to fix uiautomator dump on animated screens#118
feat(inspect): add --disable-animations flag to fix uiautomator dump on animated screens#118farhanlabib wants to merge 5 commits into
Conversation
…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.
…on animated screens uiautomator dump fails with "no XML content found" when a screen contains a continuously animated SurfaceView or TextureView that never settles (e.g. a ride-searching screen). The fix is to disable the three Android system animation scales via ADB before triggering the dump, then restore them. Changes: - device.disableAnimations() / enableAnimations() on the Device class - --disable-animations flag for `inspect` (terminal) and `inspect --ui` (browser) - animations are always restored in a finally block / on SIGINT
5585c73 to
fbf2f07
Compare
|
@farhanlabib thanks for another great fix! :). This should go in mobilecli and not mobilewright. So it works also for mobile-mcp and cloud providers using mobilecli and mobilewright on their backend. Mind to move the code there? also, I would do a get first, so we restore what was there, and not assume we need to enable animations at the end of the code. |
Thanks for the guidance! I'll move this to mobilecli and open a PR there. The plan:
|
…direct ADB Replaces execSync ADB calls with the new device.io.animation-scales.get/set RPC methods from mobile-next/mobilecli#230. This means the feature works for all mobilecli consumers (mobile-mcp, cloud providers, etc.) and not just when adb is available on the host running mobilewright. Changes: - AnimationScales type added to @mobilewright/protocol - getAnimationScales/setAnimationScales added to MobilewrightDriver interface - Implemented in driver-mobilecli and driver-mobile-use - Device.disableAnimations() now returns saved scales; enableAnimations() accepts them - inspect and inspect --ui save actual values on start and restore on finish
Done — refactored in the latest commit. The execSync ADB calls are gone. Instead:
This PR depends on mobile-next/mobilecli#230 landing first. |
Problem
npx mobilewright inspectfails with:This happens on screens that are continuously animated — a ride-searching page with a
SurfaceVieworTextureViewthat never settles. uiautomator's XML dump requires a stable layout so it always fails on these screens.Solution
Adds
--disable-animationsto theinspectcommand anddisableAnimations()enableAnimations()to theDeviceclass. These call two new RPC methods in mobilecli —device.io.animation-scales.getanddevice.io.animation-scales.set— to disable the three Android global animation scales before dumping and restore the original values afterward (GET first, so we never assume the scales were 1).Animations are always restored — in a
finallyblock for the terminal command, onSIGINTfor the browser UI, and in afinallyblock in tests.Dependencies
Changes
AnimationScalestype added to@mobilewright/protocolgetAnimationScales()setAnimationScales()added to theMobilewrightDriverinterface, implemented indriver-mobileclianddriver-mobile-useDevice.disableAnimations()— saves current scales, sets all to 0, returns saved scalesDevice.enableAnimations(saved)— restores to the saved scales (defaults to 1 if none passed)--disable-animationsflag oninspect(terminal tree dump)--disable-animationsflag oninspect --ui(browser UI — disabled on start, restored on Ctrl+C)Usage
In tests:
Tested
Built the mobilecli binary from mobile-next/mobilecli#230 locally, swapped it into
node_modules, and confirmeddevice.io.animation-scales.get/setworks end-to-end on a live Android device with a continuously animated ride-searching screen.