Skip to content

Commit b01afd2

Browse files
authored
fix(browser): fix trace highlight of shadow dom on webdriverio (#10227)
1 parent 0dccf3d commit b01afd2

3 files changed

Lines changed: 77 additions & 51 deletions

File tree

packages/browser/src/client/tester/locators.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,7 @@ export abstract class Locator {
355355
return {
356356
selector: this.selector,
357357
locator: this.asLocator(),
358+
_pwSelector: this._pwSelector,
358359
}
359360
}
360361

@@ -429,6 +430,10 @@ export function triggerCommandWithTrace<T>(
429430
export interface SerializedLocator {
430431
selector: string
431432
locator: string
433+
/**
434+
* @internal
435+
*/
436+
_pwSelector?: string
432437
}
433438

434439
function createStrictModeViolationError(

packages/browser/src/client/tester/trace.ts

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ export type BrowserTraceSelectorResolution = 'matched' | 'missing' | 'error'
1515

1616
export interface BrowserTraceEntry {
1717
name: string
18-
// not used yet for UI but tested
1918
kind: BrowserTraceEntryKind
2019
status?: BrowserTraceEntryStatus
2120
startTime: number
@@ -85,19 +84,9 @@ export function recordBrowserTraceEntry(
8584
startTime?: number
8685
},
8786
): void {
88-
// TODO: trace-view currently receives selectors after locator/action resolution,
89-
// so provider-specific lowered selectors can leak into snapshot lookup. Preserve
90-
// the original locator selector, or record the target node id before lowering.
91-
// for example, this causes shadow dom selectors to fail with `>>>` marker.
92-
// For now, remove trivial `html >` prefix generated by convertElementToCssSelector.
93-
// this is also necessary to `engine.querySelector + document.documentElement`
94-
// to find an element on webdriverio
95-
if (options.element?.selector?.startsWith('html >')) {
96-
options.element.selector = options.element.selector.slice(6)
97-
}
9887
const attemptInfo = getBrowserState().browserTraceAttempts.get(task.id)!
9988
const relativeStartTime = (options.startTime ?? now()) - attemptInfo.startTime
100-
const snapshot = takeSnapshot(options.element?.selector)
89+
const snapshot = takeSnapshot(options.element)
10190
const entry: BrowserTraceEntry = {
10291
...options,
10392
startTime: relativeStartTime,
@@ -117,7 +106,7 @@ export function recordBrowserTraceEntry(
117106
// selector engine inside the snapshot iframe at view time via injected script.
118107
// Our approach resolves at collection time (same moment as snapshot) — simpler but
119108
// requires Mirror plumbing. nodeId-based lookup also works across shadow DOM, unlike querySelector.
120-
function takeSnapshot(selector?: string): TraceSnapshot {
109+
function takeSnapshot(serializedLocator?: SerializedLocator): TraceSnapshot {
121110
const { snapshot, createMirror } = getBrowserState().browserTraceDomSnapshot!
122111
const traceView = getBrowserState().config.browser.traceView
123112
const engine = getBrowserState().selectorEngine!
@@ -144,10 +133,10 @@ function takeSnapshot(selector?: string): TraceSnapshot {
144133
const ids = Array.from(elements, el => mirror.getId(el)).filter(id => id !== -1)
145134
result.pseudoClassIds[className] = ids
146135
}
147-
if (selector) {
136+
if (serializedLocator) {
148137
try {
149138
const el = engine.querySelector(
150-
engine.parseSelector(selector),
139+
engine.parseSelector(serializedLocator._pwSelector ?? serializedLocator.selector),
151140
document.documentElement,
152141
false,
153142
)

0 commit comments

Comments
 (0)