Revert "chore: upstream the frame tree snapshot" (#35911)

This commit is contained in:
Pavel Feldman 2025-05-09 11:28:25 -07:00 committed by GitHub
parent dee0535480
commit 9de2bd49e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 42 additions and 81 deletions

View File

@ -303,13 +303,8 @@ export class Locator implements api.Locator {
return await this._withElement((h, timeout) => h.screenshot({ ...options, mask, timeout }), options.timeout);
}
async ariaSnapshot(options?: TimeoutOptions): Promise<string> {
const result = await this._frame._channel.ariaSnapshot({ ...options, selector: this._selector });
return result.snapshot;
}
async _snapshotForAI(): Promise<string> {
const result = await this._frame._channel.snapshotForAI({ selector: this._selector });
async ariaSnapshot(options?: { _forAI?: boolean } & TimeoutOptions): Promise<string> {
const result = await this._frame._channel.ariaSnapshot({ ...options, forAI: options?._forAI, selector: this._selector });
return result.snapshot;
}

View File

@ -95,7 +95,6 @@ export const commandsWithTracingSnapshots = new Set([
'Frame.addScriptTag',
'Frame.addStyleTag',
'Frame.ariaSnapshot',
'Frame.snapshotForAI',
'Frame.blur',
'Frame.check',
'Frame.click',

View File

@ -1484,17 +1484,12 @@ scheme.FrameAddStyleTagResult = tObject({
});
scheme.FrameAriaSnapshotParams = tObject({
selector: tString,
forAI: tOptional(tBoolean),
timeout: tOptional(tNumber),
});
scheme.FrameAriaSnapshotResult = tObject({
snapshot: tString,
});
scheme.FrameSnapshotForAIParams = tObject({
selector: tString,
});
scheme.FrameSnapshotForAIResult = tObject({
snapshot: tString,
});
scheme.FrameBlurParams = tObject({
selector: tString,
strict: tOptional(tBoolean),

View File

@ -271,8 +271,4 @@ export class FrameDispatcher extends Dispatcher<Frame, channels.FrameChannel, Br
async ariaSnapshot(params: channels.FrameAriaSnapshotParams, metadata: CallMetadata): Promise<channels.FrameAriaSnapshotResult> {
return { snapshot: await this._frame.ariaSnapshot(metadata, params.selector, params) };
}
async snapshotForAI(params: channels.FrameSnapshotForAIParams, metadata: CallMetadata): Promise<channels.FrameSnapshotForAIResult> {
return { snapshot: await this._frame.snapshotForAI(metadata, params.selector) };
}
}

View File

@ -811,7 +811,7 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
return this._page.delegate.getBoundingBox(this);
}
async ariaSnapshot(options?: { forAI?: boolean }): Promise<string> {
async ariaSnapshot(options: { forAI?: boolean }): Promise<string> {
return await this.evaluateInUtility(([injected, element, options]) => injected.ariaSnapshot(element, options), options);
}

View File

@ -1411,41 +1411,13 @@ export class Frame extends SdkObject {
});
}
async ariaSnapshot(metadata: CallMetadata, selector: string, options: types.TimeoutOptions = {}): Promise<string> {
async ariaSnapshot(metadata: CallMetadata, selector: string, options: { forAI?: boolean } & types.TimeoutOptions = {}): Promise<string> {
const controller = new ProgressController(metadata, this);
return controller.run(async progress => {
return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, handle => handle.ariaSnapshot());
return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, handle => handle.ariaSnapshot(options));
}, this._page.timeoutSettings.timeout(options));
}
async snapshotForAI(metadata: CallMetadata, selector: string): Promise<string> {
const allFrameSnapshot = async (selector: string): Promise<string> => {
const controller = new ProgressController(metadata, this);
const snapshot = await controller.run(async progress => {
return await this._retryWithProgressIfNotConnected(progress, selector, true /* strict */, true /* performActionPreChecks */, handle => handle.ariaSnapshot({ forAI: true }));
}, this._page.timeoutSettings.defaultTimeout());
const lines = snapshot.split('\n');
const result = [];
for (const line of lines) {
const match = line.match(/^(\s*)- iframe \[ref=(.*)\]/);
if (!match) {
result.push(line);
continue;
}
const leadingSpace = match[1];
const ref = match[2];
const childSelector = `${selector} >> aria-ref=${ref} >> internal:control=enter-frame >> body`;
const childSnapshot = await allFrameSnapshot(childSelector);
result.push(line + ':', childSnapshot.split('\n').map(l => leadingSpace + ' ' + l).join('\n'));
}
return result.join('\n');
};
return await allFrameSnapshot(selector);
}
async expect(metadata: CallMetadata, selector: string, options: FrameExpectParams): Promise<{ matches: boolean, received?: any, log?: string[], timedOut?: boolean }> {
const result = await this._expectImpl(metadata, selector, options);
// Library mode special case for the expect errors which are return values, not exceptions.

View File

@ -2589,7 +2589,6 @@ export interface FrameChannel extends FrameEventTarget, Channel {
addScriptTag(params: FrameAddScriptTagParams, metadata?: CallMetadata): Promise<FrameAddScriptTagResult>;
addStyleTag(params: FrameAddStyleTagParams, metadata?: CallMetadata): Promise<FrameAddStyleTagResult>;
ariaSnapshot(params: FrameAriaSnapshotParams, metadata?: CallMetadata): Promise<FrameAriaSnapshotResult>;
snapshotForAI(params: FrameSnapshotForAIParams, metadata?: CallMetadata): Promise<FrameSnapshotForAIResult>;
blur(params: FrameBlurParams, metadata?: CallMetadata): Promise<FrameBlurResult>;
check(params: FrameCheckParams, metadata?: CallMetadata): Promise<FrameCheckResult>;
click(params: FrameClickParams, metadata?: CallMetadata): Promise<FrameClickResult>;
@ -2696,23 +2695,16 @@ export type FrameAddStyleTagResult = {
};
export type FrameAriaSnapshotParams = {
selector: string,
forAI?: boolean,
timeout?: number,
};
export type FrameAriaSnapshotOptions = {
forAI?: boolean,
timeout?: number,
};
export type FrameAriaSnapshotResult = {
snapshot: string,
};
export type FrameSnapshotForAIParams = {
selector: string,
};
export type FrameSnapshotForAIOptions = {
};
export type FrameSnapshotForAIResult = {
snapshot: string,
};
export type FrameBlurParams = {
selector: string,
strict?: boolean,

View File

@ -1976,20 +1976,13 @@ Frame:
ariaSnapshot:
parameters:
selector: string
forAI: boolean?
timeout: number?
returns:
snapshot: string
flags:
snapshot: true
snapshotForAI:
parameters:
selector: string
returns:
snapshot: string
flags:
snapshot: true
blur:
parameters:
selector: string

View File

@ -14,11 +14,10 @@
* limitations under the License.
*/
import type { FrameLocator, Page } from '@playwright/test';
import { test as it, expect } from './pageTest';
function snapshotForAI(page: any): Promise<string> {
return page.locator('body')._snapshotForAI();
}
const forAI = { _forAI: true } as any;
it('should generate refs', async ({ page }) => {
await page.setContent(`
@ -27,7 +26,7 @@ it('should generate refs', async ({ page }) => {
<button>Three</button>
`);
const snapshot1 = await snapshotForAI(page);
const snapshot1 = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot1).toContainYaml(`
- generic [ref=e1]:
- button "One" [ref=e2]
@ -42,7 +41,7 @@ it('should generate refs', async ({ page }) => {
e.textContent = 'Not Two';
});
const snapshot2 = await snapshotForAI(page);
const snapshot2 = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot2).toContainYaml(`
- generic [ref=e1]:
- button "One" [ref=e2]
@ -57,17 +56,37 @@ it('should list iframes', async ({ page }) => {
<iframe name="foo" src="data:text/html,<h1>World</h1>">
`);
const snapshot1 = await snapshotForAI(page);
const snapshot1 = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot1).toContain('- iframe');
const frameSnapshot = await page.frameLocator(`iframe`).locator('body').ariaSnapshot();
expect(frameSnapshot).toEqual('- heading "World" [level=1]');
});
it('should stitch all frame snapshots', async ({ page, server }) => {
it('ref mode can be used to stitch all frame snapshots', async ({ page, server }) => {
await page.goto(server.PREFIX + '/frames/nested-frames.html');
const snapshot = await snapshotForAI(page);
expect(snapshot).toContainYaml(`
async function allFrameSnapshot(frame: Page | FrameLocator): Promise<string> {
const snapshot = await frame.locator('body').ariaSnapshot(forAI);
const lines = snapshot.split('\n');
const result = [];
for (const line of lines) {
const match = line.match(/^(\s*)- iframe \[ref=(.*)\]/);
if (!match) {
result.push(line);
continue;
}
const leadingSpace = match[1];
const ref = match[2];
const childFrame = frame.frameLocator(`aria-ref=${ref}`);
const childSnapshot = await allFrameSnapshot(childFrame);
result.push(line + ':', childSnapshot.split('\n').map(l => leadingSpace + ' ' + l).join('\n'));
}
return result.join('\n');
}
expect(await allFrameSnapshot(page)).toContainYaml(`
- generic [ref=e1]:
- iframe [ref=e2]:
- generic [ref=e1]:
@ -87,7 +106,7 @@ it('should not generate refs for hidden elements', async ({ page }) => {
<button>Three</button>
`);
const snapshot = await snapshotForAI(page);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- generic [ref=e1]:
- button "One" [ref=e2]
@ -119,7 +138,7 @@ it('should not generate refs for elements with pointer-events:none', async ({ pa
</div>
`);
const snapshot = await snapshotForAI(page);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- generic [ref=e1]:
- button "no-ref"
@ -163,7 +182,7 @@ it('emit generic roles for nodes w/o roles', async ({ page }) => {
</div>
`);
const snapshot = await snapshotForAI(page);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- generic [ref=e2]:
@ -193,7 +212,7 @@ it('should collapse generic nodes', async ({ page }) => {
</div>
`);
const snapshot = await snapshotForAI(page);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- button \"Button\" [ref=e5]
`);
@ -204,7 +223,7 @@ it('should include cursor pointer hint', async ({ page }) => {
<button style="cursor: pointer">Button</button>
`);
const snapshot = await snapshotForAI(page);
const snapshot = await page.locator('body').ariaSnapshot(forAI);
expect(snapshot).toContainYaml(`
- button \"Button\" [ref=e2] [cursor=pointer]
`);