recon_gen.common.browser.screenshot
ScreenshotHarness: walk a deployed App’s tree and capture screenshots systematically.
Three capture modes:
capture_all_sheets()— one full-page screenshot per sheet. Returnsdict[Sheet, Path]keyed by the Sheet object ref so handbook templates can look up by Sheet, not by sheet_id string. Filenames remain{sheet_id}.pngfor stable on-disk names.capture_per_visual(sheet)— one screenshot per visual on the sheet, scroll-into-view + element crop. Returnsdict[VisualLike, Path]keyed by the Visual object ref; filenames derive from each visual’s resolvedvisual_id.capture_with_state(parameter_values)— apply parameter values via URL hash, then capture every sheet. Returnsdict[Sheet, Path]keyed by Sheet ref.
Sheet/Visual object keys (M.1.10 / F8) means callers can do
paths[my_sheet] from the same App they constructed, instead
of carrying a parallel sheet_id string around. The on-disk
filenames stay sheet_id-derived so previously-generated images
overwrite cleanly across runs.
Why this matters for Phase M: when whitelabel-V2 swaps personas
(Sasquatch → Acme Bank), the docs need Acme-shaped screenshots.
Manual capture doesn’t scale; capture_all_sheets() regenerates
the screenshot set against the new persona’s deploy in one call.
The persona dataclass drives BOTH the seed generator AND the
screenshot pipeline in lockstep.
Same Page-based infra as TreeValidator; different consumer —
they could share a DeployedTreeContext helper if patterns
crystallize. For now each tool has its own class.
Functions
|
Walk a deployed App's tree and capture full-page PNGs per sheet. |
Classes
|
Walk an App + Page; produce a directory of named screenshots. |
- class recon_gen.common.browser.screenshot.ScreenshotHarness(app, page, output_dir, embed_url=None, timeout_ms=30000)[source]
Bases:
objectWalk an App + Page; produce a directory of named screenshots.
- Parameters:
app (App)
page (Any)
output_dir (Path)
embed_url (str | None)
timeout_ms (int)
- capture_all_sheets()[source]
One full-page screenshot per sheet on the App’s analysis.
Returns
dict[Sheet, Path]keyed by the Sheet object ref. Filenames remain{sheet_id}.pngso re-running overwrites the same on-disk file; only the in-memory key shape changed (M.1.10 / F8).- Return type:
dict[Sheet,Path]
- capture_per_visual(sheet)[source]
One screenshot per visual on
sheet, element-cropped.Returns
dict[VisualLike, Path]keyed by the Visual object ref. Skips visuals without a resolvedvisual_id— the auto-ID walker hasn’t run, or the visual is a factory wrapper without an explicit id. Caller shouldapp.emit_analysis()once before to resolve auto-IDs (the validator + this harness usually share a session-scoped fixture that already does that).- Return type:
dict[VisualLike,Path]- Parameters:
sheet (Sheet)
- capture_with_state(*, parameter_values, suffix='state')[source]
Re-load the dashboard with parameter values applied via URL hash (
#p.<name>=<value>), then capture every sheet.Returns
dict[Sheet, Path]keyed by Sheet object ref. Filenames suffix-tagged so multiple states don’t overwrite each other:{sheet_id}-{suffix}.png. Pass distinctsuffixvalues per state.Per the project memory
project_qs_url_parameter_no_control_sync, the on-screen control widget may not reflect the URL value even when the data is filtered. The screenshot captures what the analyst SEES, which is the rendered visual state — that’s the right semantics for handbook screenshots.Requires
embed_urlset on construction.- Return type:
dict[Sheet,Path]- Parameters:
parameter_values (dict[ParameterDeclLike, Any])
suffix (str)
- embed_url: str | None = None
- output_dir: Path
- page: Any
- timeout_ms: int = 30000
- recon_gen.common.browser.screenshot.capture_deployed_app(app, *, embed_url, output_dir, viewport=(1280, 900), initial_settle_ms=10000, per_sheet_settle_ms=8000, page_timeout_ms=120000, headless=True, url_params=None)[source]
Walk a deployed App’s tree and capture full-page PNGs per sheet.
Differs from
ScreenshotHarness.capture_all_sheets()(which assumes a Page is already open + the test fixture has set the viewport): this helper owns the browser lifecycle and uses settle timeouts instead ofwait_for_visuals_present. Matches the proven shape of the pre-Q ad-hoc capture scripts. The forgiving settle timing tolerates QS spinner-forever cases (Operational Footguns) by capturing whatever painted in the window — a spinner-frame in the PNG is acceptable for handbook docs since the next run usually clears it.url_params: optional{paramName: value}dict appended to the embed URL as#p.<name>=<value>&p.<name>=<value>...so the captured page renders with overridden parameter values. Used by the screenshots CLI to inject--date-from / --date-towhen the seed anchors at a date the dashboard’s default rolling-window controls don’t span. Per the QuickSight URL-param control-sync limitation (see project memoryproject_qs_url_parameter_no_control_sync), the on-screen control widget may still show the default value; the data is filtered by the URL value, which is what matters for screenshots. Values are URL-encoded.Returns
dict[Sheet, Path]keyed by Sheet object ref. Filenames are{sheet_id}.pngso re-running overwrites the same on-disk file.