Skip to content

Add snapshot options, browser_dom_query, and unit test coverage - #4

Merged
etairl merged 3 commits into
etairl:mainfrom
BryceBarbara:feat/snapshot-options-dom-query
May 31, 2026
Merged

Add snapshot options, browser_dom_query, and unit test coverage#4
etairl merged 3 commits into
etairl:mainfrom
BryceBarbara:feat/snapshot-options-dom-query

Conversation

@BryceBarbara

@BryceBarbara BryceBarbara commented May 27, 2026

Copy link
Copy Markdown
Contributor

Summary

  • extractPageSnapshot now accepts maxDepth, maxChildren, and selector options; browser_snapshot and browser_get_page_structure expose these as optional inputs via snapshotSchema
  • PageSnapshotNode replaces the role/name fields with a generic attributes map; hiddenChildCount and hiddenAttrCount signal truncation to callers
  • formatNode (used by formatPageStructure) updated accordingly: attributes are now rendered as key="value" for every entry in the map, with a trailing […N more attrs] token when the cap is hit and a […N more children] line appended when child nodes were omitted — previously only role and name were surfaced
  • generateLocatorCandidates removes the .first() call so the evaluate callback runs against all matching elements rather than only the first
  • New browser_dom_query tool returns element presence, count, and state (visible, enabled, checked, value) without waiting — useful for conditional logic without implicit timeouts
  • buildNode is now unit-tested by having the page.evaluate mock call the serialised callback directly in Node.js with a vi.stubGlobal document, covering SKIP_TAGS filtering, depth/child capping, attribute capping and priority ordering, text truncation, whitespace normalisation, innerText fallback, and selector scoping

Test plan

All 41 tests pass (pnpm test). Manual testing of browser_snapshot params and browser_dom_query behaviour confirmed locally.

- extractPageSnapshot accepts maxDepth/maxChildren/selector; snapshot tools expose them
- PageSnapshotNode uses attributes map + hiddenChildCount/hiddenAttrCount instead of role/name
- New browser_dom_query returns element presence, count, and state without waiting
- buildNode unit-tested by calling the page.evaluate callback in Node.js with a stubbed document
@BryceBarbara

Copy link
Copy Markdown
Contributor Author

@etairl Happy to make any changes needed or remove anything that isn't wanted.

@etairl etairl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The big one: removing .first() from generateLocatorCandidates is a regression, not an upgrade. Playwright's Locator.evaluate runs in strict mode and throws on multi-match — for "all elements" you'd need evaluateAll. The unit test passes because the mock doesn't enforce strict mode, but browser_generate_locator exists specifically to disambiguate broad selectors like button or .btn, which will now throw instead of picking the first match. Please restore .first().

Otherwise: top-level node truncation when no selector is set silently drops children without reporting hiddenChildCount (worth fixing while you're in there), and extractPageSnapshot does await evaluate() then await page.title() sequentially — Promise.all them. The buildNode test infra and the attribute-priority/cap work are great; happy to merge once the .first() thing is sorted.

Bryce Barbara added 2 commits May 28, 2026 10:20
- Capture url inside page.evaluate so it's atomic with title/tree
- Hard cap total nodes at 500 with hiddenByNodeCap reporting
- Replace hiddenChildCount with hiddenByDepth and hiddenByCount so
  formatted output tells the caller which param to increase
@BryceBarbara

Copy link
Copy Markdown
Contributor Author

Addressed the .first() regression and tried to look for other concerns in the changes.

@BryceBarbara
BryceBarbara requested a review from etairl May 28, 2026 18:18

@etairl etairl left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nailed it — and the URL race catch plus the 500-node cap and the split hidden-reason hints are real improvements I didn't ask for. Merging.

@etairl
etairl merged commit 313aff6 into etairl:main May 31, 2026
3 checks passed
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.

2 participants