Skip to content

feat(elements): Introduce @wdio/element package into the devtools project#215

Open
Winify wants to merge 9 commits into
webdriverio:mainfrom
Winify:feature/elements-snapshot
Open

feat(elements): Introduce @wdio/element package into the devtools project#215
Winify wants to merge 9 commits into
webdriverio:mainfrom
Winify:feature/elements-snapshot

Conversation

@Winify
Copy link
Copy Markdown

@Winify Winify commented May 31, 2026

Purpose

New package that extracts structured, AI-readable element trees from both browser pages and mobile apps.

What it does

getElements(browser, options) — unified API for both platforms. Returns { elements, tree } with a flat interactable element list and the raw element tree for snapshot serialization.

serializeWebSnapshot(tree, context?) — depth-indented text snapshot from a browser accessibility tree. Interactive elements render with selectors, structural elements provide hierarchy and context, and statictext captures visible text that has no interactivity.

serializeMobileSnapshot(tree, context) — same format for Android/iOS page-source XML. Full Appium/WDIO locator pipeline wired in. .instance(N) indexing for duplicate selectors.

Capabilities

Web Mobile
Semantic roles button, link, textbox, heading[2], img, statictext, … button, img, statictext, textbox, switch, list, …
Unique selectors CSS: #id, tag.class, tag*=Text, [aria-label="…"], CSS-path fallback Appium: ~content-desc, id:resource-id, android=new UiSelector()…, .instance(N)
Viewport filtering inViewportOnly: true (default) inViewportOnly: true (default)
Context disambiguation button "Wishlist" ∈ "The Housemaid" → … statictext "Google" ∈ "text_frame" → …
Duplicate dedup Identical statictext children suppressed .instance(N) suffix on repeated selectors
Tap-target promotion N/A (a11y tree already correct) Clickable parent container carries ; label children provide

Architecture

                    getElements(browser, opts)
                           │
          ┌────────────────┴────────────────┐
          ▼                                 ▼
   [Browser]                          [Mobile]
   browser.execute()                  browser.getPageSource()
   DOM → a11y tree                    XML → JSONElement tree
          │                                 │
          ▼                                 ▼
   getBrowserAccessibilityTree()      getMobileVisibleElementsWithTree()
   → AccessibilityNode[]              → { MobileElementInfo[], JSONElement }
          │                                 │
          ▼                                 ▼
   serializeWebSnapshot()             serializeMobileSnapshot()
   → depth-indented text              → depth-indented text

Snapshot Examples

mobile-snapshot--android-settings.txt
mobile-snapshot--apidemos.txt
web-snapshot--worldofbooks.txt

Winify added 9 commits May 31, 2026 18:23
- Migrates browser element detection, accessibility tree, and mobile element locator generation from the MCP project into a standalone, reusable package
- Adds package to pnpm-workspace.yaml and registers path aliases in the root tsconfig.json for IDE resolution.
- Fix linter
- Empty selector → trailing '→  ' in output, unusable by agents, guard added at top of the interactive branch: skip the node entirely
- Option added to filter elements that are not visible (or not in viewport)
- Introduce `statictext` role for visible text-bearing element (book titles, prices, promo copy) that otherwise have no a11y role (Suppress `statictext` children whose text is already included in the parent)
- Extend inferPurpose() to consider same-depth structural siblings (img, heading, statictext) as context, and render `∈ parent` for all named interactive elements
- Use local fallback `getBestAndroidLocator(attrs)` and `getBestIOSLocator(attrs)`
- Emit noisy mobile node roles from the snapshot
@Winify Winify requested a review from vishnuv688 May 31, 2026 19:32
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