"""The screenshots the website uses, as data. Each shot is one page of the netOrk UI. `path` may contain `{placeholders}` that are filled from `--var name=value` on the command line (device IDs differ per instance, so they are never hard-coded here). Device detail sections are addressed through the URL hash the UI itself writes (`#security/assessment`, `#config`, ...), so no clicking is needed. `mask` lists extra CSS selectors to cover on top of the automatic masks (public IPv4 addresses, e-mail addresses, and the terms from the mask file). """ from dataclasses import dataclass, field @dataclass class Shot: name: str path: str # Selector that must be visible before the shot is taken. wait_for: str = "main" mask: list[str] = field(default_factory=list) full_page: bool = False # Crop to a region (x, y, width, height in CSS px of the viewport) ... clip: tuple[int, int, int, int] | None = None # ... or to one element, plus `pad` px around it. Cropping shows less of a # real screen; it never changes what is on it. element: str | list[str] | None = None # several: crop to what they cover together pad: int = 16 # Viewport for this shot, (width, height) in CSS px; default in capture.py. viewport: tuple[int, int] | None = None # Width of the published WebP in pixels (captures are taken at 2x). width: int = 1600 # Selectors clicked in order before the shot, first match each. Only for # controls that change the view (filters, tabs); the API guard in # capture.py aborts anything that would write. clicks: list[str] = field(default_factory=list) # The drift comparison on a device page: the summary line ("… (42 compared)") down to # the end of the table. The card around it stretches to the window height. DRIFT_CARD = ["xpath=//*[contains(text(), 'compared)')]", "xpath=//table[.//th[contains(., 'Expected')]]"] SHOTS: list[Shot] = [ # Home hero: an access point checked against its profile, wide and short. Shot("drift", "/devices/{ap}#drift", wait_for="main table", element=DRIFT_CARD, pad=28, viewport=(1440, 900), width=2400), # Phones: the same finding from "Parameter" to the status badge, readable at 390px. Shot("drift-narrow", "/devices/{ap}#drift", wait_for="main table", element=["xpath=//th[contains(., 'Parameter')]", "xpath=//th[contains(., 'Actual')]", "xpath=//tbody//td[contains(., 'Remote Syslog')]", "xpath=//tbody//span[contains(., 'Incomplete')]", "xpath=//tbody//*[starts-with(normalize-space(text()), 'Set this field')]"], pad=16, viewport=(1180, 900), width=1200), Shot("vulnerabilities", "/vulnerabilities", clip=(256, 40, 1344, 620), width=2400), # Background polls drown out what people did: filter the scheduler out, # the way a reader would (click a source badge, then flip it to exclude). Shot("audit-log", "/audit-log", clip=(256, 40, 1344, 560), width=2400, clicks=[ "tbody td >> text=scheduler", "button[title='Click to toggle include/exclude']", ]), ]