chore: use api selectors in codegen hover (#17855)
This commit is contained in:
parent
ed6ecbca2a
commit
f2685cab95
|
|
@ -90,8 +90,8 @@ class ProtocolHandler {
|
||||||
this._controller.on(DebugController.Events.BrowsersChanged, browsers => {
|
this._controller.on(DebugController.Events.BrowsersChanged, browsers => {
|
||||||
process.send!({ method: 'browsersChanged', params: { browsers } });
|
process.send!({ method: 'browsersChanged', params: { browsers } });
|
||||||
});
|
});
|
||||||
this._controller.on(DebugController.Events.InspectRequested, selector => {
|
this._controller.on(DebugController.Events.InspectRequested, ({ selector, locators }) => {
|
||||||
process.send!({ method: 'inspectRequested', params: { selector } });
|
process.send!({ method: 'inspectRequested', params: { selector, locators } });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -334,6 +334,7 @@ scheme.RecorderSource = tObject({
|
||||||
scheme.DebugControllerInitializer = tOptional(tObject({}));
|
scheme.DebugControllerInitializer = tOptional(tObject({}));
|
||||||
scheme.DebugControllerInspectRequestedEvent = tObject({
|
scheme.DebugControllerInspectRequestedEvent = tObject({
|
||||||
selector: tString,
|
selector: tString,
|
||||||
|
locators: tArray(tType('NameValue')),
|
||||||
});
|
});
|
||||||
scheme.DebugControllerBrowsersChangedEvent = tObject({
|
scheme.DebugControllerBrowsersChangedEvent = tObject({
|
||||||
browsers: tArray(tObject({
|
browsers: tArray(tObject({
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,9 @@ import type { InstrumentationListener } from './instrumentation';
|
||||||
import type { Playwright } from './playwright';
|
import type { Playwright } from './playwright';
|
||||||
import { Recorder } from './recorder';
|
import { Recorder } from './recorder';
|
||||||
import { EmptyRecorderApp } from './recorder/recorderApp';
|
import { EmptyRecorderApp } from './recorder/recorderApp';
|
||||||
|
import { asLocator } from './isomorphic/locatorGenerators';
|
||||||
|
import type { Language } from './isomorphic/locatorGenerators';
|
||||||
|
import type { NameValue } from '../common/types';
|
||||||
|
|
||||||
const internalMetadata = serverSideCallMetadata();
|
const internalMetadata = serverSideCallMetadata();
|
||||||
|
|
||||||
|
|
@ -215,7 +218,8 @@ class InspectingRecorderApp extends EmptyRecorderApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
override async setSelector(selector: string): Promise<void> {
|
override async setSelector(selector: string): Promise<void> {
|
||||||
this._debugController.emit(DebugController.Events.InspectRequested, selector);
|
const locators: NameValue[] = ['javascript', 'python', 'java', 'csharp'].map(l => ({ name: l, value: asLocator(l as Language, selector) }));
|
||||||
|
this._debugController.emit(DebugController.Events.InspectRequested, { selector, locators });
|
||||||
}
|
}
|
||||||
|
|
||||||
override async setSources(sources: Source[]): Promise<void> {
|
override async setSources(sources: Source[]): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,8 @@ export class DebugControllerDispatcher extends Dispatcher<DebugController, chann
|
||||||
this._object.on(DebugController.Events.BrowsersChanged, browsers => {
|
this._object.on(DebugController.Events.BrowsersChanged, browsers => {
|
||||||
this._dispatchEvent('browsersChanged', { browsers });
|
this._dispatchEvent('browsersChanged', { browsers });
|
||||||
});
|
});
|
||||||
this._object.on(DebugController.Events.InspectRequested, selector => {
|
this._object.on(DebugController.Events.InspectRequested, ({ selector, locators }) => {
|
||||||
this._dispatchEvent('inspectRequested', { selector });
|
this._dispatchEvent('inspectRequested', { selector, locators });
|
||||||
});
|
});
|
||||||
this._object.on(DebugController.Events.SourcesChanged, sources => {
|
this._object.on(DebugController.Events.SourcesChanged, sources => {
|
||||||
this._dispatchEvent('sourcesChanged', { sources });
|
this._dispatchEvent('sourcesChanged', { sources });
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
import { stringifySelector } from '../isomorphic/selectorParser';
|
import { stringifySelector } from '../isomorphic/selectorParser';
|
||||||
import type { ParsedSelector } from '../isomorphic/selectorParser';
|
import type { ParsedSelector } from '../isomorphic/selectorParser';
|
||||||
import type { InjectedScript } from './injectedScript';
|
import type { InjectedScript } from './injectedScript';
|
||||||
|
import { asLocator } from '../isomorphic/locatorGenerators';
|
||||||
|
import type { Language } from '../isomorphic/locatorGenerators';
|
||||||
|
|
||||||
type HighlightEntry = {
|
type HighlightEntry = {
|
||||||
targetElement: Element,
|
targetElement: Element,
|
||||||
|
|
@ -35,6 +37,7 @@ export class Highlight {
|
||||||
private _isUnderTest: boolean;
|
private _isUnderTest: boolean;
|
||||||
private _injectedScript: InjectedScript;
|
private _injectedScript: InjectedScript;
|
||||||
private _rafRequest: number | undefined;
|
private _rafRequest: number | undefined;
|
||||||
|
private _language: Language = 'javascript';
|
||||||
|
|
||||||
constructor(injectedScript: InjectedScript) {
|
constructor(injectedScript: InjectedScript) {
|
||||||
this._injectedScript = injectedScript;
|
this._injectedScript = injectedScript;
|
||||||
|
|
@ -102,6 +105,10 @@ export class Highlight {
|
||||||
document.documentElement.appendChild(this._glassPaneElement);
|
document.documentElement.appendChild(this._glassPaneElement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setLanguage(language: Language) {
|
||||||
|
this._language = language;
|
||||||
|
}
|
||||||
|
|
||||||
runHighlightOnRaf(selector: ParsedSelector) {
|
runHighlightOnRaf(selector: ParsedSelector) {
|
||||||
if (this._rafRequest)
|
if (this._rafRequest)
|
||||||
cancelAnimationFrame(this._rafRequest);
|
cancelAnimationFrame(this._rafRequest);
|
||||||
|
|
@ -145,7 +152,7 @@ export class Highlight {
|
||||||
color = '#dc6f6f7f';
|
color = '#dc6f6f7f';
|
||||||
else
|
else
|
||||||
color = elements.length > 1 ? '#f6b26b7f' : '#6fa8dc7f';
|
color = elements.length > 1 ? '#f6b26b7f' : '#6fa8dc7f';
|
||||||
this._innerUpdateHighlight(elements, { color, tooltipText: selector });
|
this._innerUpdateHighlight(elements, { color, tooltipText: selector ? asLocator(this._language, selector) : '' });
|
||||||
}
|
}
|
||||||
|
|
||||||
maskElements(elements: Element[]) {
|
maskElements(elements: Element[]) {
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,8 @@ class Recorder {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { mode, actionPoint, actionSelector } = state;
|
const { mode, actionPoint, actionSelector, language } = state;
|
||||||
|
this._highlight.setLanguage(language);
|
||||||
if (mode !== this._mode) {
|
if (mode !== this._mode) {
|
||||||
this._mode = mode;
|
this._mode = mode;
|
||||||
this._clearHighlight();
|
this._clearHighlight();
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import type { CSSComplexSelectorList } from '../isomorphic/cssParser';
|
||||||
import { parseAttributeSelector, parseSelector, stringifySelector } from '../isomorphic/selectorParser';
|
import { parseAttributeSelector, parseSelector, stringifySelector } from '../isomorphic/selectorParser';
|
||||||
import type { ParsedSelector } from '../isomorphic/selectorParser';
|
import type { ParsedSelector } from '../isomorphic/selectorParser';
|
||||||
|
|
||||||
type Language = 'javascript' | 'python' | 'java' | 'csharp';
|
export type Language = 'javascript' | 'python' | 'java' | 'csharp';
|
||||||
export type LocatorType = 'default' | 'role' | 'text' | 'label' | 'placeholder' | 'alt' | 'title' | 'test-id' | 'nth' | 'first' | 'last' | 'has-text';
|
export type LocatorType = 'default' | 'role' | 'text' | 'label' | 'placeholder' | 'alt' | 'title' | 'test-id' | 'nth' | 'first' | 'last' | 'has-text';
|
||||||
export type LocatorBase = 'page' | 'locator' | 'frame-locator';
|
export type LocatorBase = 'page' | 'locator' | 'frame-locator';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ import { metadataToCallLog } from './recorder/recorderUtils';
|
||||||
import { Debugger } from './debugger';
|
import { Debugger } from './debugger';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import { raceAgainstTimeout } from '../utils/timeoutRunner';
|
import { raceAgainstTimeout } from '../utils/timeoutRunner';
|
||||||
import type { LanguageGenerator } from './recorder/language';
|
import type { Language, LanguageGenerator } from './recorder/language';
|
||||||
|
|
||||||
type BindingSource = { frame: Frame, page: Page };
|
type BindingSource = { frame: Frame, page: Page };
|
||||||
|
|
||||||
|
|
@ -59,6 +59,7 @@ export class Recorder implements InstrumentationListener {
|
||||||
private _handleSIGINT: boolean | undefined;
|
private _handleSIGINT: boolean | undefined;
|
||||||
private _recorderAppFactory: (recorder: Recorder) => Promise<IRecorderApp>;
|
private _recorderAppFactory: (recorder: Recorder) => Promise<IRecorderApp>;
|
||||||
private _omitCallTracking = false;
|
private _omitCallTracking = false;
|
||||||
|
private _currentLanguage: Language;
|
||||||
|
|
||||||
static showInspector(context: BrowserContext) {
|
static showInspector(context: BrowserContext) {
|
||||||
Recorder.show(context, {}).catch(() => {});
|
Recorder.show(context, {}).catch(() => {});
|
||||||
|
|
@ -83,6 +84,7 @@ export class Recorder implements InstrumentationListener {
|
||||||
this._debugger = Debugger.lookup(context)!;
|
this._debugger = Debugger.lookup(context)!;
|
||||||
this._handleSIGINT = params.handleSIGINT;
|
this._handleSIGINT = params.handleSIGINT;
|
||||||
context.instrumentation.addListener(this, context);
|
context.instrumentation.addListener(this, context);
|
||||||
|
this._currentLanguage = this._contextRecorder.languageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async defaultRecorderAppFactory(recorder: Recorder) {
|
private static async defaultRecorderAppFactory(recorder: Recorder) {
|
||||||
|
|
@ -111,6 +113,11 @@ export class Recorder implements InstrumentationListener {
|
||||||
this._debugger.resume(true);
|
this._debugger.resume(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (data.event === 'fileChanged') {
|
||||||
|
this._currentLanguage = this._contextRecorder.languageName(data.params.file);
|
||||||
|
this._refreshOverlay();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (data.event === 'resume') {
|
if (data.event === 'resume') {
|
||||||
this._debugger.resume(false);
|
this._debugger.resume(false);
|
||||||
return;
|
return;
|
||||||
|
|
@ -155,6 +162,7 @@ export class Recorder implements InstrumentationListener {
|
||||||
mode: this._mode,
|
mode: this._mode,
|
||||||
actionPoint,
|
actionPoint,
|
||||||
actionSelector,
|
actionSelector,
|
||||||
|
language: this._currentLanguage
|
||||||
};
|
};
|
||||||
return uiState;
|
return uiState;
|
||||||
});
|
});
|
||||||
|
|
@ -381,6 +389,14 @@ class ContextRecorder extends EventEmitter {
|
||||||
this._generator?.restart();
|
this._generator?.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
languageName(id?: string): Language {
|
||||||
|
for (const lang of this._orderedLanguages) {
|
||||||
|
if (!id || lang.id === id)
|
||||||
|
return lang.highlighter;
|
||||||
|
}
|
||||||
|
return 'javascript';
|
||||||
|
}
|
||||||
|
|
||||||
async install() {
|
async install() {
|
||||||
this._context.on(BrowserContext.Events.Page, page => this._onPage(page));
|
this._context.on(BrowserContext.Events.Page, page => this._onPage(page));
|
||||||
for (const page of this._context.pages())
|
for (const page of this._context.pages())
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BrowserContextOptions } from '../../..';
|
import type { BrowserContextOptions } from '../../..';
|
||||||
import type { LanguageGenerator, LanguageGeneratorOptions } from './language';
|
import type { Language, LanguageGenerator, LanguageGeneratorOptions } from './language';
|
||||||
import { sanitizeDeviceOptions, toSignalMap } from './language';
|
import { sanitizeDeviceOptions, toSignalMap } from './language';
|
||||||
import type { ActionInContext } from './codeGenerator';
|
import type { ActionInContext } from './codeGenerator';
|
||||||
import type { Action } from './recorderActions';
|
import type { Action } from './recorderActions';
|
||||||
|
|
@ -31,7 +31,7 @@ export class CSharpLanguageGenerator implements LanguageGenerator {
|
||||||
id: string;
|
id: string;
|
||||||
groupName = '.NET C#';
|
groupName = '.NET C#';
|
||||||
name: string;
|
name: string;
|
||||||
highlighter = 'csharp';
|
highlighter = 'csharp' as Language;
|
||||||
_mode: CSharpLanguageMode;
|
_mode: CSharpLanguageMode;
|
||||||
|
|
||||||
constructor(mode: CSharpLanguageMode) {
|
constructor(mode: CSharpLanguageMode) {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BrowserContextOptions } from '../../..';
|
import type { BrowserContextOptions } from '../../..';
|
||||||
import type { LanguageGenerator, LanguageGeneratorOptions } from './language';
|
import type { Language, LanguageGenerator, LanguageGeneratorOptions } from './language';
|
||||||
import { toSignalMap } from './language';
|
import { toSignalMap } from './language';
|
||||||
import type { ActionInContext } from './codeGenerator';
|
import type { ActionInContext } from './codeGenerator';
|
||||||
import type { Action } from './recorderActions';
|
import type { Action } from './recorderActions';
|
||||||
|
|
@ -30,7 +30,7 @@ export class JavaLanguageGenerator implements LanguageGenerator {
|
||||||
id = 'java';
|
id = 'java';
|
||||||
groupName = 'Java';
|
groupName = 'Java';
|
||||||
name = 'Library';
|
name = 'Library';
|
||||||
highlighter = 'java';
|
highlighter = 'java' as Language;
|
||||||
|
|
||||||
generateAction(actionInContext: ActionInContext): string {
|
generateAction(actionInContext: ActionInContext): string {
|
||||||
const action = actionInContext.action;
|
const action = actionInContext.action;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BrowserContextOptions } from '../../..';
|
import type { BrowserContextOptions } from '../../..';
|
||||||
import type { LanguageGenerator, LanguageGeneratorOptions } from './language';
|
import type { Language, LanguageGenerator, LanguageGeneratorOptions } from './language';
|
||||||
import { sanitizeDeviceOptions, toSignalMap } from './language';
|
import { sanitizeDeviceOptions, toSignalMap } from './language';
|
||||||
import type { ActionInContext } from './codeGenerator';
|
import type { ActionInContext } from './codeGenerator';
|
||||||
import type { Action } from './recorderActions';
|
import type { Action } from './recorderActions';
|
||||||
|
|
@ -29,7 +29,7 @@ export class JavaScriptLanguageGenerator implements LanguageGenerator {
|
||||||
id: string;
|
id: string;
|
||||||
groupName = 'Node.js';
|
groupName = 'Node.js';
|
||||||
name: string;
|
name: string;
|
||||||
highlighter = 'javascript';
|
highlighter = 'javascript' as Language;
|
||||||
private _isTest: boolean;
|
private _isTest: boolean;
|
||||||
|
|
||||||
constructor(isTest: boolean) {
|
constructor(isTest: boolean) {
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BrowserContextOptions, LaunchOptions } from '../../..';
|
import type { BrowserContextOptions, LaunchOptions } from '../../..';
|
||||||
|
import type { Language } from '../isomorphic/locatorGenerators';
|
||||||
import type { ActionInContext } from './codeGenerator';
|
import type { ActionInContext } from './codeGenerator';
|
||||||
import type { Action, DialogSignal, DownloadSignal, NavigationSignal, PopupSignal } from './recorderActions';
|
import type { Action, DialogSignal, DownloadSignal, NavigationSignal, PopupSignal } from './recorderActions';
|
||||||
|
export type { Language } from '../isomorphic/locatorGenerators';
|
||||||
|
|
||||||
export type LanguageGeneratorOptions = {
|
export type LanguageGeneratorOptions = {
|
||||||
browserName: string;
|
browserName: string;
|
||||||
|
|
@ -33,7 +35,7 @@ export interface LanguageGenerator {
|
||||||
id: string;
|
id: string;
|
||||||
groupName: string;
|
groupName: string;
|
||||||
name: string;
|
name: string;
|
||||||
highlighter: string;
|
highlighter: Language;
|
||||||
generateHeader(options: LanguageGeneratorOptions): string;
|
generateHeader(options: LanguageGeneratorOptions): string;
|
||||||
generateAction(actionInContext: ActionInContext): string;
|
generateAction(actionInContext: ActionInContext): string;
|
||||||
generateFooter(saveStorage: string | undefined): string;
|
generateFooter(saveStorage: string | undefined): string;
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { BrowserContextOptions } from '../../..';
|
import type { BrowserContextOptions } from '../../..';
|
||||||
import type { LanguageGenerator, LanguageGeneratorOptions } from './language';
|
import type { Language, LanguageGenerator, LanguageGeneratorOptions } from './language';
|
||||||
import { sanitizeDeviceOptions, toSignalMap } from './language';
|
import { sanitizeDeviceOptions, toSignalMap } from './language';
|
||||||
import type { ActionInContext } from './codeGenerator';
|
import type { ActionInContext } from './codeGenerator';
|
||||||
import type { Action } from './recorderActions';
|
import type { Action } from './recorderActions';
|
||||||
|
|
@ -29,7 +29,7 @@ export class PythonLanguageGenerator implements LanguageGenerator {
|
||||||
id: string;
|
id: string;
|
||||||
groupName = 'Python';
|
groupName = 'Python';
|
||||||
name: string;
|
name: string;
|
||||||
highlighter = 'python';
|
highlighter = 'python' as Language;
|
||||||
|
|
||||||
private _awaitPrefix: '' | 'await ';
|
private _awaitPrefix: '' | 'await ';
|
||||||
private _asyncPrefix: '' | 'async ';
|
private _asyncPrefix: '' | 'async ';
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,7 @@ export function toTitleCase(name: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function toSnakeCase(name: string): string {
|
export function toSnakeCase(name: string): string {
|
||||||
const toSnakeCaseRegex = /((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z]))/g;
|
return name.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
|
||||||
return name.replace(toSnakeCaseRegex, `_$1`).toLowerCase();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cssEscape(s: string): string {
|
export function cssEscape(s: string): string {
|
||||||
|
|
|
||||||
|
|
@ -610,6 +610,7 @@ export interface DebugControllerChannel extends DebugControllerEventTarget, Chan
|
||||||
}
|
}
|
||||||
export type DebugControllerInspectRequestedEvent = {
|
export type DebugControllerInspectRequestedEvent = {
|
||||||
selector: string,
|
selector: string,
|
||||||
|
locators: NameValue[],
|
||||||
};
|
};
|
||||||
export type DebugControllerBrowsersChangedEvent = {
|
export type DebugControllerBrowsersChangedEvent = {
|
||||||
browsers: {
|
browsers: {
|
||||||
|
|
|
||||||
|
|
@ -693,6 +693,9 @@ DebugController:
|
||||||
inspectRequested:
|
inspectRequested:
|
||||||
parameters:
|
parameters:
|
||||||
selector: string
|
selector: string
|
||||||
|
locators:
|
||||||
|
type: array
|
||||||
|
items: NameValue
|
||||||
|
|
||||||
browsersChanged:
|
browsersChanged:
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@ export const Recorder: React.FC<RecorderProps> = ({
|
||||||
<div>Target:</div>
|
<div>Target:</div>
|
||||||
<select className='recorder-chooser' hidden={!sources.length} value={fileId} onChange={event => {
|
<select className='recorder-chooser' hidden={!sources.length} value={fileId} onChange={event => {
|
||||||
setFileId(event.target.selectedOptions[0].value);
|
setFileId(event.target.selectedOptions[0].value);
|
||||||
|
window.dispatch({ event: 'fileChanged', params: { file: event.target.selectedOptions[0].value } });
|
||||||
}}>{renderSourceOptions(sources)}</select>
|
}}>{renderSourceOptions(sources)}</select>
|
||||||
<ToolbarButton icon='clear-all' title='Clear' disabled={!source || !source.text} onClick={() => {
|
<ToolbarButton icon='clear-all' title='Clear' disabled={!source || !source.text} onClick={() => {
|
||||||
window.dispatch({ event: 'clear' });
|
window.dispatch({ event: 'clear' });
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export type Point = { x: number, y: number };
|
||||||
export type Mode = 'inspecting' | 'recording' | 'none';
|
export type Mode = 'inspecting' | 'recording' | 'none';
|
||||||
|
|
||||||
export type EventData = {
|
export type EventData = {
|
||||||
event: 'clear' | 'resume' | 'step' | 'pause' | 'setMode' | 'selectorUpdated';
|
event: 'clear' | 'resume' | 'step' | 'pause' | 'setMode' | 'selectorUpdated' | 'fileChanged';
|
||||||
params: any;
|
params: any;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -27,6 +27,7 @@ export type UIState = {
|
||||||
mode: Mode;
|
mode: Mode;
|
||||||
actionPoint?: Point;
|
actionPoint?: Point;
|
||||||
actionSelector?: string;
|
actionSelector?: string;
|
||||||
|
language: 'javascript' | 'python' | 'java' | 'csharp';
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CallLogStatus = 'in-progress' | 'done' | 'error' | 'paused';
|
export type CallLogStatus = 'in-progress' | 'done' | 'error' | 'paused';
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ it('should highlight locator', async ({ page, isAndroid }) => {
|
||||||
const textPromise = waitForTestLog<string>(page, 'Highlight text for test: ');
|
const textPromise = waitForTestLog<string>(page, 'Highlight text for test: ');
|
||||||
const boxPromise = waitForTestLog<{ x: number, y: number, width: number, height: number }>(page, 'Highlight box for test: ');
|
const boxPromise = waitForTestLog<{ x: number, y: number, width: number, height: number }>(page, 'Highlight box for test: ');
|
||||||
await page.locator('input').highlight();
|
await page.locator('input').highlight();
|
||||||
expect(await textPromise).toBe('input');
|
expect(await textPromise).toBe('locator(\'input\')');
|
||||||
let box1 = await page.locator('input').boundingBox();
|
let box1 = await page.locator('input').boundingBox();
|
||||||
let box2 = await boxPromise;
|
let box2 = await boxPromise;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue