fix(tracing): collect apiName for mouse/keyboard/touchscreen (#8755)

This commit is contained in:
Dmitry Gozman 2021-09-07 13:48:30 -07:00 committed by GitHub
parent b2c59a15dd
commit b30772c67e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 52 additions and 25 deletions

View File

@ -89,7 +89,7 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
return channel;
}
async _wrapApiCall<R, C extends channels.Channel>(func: (channel: C, stackTrace: ParsedStackTrace) => Promise<R>, logger?: Logger): Promise<R> {
async _wrapApiCall<R, C extends channels.Channel = T>(func: (channel: C, stackTrace: ParsedStackTrace) => Promise<R>, logger?: Logger): Promise<R> {
logger = logger || this._logger;
const stackTrace = captureStackTrace();
const { apiName, frameTexts } = stackTrace;

View File

@ -17,56 +17,75 @@
import * as channels from '../protocol/channels';
import * as api from '../../types/types';
import type { Page } from './page';
export class Keyboard implements api.Keyboard {
private _channel: channels.PageChannel;
private _page: Page;
constructor(channel: channels.PageChannel) {
this._channel = channel;
constructor(page: Page) {
this._page = page;
}
async down(key: string) {
await this._channel.keyboardDown({ key });
await this._page._wrapApiCall(async channel => {
await channel.keyboardDown({ key });
});
}
async up(key: string) {
await this._channel.keyboardUp({ key });
await this._page._wrapApiCall(async channel => {
await channel.keyboardUp({ key });
});
}
async insertText(text: string) {
await this._channel.keyboardInsertText({ text });
await this._page._wrapApiCall(async channel => {
await channel.keyboardInsertText({ text });
});
}
async type(text: string, options: channels.PageKeyboardTypeOptions = {}) {
await this._channel.keyboardType({ text, ...options });
await this._page._wrapApiCall(async channel => {
await channel.keyboardType({ text, ...options });
});
}
async press(key: string, options: channels.PageKeyboardPressOptions = {}) {
await this._channel.keyboardPress({ key, ...options });
await this._page._wrapApiCall(async channel => {
await channel.keyboardPress({ key, ...options });
});
}
}
export class Mouse implements api.Mouse {
private _channel: channels.PageChannel;
private _page: Page;
constructor(channel: channels.PageChannel) {
this._channel = channel;
constructor(page: Page) {
this._page = page;
}
async move(x: number, y: number, options: { steps?: number } = {}) {
await this._channel.mouseMove({ x, y, ...options });
await this._page._wrapApiCall(async channel => {
await channel.mouseMove({ x, y, ...options });
});
}
async down(options: channels.PageMouseDownOptions = {}) {
await this._channel.mouseDown({ ...options });
await this._page._wrapApiCall(async channel => {
await channel.mouseDown({ ...options });
});
}
async up(options: channels.PageMouseUpOptions = {}) {
await this._channel.mouseUp(options);
await this._page._wrapApiCall(async channel => {
await channel.mouseUp(options);
});
}
async click(x: number, y: number, options: channels.PageMouseClickOptions = {}) {
await this._channel.mouseClick({ x, y, ...options });
await this._page._wrapApiCall(async channel => {
await channel.mouseClick({ x, y, ...options });
});
}
async dblclick(x: number, y: number, options: Omit<channels.PageMouseClickOptions, 'clickCount'> = {}) {
@ -75,13 +94,15 @@ export class Mouse implements api.Mouse {
}
export class Touchscreen implements api.Touchscreen {
private _channel: channels.PageChannel;
private _page: Page;
constructor(channel: channels.PageChannel) {
this._channel = channel;
constructor(page: Page) {
this._page = page;
}
async tap(x: number, y: number) {
await this._channel.touchscreenTap({x, y});
await this._page._wrapApiCall(async channel => {
await channel.touchscreenTap({x, y});
});
}
}

View File

@ -98,9 +98,9 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
this._timeoutSettings = new TimeoutSettings(this._browserContext._timeoutSettings);
this.accessibility = new Accessibility(this._channel);
this.keyboard = new Keyboard(this._channel);
this.mouse = new Mouse(this._channel);
this.touchscreen = new Touchscreen(this._channel);
this.keyboard = new Keyboard(this);
this.mouse = new Mouse(this);
this.touchscreen = new Touchscreen(this);
this._mainFrame = Frame.from(initializer.mainFrame);
this._mainFrame._page = this;

View File

@ -293,10 +293,10 @@ it('should throw on unknown keys', async ({page, server}) => {
expect(error.message).toContain('Unknown key: "NotARealKey"');
error = await page.keyboard.press('ё').catch(e => e);
expect(error && error.message).toBe('Unknown key: "ё"');
expect(error && error.message).toContain('Unknown key: "ё"');
error = await page.keyboard.press('😊').catch(e => e);
expect(error && error.message).toBe('Unknown key: "😊"');
expect(error && error.message).toContain('Unknown key: "😊"');
});
it('should type emoji', async ({page, server}) => {

View File

@ -25,6 +25,9 @@ test('should collect trace with resources, but no js', async ({ context, page, s
await page.goto(server.PREFIX + '/frames/frame.html');
await page.setContent('<button>Click</button>');
await page.click('"Click"');
await page.mouse.move(20, 20);
await page.mouse.dblclick(30, 30);
await page.keyboard.insertText('abc');
await page.waitForTimeout(2000); // Give it some time to produce screenshots.
await page.close();
await context.tracing.stop({ path: testInfo.outputPath('trace.zip') });
@ -34,6 +37,9 @@ test('should collect trace with resources, but no js', async ({ context, page, s
expect(events.find(e => e.metadata?.apiName === 'page.goto')).toBeTruthy();
expect(events.find(e => e.metadata?.apiName === 'page.setContent')).toBeTruthy();
expect(events.find(e => e.metadata?.apiName === 'page.click')).toBeTruthy();
expect(events.find(e => e.metadata?.apiName === 'mouse.move')).toBeTruthy();
expect(events.find(e => e.metadata?.apiName === 'mouse.dblclick')).toBeTruthy();
expect(events.find(e => e.metadata?.apiName === 'keyboard.insertText')).toBeTruthy();
expect(events.find(e => e.metadata?.apiName === 'page.close')).toBeTruthy();
expect(events.some(e => e.type === 'frame-snapshot')).toBeTruthy();