You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Selenium and Nightwatch traces are framed at 1280x720: neither adapter publishes a viewport #373
Neither the Selenium nor the Nightwatch adapter publishes a viewport at all — grep -rn "viewport" packages/selenium-devtools/src packages/nightwatch-devtools/src returns nothing. So trace.metadata.viewport is absent for every trace either one produces, and the reader falls back to a hard-coded default in three places (packages/trace/src/trace-exporter.ts:190, :318, :367):
That default is what the player lays the DOM-replay iframe out at (packages/app/src/components/browser/snapshot.ts:309 — viewport?.width || 1280), so every Selenium and Nightwatch trace is replayed at 1280x720 regardless of the window the run actually used. It is not a mobile-only problem; a desktop run at 2560x1440 is framed just as wrongly, which is presumably why it went unnoticed — the proportions are plausible.
The WDIO service and the Python adapter both do this already, and they show what it takes:
packages/service/src/session-metadata.tsresolveViewport — reads window.visualViewport for a page (it carries the real scale and offsets, unlike the driver window, which includes browser chrome) and getWindowSize() for a native app, degrading to no viewport rather than failing the session.
packages/selenium-devtools-py/src/selenium_devtools/instrumentation.py_viewport / _driver_window — the same split, with the read marked internal so it does not re-enter the command hook as a captured executeScript/getWindowRect row. Both adapters here would need that same care: Selenium's unpatched getDriverOriginals(), Nightwatch's raw webdriverHttp transport.
isNativeAppSession (shared) already answers which of the two reads applies, so the branch is settled — this is the read itself plus its plumbing into each adapter's metadata.
Worth doing in the same change: metadata.viewport is documented as "metadata only" in a couple of places, and it is not — it is load-bearing geometry wherever there is DOM to replay. Whichever comment survives should say so.
Split out of #372, which covered native detection and deliberately stopped short of this.
Measured this while building a harness for the two adapters, and the consequence is worse than the issue says.
A missing viewport does not merely mis-size the replay — it switches the device layout off entirely.workbench.ts#deviceLayout treats a capture wider than it is tall as landscape and deliberately picks the stacked layout for it, because a wide frame in a tall column wastes the column. The reader's fallback is 1280 × 720, which is landscape. So for every Selenium and Nightwatch trace:
the phone renders in the small stacked player instead of the full-height device column,
and the dock stays below it rather than beside it.
The comment on that gate says an unknown shape is treated as portrait, and it is right to — but a viewport is never unknown by the time the app sees it, because the exporter has already substituted its default. The fallback turns "no information" into "landscape".
Two side-by-side zips make it visible, built through the real writeTraceZip with identical commands, screenshots and metadata and differing only in whether a viewport was published: with one, the device column; without, the stacked layout.
Worth deciding as part of this issue: whether the exporter's ?? { width: 1280, height: 720 } should stay a viewport at all, or whether the field should be left absent so the app's documented "unknown means portrait" path can actually be reached. Substituting a desktop shape for silence is what makes a phone trace claim to be landscape. That would also make the fix safe to land before every adapter publishes a real viewport.
Activity
vishnuv688 commentedon Sep 9, 2026
Measured this while building a harness for the two adapters, and the consequence is worse than the issue says.
A missing viewport does not merely mis-size the replay — it switches the device layout off entirely.
workbench.ts#deviceLayouttreats a capture wider than it is tall as landscape and deliberately picks the stacked layout for it, because a wide frame in a tall column wastes the column. The reader's fallback is1280 × 720, which is landscape. So for every Selenium and Nightwatch trace:The comment on that gate says an unknown shape is treated as portrait, and it is right to — but a viewport is never unknown by the time the app sees it, because the exporter has already substituted its default. The fallback turns "no information" into "landscape".
Two side-by-side zips make it visible, built through the real
writeTraceZipwith identical commands, screenshots and metadata and differing only in whether a viewport was published: with one, the device column; without, the stacked layout.Worth deciding as part of this issue: whether the exporter's
?? { width: 1280, height: 720 }should stay a viewport at all, or whether the field should be left absent so the app's documented "unknown means portrait" path can actually be reached. Substituting a desktop shape for silence is what makes a phone trace claim to be landscape. That would also make the fix safe to land before every adapter publishes a real viewport.