mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: extract polling recorder (#32749)
We are reusing recorder in a snapshot tab, no need for the polling harness to be there.
This commit is contained in:
parent
99895005e2
commit
0cdc7ee1a3
@ -0,0 +1,91 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) Microsoft Corporation.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type { Mode, OverlayState, UIState } from '@recorder/recorderTypes';
|
||||||
|
import type * as actions from '../../recorder/recorderActions';
|
||||||
|
import type { InjectedScript } from '../injectedScript';
|
||||||
|
import { Recorder } from './recorder';
|
||||||
|
import type { RecorderDelegate } from './recorder';
|
||||||
|
|
||||||
|
interface Embedder {
|
||||||
|
__pw_recorderPerformAction(action: actions.PerformOnRecordAction): Promise<void>;
|
||||||
|
__pw_recorderRecordAction(action: actions.Action): Promise<void>;
|
||||||
|
__pw_recorderState(): Promise<UIState>;
|
||||||
|
__pw_recorderSetSelector(selector: string): Promise<void>;
|
||||||
|
__pw_recorderSetMode(mode: Mode): Promise<void>;
|
||||||
|
__pw_recorderSetOverlayState(state: OverlayState): Promise<void>;
|
||||||
|
__pw_refreshOverlay(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class PollingRecorder implements RecorderDelegate {
|
||||||
|
private _recorder: Recorder;
|
||||||
|
private _embedder: Embedder;
|
||||||
|
private _pollRecorderModeTimer: number | undefined;
|
||||||
|
|
||||||
|
constructor(injectedScript: InjectedScript) {
|
||||||
|
this._recorder = new Recorder(injectedScript);
|
||||||
|
this._embedder = injectedScript.window as any;
|
||||||
|
|
||||||
|
injectedScript.onGlobalListenersRemoved.add(() => this._recorder.installListeners());
|
||||||
|
|
||||||
|
const refreshOverlay = () => {
|
||||||
|
this._pollRecorderMode().catch(e => console.log(e)); // eslint-disable-line no-console
|
||||||
|
};
|
||||||
|
this._embedder.__pw_refreshOverlay = refreshOverlay;
|
||||||
|
refreshOverlay();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _pollRecorderMode() {
|
||||||
|
const pollPeriod = 1000;
|
||||||
|
if (this._pollRecorderModeTimer)
|
||||||
|
clearTimeout(this._pollRecorderModeTimer);
|
||||||
|
const state = await this._embedder.__pw_recorderState().catch(() => {});
|
||||||
|
if (!state) {
|
||||||
|
this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const win = this._recorder.document.defaultView!;
|
||||||
|
if (win.top !== win) {
|
||||||
|
// Only show action point in the main frame, since it is relative to the page's viewport.
|
||||||
|
// Otherwise we'll see multiple action points at different locations.
|
||||||
|
state.actionPoint = undefined;
|
||||||
|
}
|
||||||
|
this._recorder.setUIState(state, this);
|
||||||
|
this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);
|
||||||
|
}
|
||||||
|
|
||||||
|
async performAction(action: actions.PerformOnRecordAction) {
|
||||||
|
await this._embedder.__pw_recorderPerformAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
async recordAction(action: actions.Action): Promise<void> {
|
||||||
|
await this._embedder.__pw_recorderRecordAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setSelector(selector: string): Promise<void> {
|
||||||
|
await this._embedder.__pw_recorderSetSelector(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setMode(mode: Mode): Promise<void> {
|
||||||
|
await this._embedder.__pw_recorderSetMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setOverlayState(state: OverlayState): Promise<void> {
|
||||||
|
await this._embedder.__pw_recorderSetOverlayState(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PollingRecorder;
|
||||||
@ -21,9 +21,8 @@ import type { Mode, OverlayState, UIState } from '@recorder/recorderTypes';
|
|||||||
import type { ElementText } from '../selectorUtils';
|
import type { ElementText } from '../selectorUtils';
|
||||||
import type { Highlight, HighlightOptions } from '../highlight';
|
import type { Highlight, HighlightOptions } from '../highlight';
|
||||||
import clipPaths from './clipPaths';
|
import clipPaths from './clipPaths';
|
||||||
import type { SimpleDomNode } from '../simpleDom';
|
|
||||||
|
|
||||||
interface RecorderDelegate {
|
export interface RecorderDelegate {
|
||||||
performAction?(action: actions.PerformOnRecordAction): Promise<void>;
|
performAction?(action: actions.PerformOnRecordAction): Promise<void>;
|
||||||
recordAction?(action: actions.Action): Promise<void>;
|
recordAction?(action: actions.Action): Promise<void>;
|
||||||
setSelector?(selector: string): Promise<void>;
|
setSelector?(selector: string): Promise<void>;
|
||||||
@ -1457,73 +1456,3 @@ function createSvgElement(doc: Document, { tagName, attrs, children }: SvgJson):
|
|||||||
|
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Embedder {
|
|
||||||
__pw_recorderPerformAction(action: actions.PerformOnRecordAction, simpleDomNode?: SimpleDomNode): Promise<void>;
|
|
||||||
__pw_recorderRecordAction(action: actions.Action, simpleDomNode?: SimpleDomNode): Promise<void>;
|
|
||||||
__pw_recorderState(): Promise<UIState>;
|
|
||||||
__pw_recorderSetSelector(selector: string): Promise<void>;
|
|
||||||
__pw_recorderSetMode(mode: Mode): Promise<void>;
|
|
||||||
__pw_recorderSetOverlayState(state: OverlayState): Promise<void>;
|
|
||||||
__pw_refreshOverlay(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class PollingRecorder implements RecorderDelegate {
|
|
||||||
private _recorder: Recorder;
|
|
||||||
private _embedder: Embedder;
|
|
||||||
private _pollRecorderModeTimer: number | undefined;
|
|
||||||
|
|
||||||
constructor(injectedScript: InjectedScript) {
|
|
||||||
this._recorder = new Recorder(injectedScript);
|
|
||||||
this._embedder = injectedScript.window as any;
|
|
||||||
|
|
||||||
injectedScript.onGlobalListenersRemoved.add(() => this._recorder.installListeners());
|
|
||||||
|
|
||||||
const refreshOverlay = () => {
|
|
||||||
this._pollRecorderMode().catch(e => console.log(e)); // eslint-disable-line no-console
|
|
||||||
};
|
|
||||||
this._embedder.__pw_refreshOverlay = refreshOverlay;
|
|
||||||
refreshOverlay();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _pollRecorderMode() {
|
|
||||||
const pollPeriod = 1000;
|
|
||||||
if (this._pollRecorderModeTimer)
|
|
||||||
clearTimeout(this._pollRecorderModeTimer);
|
|
||||||
const state = await this._embedder.__pw_recorderState().catch(() => {});
|
|
||||||
if (!state) {
|
|
||||||
this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const win = this._recorder.document.defaultView!;
|
|
||||||
if (win.top !== win) {
|
|
||||||
// Only show action point in the main frame, since it is relative to the page's viewport.
|
|
||||||
// Otherwise we'll see multiple action points at different locations.
|
|
||||||
state.actionPoint = undefined;
|
|
||||||
}
|
|
||||||
this._recorder.setUIState(state, this);
|
|
||||||
this._pollRecorderModeTimer = this._recorder.injectedScript.builtinSetTimeout(() => this._pollRecorderMode(), pollPeriod);
|
|
||||||
}
|
|
||||||
|
|
||||||
async performAction(action: actions.PerformOnRecordAction, simpleDomNode?: SimpleDomNode) {
|
|
||||||
await this._embedder.__pw_recorderPerformAction(action, simpleDomNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
async recordAction(action: actions.Action, simpleDomNode?: SimpleDomNode): Promise<void> {
|
|
||||||
await this._embedder.__pw_recorderRecordAction(action, simpleDomNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
async setSelector(selector: string): Promise<void> {
|
|
||||||
await this._embedder.__pw_recorderSetSelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
async setMode(mode: Mode): Promise<void> {
|
|
||||||
await this._embedder.__pw_recorderSetMode(mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
async setOverlayState(state: OverlayState): Promise<void> {
|
|
||||||
await this._embedder.__pw_recorderSetOverlayState(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default PollingRecorder;
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
../isomorphic/**
|
../isomorphic/**
|
||||||
../registry/**
|
../registry/**
|
||||||
../../common/
|
../../common/
|
||||||
../../generated/recorderSource.ts
|
../../generated/pollingRecorderSource.ts
|
||||||
../../protocol/
|
../../protocol/
|
||||||
../../utils/**
|
../../utils/**
|
||||||
../../utilsBundle.ts
|
../../utilsBundle.ts
|
||||||
|
|||||||
@ -17,7 +17,7 @@
|
|||||||
import type * as channels from '@protocol/channels';
|
import type * as channels from '@protocol/channels';
|
||||||
import type { Source } from '@recorder/recorderTypes';
|
import type { Source } from '@recorder/recorderTypes';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import * as recorderSource from '../../generated/recorderSource';
|
import * as recorderSource from '../../generated/pollingRecorderSource';
|
||||||
import { eventsHelper, monotonicTime, quoteCSSAttributeValue, type RegisteredListener } from '../../utils';
|
import { eventsHelper, monotonicTime, quoteCSSAttributeValue, type RegisteredListener } from '../../utils';
|
||||||
import { raceAgainstDeadline } from '../../utils/timeoutRunner';
|
import { raceAgainstDeadline } from '../../utils/timeoutRunner';
|
||||||
import { BrowserContext } from '../browserContext';
|
import { BrowserContext } from '../browserContext';
|
||||||
|
|||||||
@ -45,7 +45,7 @@ const injectedScripts = [
|
|||||||
true,
|
true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
path.join(ROOT, 'packages', 'playwright-core', 'src', 'server', 'injected', 'recorder', 'recorder.ts'),
|
path.join(ROOT, 'packages', 'playwright-core', 'src', 'server', 'injected', 'recorder', 'pollingRecorder.ts'),
|
||||||
path.join(ROOT, 'packages', 'playwright-core', 'lib', 'server', 'injected', 'packed'),
|
path.join(ROOT, 'packages', 'playwright-core', 'lib', 'server', 'injected', 'packed'),
|
||||||
path.join(ROOT, 'packages', 'playwright-core', 'src', 'generated'),
|
path.join(ROOT, 'packages', 'playwright-core', 'src', 'generated'),
|
||||||
true,
|
true,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user