/** * Content painted over other content: the overlap nothing measures. * * Every geometry check here asks the same question about one element and its * container. None of them compares two elements with each other, so a chip * drawn across the name beside it, a floating button covering the last row of a * table, or a sticky bar sitting on the heading under it, all of which destroy * information outright, are visible to nobody but a judge reading an image. * * Overlap on its own means nothing: a page is layers, and most of them are * meant to be. The whole difficulty is separating a collision from the many * legitimate reasons two boxes intersect, which is what every exclusion below * is for. Anything positioned out of flow is excluded because that IS the way * an overlay is built. Anything inside an open dialog is excluded because a * modal is supposed to cover the page. Ancestry is excluded because a parent * always contains its child. What is left is two ordinary siblings in normal * flow occupying the same pixels, which is a defect every time. * * Same split as the clip check: one self-contained `page.evaluate` measures, * and a pure function rules. */ import type { Locator, Page } from "playwright"; import type { DeterministicFinding } from "../types.js"; /** Two elements found occupying the same pixels. Raw: nothing decided. */ export interface CollisionPair { /** The element painted on top, by document order and stacking. */ topPath: string; topTag: string; topText: string; /** The one it covers. */ underPath: string; underTag: string; underText: string; /** Share of the SMALLER box the intersection covers, 0 to 1. */ share: number; /** The top element really is what paints at the intersection's centre. */ confirmed: boolean; } export interface CollisionHarvest { pairs: CollisionPair[]; truncated: boolean; } /** Runs in the browser. Self-contained: no closure over module scope. */ export declare function collectCollisionsInPage(args: { rootSelector: string | null; maxElements: number; minOverlap: number; }): CollisionHarvest; /** * Which measured overlaps are defects, as at most one finding per shot. * * Only pairs the browser confirmed: an intersection the hit test could not * reproduce (scrolled out of the viewport, covered by a third element) is a * pair of rectangles, not something a reader can see going wrong. */ export declare function classifyCollisions(harvest: CollisionHarvest): DeterministicFinding[]; /** Measure this shot, and rule. */ export declare function checkCollisions(page: Page, element: Locator | null, opts?: { elementSelector?: string | null; }): Promise;