Files
playwriter/website/public/resources/styles-api.md
Tommy D. Rossi 87188423b1 feat: reuse Playwright's internal CDP session instead of creating new WebSocket connections
Switch from getCDPSessionForPage (creates a new WS via Target.attachToTarget)
to getExistingCDPSessionForPage which reuses Playwright's internal CRSession.
This is critical for the relay server where Target.attachToTarget is intercepted
and cannot create real new sessions.

Also add FrameLocator support in accessibilitySnapshot — FrameLocator (from
locator.contentFrame()) is now auto-resolved to the real Frame object needed
for OOPIF CDP session attachment.

- New PlaywrightCDPSessionAdapter wrapping Playwright's CDPSession as ICDPSession
- New getExistingCDPSessionForPage() using context.getExistingCDPSession()
- resolveFrame() helper converts FrameLocator to Frame via elementHandle().contentFrame()
- getAriaSnapshot() frame param now accepts Frame | FrameLocator
- Executor CDP cache uses ICDPSession, borrowed sessions detach as no-op
- Test for getExistingCDPSession through the relay
- Updated framer iframe guide with alternative page.frames() example
- Bump playwright submodule to @xmorse/playwright-core@1.59.2
- Fix styles-api.md import path
2026-02-06 18:03:26 +01:00

117 lines
3.7 KiB
Markdown

# Styles API Reference
The getStylesForLocator function inspects CSS styles applied to an element, similar to browser DevTools "Styles" panel.
## Types
```ts
import type { ICDPSession } from './cdp-session.js';
import type { Locator } from '@xmorse/playwright-core';
export interface StyleSource {
url: string;
line: number;
column: number;
}
export type StyleDeclarations = Record<string, string>;
export interface StyleRule {
selector: string;
source: StyleSource | null;
origin: 'regular' | 'user-agent' | 'injected' | 'inspector';
declarations: StyleDeclarations;
inheritedFrom: string | null;
}
export interface StylesResult {
element: string;
inlineStyle: StyleDeclarations | null;
rules: StyleRule[];
}
export declare function getStylesForLocator({ locator, cdp: cdpSession, includeUserAgentStyles, }: {
locator: Locator;
cdp: ICDPSession;
includeUserAgentStyles?: boolean;
}): Promise<StylesResult>;
export declare function formatStylesAsText(styles: StylesResult): string;
```
## Examples
```ts
import { page, getStylesForLocator, formatStylesAsText, console } from './debugger-examples-types.js'
// Example: Get styles for an element and display them
async function getElementStyles() {
const loc = page.locator('.my-button')
const styles = await getStylesForLocator({ locator: loc })
console.log(formatStylesAsText(styles))
}
// Example: Inspect computed styles for a specific element
async function inspectButtonStyles() {
const button = page.getByRole('button', { name: 'Submit' })
const styles = await getStylesForLocator({ locator: button })
console.log('Element:', styles.element)
if (styles.inlineStyle) {
console.log('Inline styles:', styles.inlineStyle)
}
for (const rule of styles.rules) {
console.log(`${rule.selector}: ${JSON.stringify(rule.declarations)}`)
if (rule.source) {
console.log(` Source: ${rule.source.url}:${rule.source.line}`)
}
}
}
// Example: Include browser default (user-agent) styles
async function getStylesWithUserAgent() {
const loc = page.locator('input[type="text"]')
const styles = await getStylesForLocator({
locator: loc,
includeUserAgentStyles: true,
})
console.log(formatStylesAsText(styles))
}
// Example: Find where a CSS property is defined
async function findPropertySource() {
const loc = page.locator('.card')
const styles = await getStylesForLocator({ locator: loc })
const backgroundRule = styles.rules.find((r) => 'background-color' in r.declarations)
if (backgroundRule) {
console.log('background-color defined by:', backgroundRule.selector)
if (backgroundRule.source) {
console.log(` at ${backgroundRule.source.url}:${backgroundRule.source.line}`)
}
}
}
// Example: Check inherited styles
async function checkInheritedStyles() {
const loc = page.locator('.nested-text')
const styles = await getStylesForLocator({ locator: loc })
const inheritedRules = styles.rules.filter((r) => r.inheritedFrom)
for (const rule of inheritedRules) {
console.log(`Inherited from ${rule.inheritedFrom}: ${rule.selector}`)
console.log(' Properties:', rule.declarations)
}
}
// Example: Compare styles between two elements
async function compareStyles() {
const primary = await getStylesForLocator({ locator: page.locator('.btn-primary') })
const secondary = await getStylesForLocator({ locator: page.locator('.btn-secondary') })
console.log('Primary button:')
console.log(formatStylesAsText(primary))
console.log('Secondary button:')
console.log(formatStylesAsText(secondary))
}
export { getElementStyles, inspectButtonStyles, getStylesWithUserAgent, findPropertySource, checkInheritedStyles, compareStyles }
```