fix(trace viewer): clear old highlighted elements upon change (#32917)
When the list of highlighted elements changes over time, we should update the elements marked as `__playwright_target__` in the snapshot. A good example is an `expect(locator).toHaveText([...])` where the list of elements changes from 4 items to 3 after clicking a "Delete" button.
This commit is contained in:
parent
616425a0fb
commit
3c5967d4f5
|
@ -65,6 +65,7 @@ export class InjectedScript {
|
|||
readonly isUnderTest: boolean;
|
||||
private _sdkLanguage: Language;
|
||||
private _testIdAttributeNameForStrictErrorAndConsoleCodegen: string = 'data-testid';
|
||||
private _markedElements?: { callId: string, elements: Set<Element> };
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
readonly window: Window & typeof globalThis;
|
||||
readonly document: Document;
|
||||
|
@ -1081,14 +1082,33 @@ export class InjectedScript {
|
|||
}
|
||||
|
||||
markTargetElements(markedElements: Set<Element>, callId: string) {
|
||||
const customEvent = new CustomEvent('__playwright_target__', {
|
||||
if (this._markedElements?.callId !== callId)
|
||||
this._markedElements = undefined;
|
||||
const previous = this._markedElements?.elements || new Set();
|
||||
|
||||
const unmarkEvent = new CustomEvent('__playwright_unmark_target__', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
detail: callId,
|
||||
composed: true,
|
||||
});
|
||||
for (const element of markedElements)
|
||||
element.dispatchEvent(customEvent);
|
||||
for (const element of previous) {
|
||||
if (!markedElements.has(element))
|
||||
element.dispatchEvent(unmarkEvent);
|
||||
}
|
||||
|
||||
const markEvent = new CustomEvent('__playwright_mark_target__', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
detail: callId,
|
||||
composed: true,
|
||||
});
|
||||
for (const element of markedElements) {
|
||||
if (!previous.has(element))
|
||||
element.dispatchEvent(markEvent);
|
||||
}
|
||||
|
||||
this._markedElements = { callId, elements: markedElements };
|
||||
}
|
||||
|
||||
private _setupGlobalListenersRemovalDetection() {
|
||||
|
|
|
@ -139,12 +139,19 @@ export function frameSnapshotStreamer(snapshotStreamer: string, removeNoScript:
|
|||
}
|
||||
|
||||
private _refreshListeners() {
|
||||
(document as any).addEventListener('__playwright_target__', (event: CustomEvent) => {
|
||||
(document as any).addEventListener('__playwright_mark_target__', (event: CustomEvent) => {
|
||||
if (!event.detail)
|
||||
return;
|
||||
const callId = event.detail as string;
|
||||
(event.composedPath()[0] as any).__playwright_target__ = callId;
|
||||
});
|
||||
(document as any).addEventListener('__playwright_unmark_target__', (event: CustomEvent) => {
|
||||
if (!event.detail)
|
||||
return;
|
||||
const callId = event.detail as string;
|
||||
if ((event.composedPath()[0] as any).__playwright_target__ === callId)
|
||||
delete (event.composedPath()[0] as any).__playwright_target__;
|
||||
});
|
||||
}
|
||||
|
||||
private _interceptNativeMethod(obj: any, method: string, cb: (thisObj: any, result: any) => void) {
|
||||
|
|
|
@ -761,7 +761,7 @@ test('should highlight target elements', async ({ page, runAndTrace, browserName
|
|||
await page.setContent(`
|
||||
<div>t1</div>
|
||||
<div>t2</div>
|
||||
<div>t3</div>
|
||||
<div id=div3>t3</div>
|
||||
<div>t4</div>
|
||||
<div>t5</div>
|
||||
<div>t6</div>
|
||||
|
@ -778,6 +778,11 @@ test('should highlight target elements', async ({ page, runAndTrace, browserName
|
|||
await page.mouse.move(123, 234);
|
||||
await page.getByText(/^t\d$/).click().catch(() => {});
|
||||
await expect(page.getByText(/t3|t4/)).toBeVisible().catch(() => {});
|
||||
|
||||
const expectPromise = expect(page.getByText(/t3|t4/)).toHaveText(['t4']);
|
||||
await page.waitForTimeout(1000);
|
||||
await page.evaluate(() => document.querySelector('#div3').textContent = 'changed');
|
||||
await expectPromise;
|
||||
});
|
||||
|
||||
async function highlightedDivs(frameLocator: FrameLocator) {
|
||||
|
@ -825,6 +830,9 @@ test('should highlight target elements', async ({ page, runAndTrace, browserName
|
|||
|
||||
const frameExpectStrictViolation = await traceViewer.snapshotFrame('expect.toBeVisible');
|
||||
await expect.poll(() => highlightedDivs(frameExpectStrictViolation)).toEqual(['t3', 't4']);
|
||||
|
||||
const frameUpdatedListOfTargets = await traceViewer.snapshotFrame('expect.toHaveText', 2);
|
||||
await expect.poll(() => highlightedDivs(frameUpdatedListOfTargets)).toEqual(['t4']);
|
||||
});
|
||||
|
||||
test('should highlight target element in shadow dom', async ({ page, server, runAndTrace }) => {
|
||||
|
|
Loading…
Reference in New Issue