fix(screenDom): prioritize known app roots and skip empty containers#223
Merged
Conversation
Resolve the screenDom container in priority order: user-configured rootSelector → #root / #app / app-root → first non-empty body child → document.body. Emit a one-time console warning when falling back to the heuristic so users discover the new rootSelector option. Unblocks sandbox environments (CodeSandbox, extensions) that inject overlay siblings before the app root and silently hijack screenDom queries. Adds rootSelector?: string to InitTWDOptions. No new public exports, no version bump — ships under the existing 1.7.2 entry. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
screenDomquery scoping robust against injected body siblings (sandbox overlays, browser extensions) that currently silently hijack queries by landing before the app root in DOM order.rootSelector→#root/#app/app-root→ first non-empty direct body child →document.body.rootSelector?: stringoption onInitTWDOptions, wired throughinitTWDto a package-internal setter (no new public exports fromtwd-js).console.warnwhen the heuristic fallback fires without a configuredrootSelector, pointing users to the new option.Motivation
Reproduced on CodeSandbox Devbox: CodeSandbox injects
<div id=\"highlighter\">before<div id=\"root\">for its click-to-inspect overlay, and everyscreenDom.getByText(...)silently fails with "element not found" because the (empty) highlighter became the scoped container. Any browser extension or framework overlay that injects a body sibling has the same effect. First-install experience on a sandbox is a silent breakage.What changes
src/proxies/screenDom.ts— priority list + skip-empty heuristic + one-time warn + module-state reset for tests.src/bundled.tsx—rootSelector?: stringonInitTWDOptions;initTWDforwards to the internal setter beforeinitTests/initRequestMocking.docs/testing-library.md(rewritten "How screenDom Works" + troubleshooting);docs/getting-started.md(new commented option in theinitTWDexample).1.7.2entry — no version bump.Non-goals
setRootSelectororresetScreenDomState— those are package-internal.initTests(React-path power users who need a custom root useinitTWD).screenDomGlobal.Test plan
npm run test:ci— 391/391 passing across 54 filesnpm run docs:build— VitePress build cleannpm run build— succeeds; the TS errors insrc/plugin/*are pre-existing and unrelated#root> decoy,#appfallback,app-rootfallback), skip-empty heuristic, configured selector wins, configured-but-missing falls through, warn fires exactly once per session#highlighterregression no longer manifests)🤖 Generated with Claude Code