feat: Enable snapshots for most remaining public commands (#34072)

This commit is contained in:
Adam Gastineau 2025-01-10 05:04:44 -08:00 committed by GitHub
parent b32d546159
commit a2e2dfd446
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 88 additions and 5 deletions

View File

@ -89,13 +89,16 @@ export const commandsWithTracingSnapshots = new Set([
'Page.mouseClick',
'Page.mouseWheel',
'Page.touchscreenTap',
'Page.accessibilitySnapshot',
'Frame.evalOnSelector',
'Frame.evalOnSelectorAll',
'Frame.addScriptTag',
'Frame.addStyleTag',
'Frame.ariaSnapshot',
'Frame.blur',
'Frame.check',
'Frame.click',
'Frame.content',
'Frame.dragAndDrop',
'Frame.dblclick',
'Frame.dispatchEvent',
@ -116,6 +119,9 @@ export const commandsWithTracingSnapshots = new Set([
'Frame.isVisible',
'Frame.isEditable',
'Frame.press',
'Frame.querySelector',
'Frame.querySelectorAll',
'Frame.queryCount',
'Frame.selectOption',
'Frame.setContent',
'Frame.setInputFiles',
@ -133,8 +139,10 @@ export const commandsWithTracingSnapshots = new Set([
'ElementHandle.evaluateExpressionHandle',
'ElementHandle.evalOnSelector',
'ElementHandle.evalOnSelectorAll',
'ElementHandle.boundingBox',
'ElementHandle.check',
'ElementHandle.click',
'ElementHandle.contentFrame',
'ElementHandle.dblclick',
'ElementHandle.dispatchEvent',
'ElementHandle.fill',
@ -150,6 +158,8 @@ export const commandsWithTracingSnapshots = new Set([
'ElementHandle.isHidden',
'ElementHandle.isVisible',
'ElementHandle.press',
'ElementHandle.querySelector',
'ElementHandle.querySelectorAll',
'ElementHandle.screenshot',
'ElementHandle.scrollIntoViewIfNeeded',
'ElementHandle.selectOption',

View File

@ -134,7 +134,7 @@ function shouldPauseBeforeStep(metadata: CallMetadata): boolean {
// Always stop on 'close'
if (metadata.method === 'close')
return true;
if (metadata.method === 'waitForSelector' || metadata.method === 'waitForEventInfo')
if (metadata.method === 'waitForSelector' || metadata.method === 'waitForEventInfo' || metadata.method === 'querySelector' || metadata.method === 'querySelectorAll')
return false; // Never stop on those, primarily for the test harness.
const step = metadata.type + '.' + metadata.method;
// Stop before everything that generates snapshot. But don't stop before those marked as pausesBeforeInputActions

View File

@ -1675,6 +1675,8 @@ Page:
root: ElementHandle?
returns:
rootAXNode: AXNode?
flags:
snapshot: true
pdf:
parameters:
@ -1885,6 +1887,8 @@ Frame:
timeout: number?
returns:
snapshot: string
flags:
snapshot: true
blur:
parameters:
@ -1943,6 +1947,8 @@ Frame:
content:
returns:
value: string
flags:
snapshot: true
dragAndDrop:
parameters:
@ -2202,6 +2208,8 @@ Frame:
strict: boolean?
returns:
element: ElementHandle?
flags:
snapshot: true
querySelectorAll:
parameters:
@ -2210,12 +2218,16 @@ Frame:
elements:
type: array
items: ElementHandle
flags:
snapshot: true
queryCount:
parameters:
selector: string
returns:
value: number
flags:
snapshot: true
selectOption:
parameters:
@ -2540,6 +2552,8 @@ ElementHandle:
boundingBox:
returns:
value: Rect?
flags:
snapshot: true
check:
parameters:
@ -2585,6 +2599,8 @@ ElementHandle:
contentFrame:
returns:
frame: Frame?
flags:
snapshot: true
dblclick:
parameters:
@ -2739,6 +2755,8 @@ ElementHandle:
strict: boolean?
returns:
element: ElementHandle?
flags:
snapshot: true
querySelectorAll:
parameters:
@ -2747,6 +2765,8 @@ ElementHandle:
elements:
type: array
items: ElementHandle
flags:
snapshot: true
screenshot:
parameters:

View File

@ -188,12 +188,20 @@ it.describe('pause', () => {
const iframe = page.frames()[1];
const button = await iframe.waitForSelector('button');
const box1 = await button.boundingBox();
const box1Promise = button.boundingBox();
const actionPoint = await page.waitForSelector('x-pw-action-point');
const box2 = await actionPoint.boundingBox();
const box2Promise = actionPoint.boundingBox();
await recorderPage.click('[title="Step over (F10)"]');
const box1 = await box1Promise;
const box2 = await box2Promise;
const iframeActionPoint = await iframe.$('x-pw-action-point');
expect(await iframeActionPoint?.boundingBox()).toBeFalsy();
const iframeActionPointPromise = iframeActionPoint?.boundingBox();
await recorderPage.click('[title="Resume (F8)"]');
expect(await iframeActionPointPromise).toBeFalsy();
const x1 = box1!.x + box1!.width / 2;
const y1 = box1!.y + box1!.height / 2;
@ -203,7 +211,6 @@ it.describe('pause', () => {
expect(Math.abs(x1 - x2) < 2).toBeTruthy();
expect(Math.abs(y1 - y2) < 2).toBeTruthy();
await recorderPage.click('[title="Resume (F8)"]');
await scriptPromise;
});

View File

@ -1271,3 +1271,49 @@ test('should record trace after fixture teardown timeout', {
// Check console events to make sure that library trace is recorded.
expect(trace.events).toContainEqual(expect.objectContaining({ type: 'console', text: 'from the page' }));
});
test('should record trace snapshot for more obscure commands', async ({ runInlineTest }) => {
const result = await runInlineTest({
'a.spec.ts': `
import { test, expect } from '@playwright/test';
test('test 1', async ({ browser }) => {
const page = await browser.newPage();
await page.setContent('<div>Content</div>');
expect(await page.locator('div').count()).toBe(1);
await page.locator('div').boundingBox();
});
`,
}, { trace: 'on' });
expect(result.exitCode).toBe(0);
expect(result.passed).toBe(1);
const tracePath = test.info().outputPath('test-results', 'a-test-1', 'trace.zip');
const trace = await parseTrace(tracePath);
expect(trace.actionTree).toEqual([
'Before Hooks',
' fixture: browser',
' browserType.launch',
'browser.newPage',
'page.setContent',
'locator.count',
'expect.toBe',
'locator.boundingBox',
'After Hooks',
]);
const snapshots = trace.traceModel.storage();
const snapshotFrameOrPageId = snapshots.snapshotsForTest()[0];
const countAction = trace.actions.find(a => a.apiName === 'locator.count');
expect(countAction.beforeSnapshot).toBeTruthy();
expect(countAction.afterSnapshot).toBeTruthy();
expect(snapshots.snapshotByName(snapshotFrameOrPageId, countAction.beforeSnapshot)).toBeTruthy();
expect(snapshots.snapshotByName(snapshotFrameOrPageId, countAction.afterSnapshot)).toBeTruthy();
const boundingBoxAction = trace.actions.find(a => a.apiName === 'locator.boundingBox');
expect(boundingBoxAction.beforeSnapshot).toBeTruthy();
expect(boundingBoxAction.afterSnapshot).toBeTruthy();
expect(snapshots.snapshotByName(snapshotFrameOrPageId, boundingBoxAction.beforeSnapshot)).toBeTruthy();
expect(snapshots.snapshotByName(snapshotFrameOrPageId, boundingBoxAction.afterSnapshot)).toBeTruthy();
});