From 5eed91a9574778d70ec88ada23efebbb9266ce6d Mon Sep 17 00:00:00 2001 From: Pavel Feldman Date: Thu, 12 Dec 2024 10:41:22 -0800 Subject: [PATCH] chore: disable mode controller when connecting via debug controller --- .../src/server/debugController.ts | 4 ++++ .../src/server/injected/highlight.css | 19 ++++++++++++------ .../src/server/injected/recorder/recorder.ts | 20 +++++++++++++------ .../playwright-core/src/server/recorder.ts | 1 + .../src/server/recorder/recorderApp.ts | 5 +++++ .../src/server/recorder/recorderFrontend.ts | 1 + .../server/recorder/recorderInTraceViewer.ts | 4 ++++ packages/recorder/src/recorderTypes.ts | 1 + packages/trace-viewer/src/ui/snapshotTab.tsx | 1 + 9 files changed, 44 insertions(+), 12 deletions(-) diff --git a/packages/playwright-core/src/server/debugController.ts b/packages/playwright-core/src/server/debugController.ts index 8878ecb59cbe5..4174129f12908 100644 --- a/packages/playwright-core/src/server/debugController.ts +++ b/packages/playwright-core/src/server/debugController.ts @@ -226,6 +226,10 @@ class InspectingRecorderApp extends EmptyRecorderApp { this._debugController = debugController; } + override disableModeController(): boolean { + return true; + } + override async elementPicked(elementInfo: ElementInfo): Promise { const locator: string = asLocator(this._debugController._sdkLanguage, elementInfo.selector); this._debugController.emit(DebugController.Events.InspectRequested, { selector: elementInfo.selector, locator, ariaSnapshot: elementInfo.ariaSnapshot }); diff --git a/packages/playwright-core/src/server/injected/highlight.css b/packages/playwright-core/src/server/injected/highlight.css index 096f9311611c4..3acfd3fb1c776 100644 --- a/packages/playwright-core/src/server/injected/highlight.css +++ b/packages/playwright-core/src/server/injected/highlight.css @@ -149,21 +149,24 @@ x-pw-tools-list { x-pw-tool-item { pointer-events: auto; - cursor: pointer; height: 28px; width: 28px; border-radius: 3px; } +x-pw-tool-item:not(.disabled) { + cursor: pointer; +} + x-pw-tool-item:not(.disabled):hover { background-color: hsl(0, 0%, 86%); } -x-pw-tool-item.active { +x-pw-tool-item.toggled { background-color: rgba(138, 202, 228, 0.5); } -x-pw-tool-item.active:not(.disabled):hover { +x-pw-tool-item.toggled:not(.disabled):hover { background-color: #8acae4c4; } @@ -179,18 +182,22 @@ x-pw-tool-item.disabled > x-div { cursor: default; } -x-pw-tool-item.record.active { +x-pw-tool-item.record.toggled { background-color: transparent; } -x-pw-tool-item.record.active:hover { +x-pw-tool-item.record.toggled:not(.disabled):hover { background-color: hsl(0, 0%, 86%); } -x-pw-tool-item.record.active > x-div { +x-pw-tool-item.record.toggled > x-div { background-color: #a1260d; } +x-pw-tool-item.record.disabled.toggled > x-div { + opacity: 0.8; +} + x-pw-tool-item.accept > x-div { background-color: #388a34; } diff --git a/packages/playwright-core/src/server/injected/recorder/recorder.ts b/packages/playwright-core/src/server/injected/recorder/recorder.ts index 73740357061ee..45d2d32da294a 100644 --- a/packages/playwright-core/src/server/injected/recorder/recorder.ts +++ b/packages/playwright-core/src/server/injected/recorder/recorder.ts @@ -883,9 +883,13 @@ class Overlay { this._dragState = { offsetX: this._offsetX, dragStart: { x: (event as MouseEvent).clientX, y: 0 } }; }), addEventListener(this._recordToggle, 'click', () => { + if (this._recordToggle.classList.contains('disabled')) + return; this._recorder.setMode(this._recorder.state.mode === 'none' || this._recorder.state.mode === 'standby' || this._recorder.state.mode === 'inspecting' ? 'recording' : 'standby'); }), addEventListener(this._pickLocatorToggle, 'click', () => { + if (this._pickLocatorToggle.classList.contains('disabled')) + return; const newMode: Record = { 'inspecting': 'standby', 'none': 'inspecting', @@ -929,15 +933,18 @@ class Overlay { } setUIState(state: UIState) { - this._recordToggle.classList.toggle('active', state.mode === 'recording' || state.mode === 'assertingText' || state.mode === 'assertingVisibility' || state.mode === 'assertingValue' || state.mode === 'recording-inspecting'); - this._pickLocatorToggle.classList.toggle('active', state.mode === 'inspecting' || state.mode === 'recording-inspecting'); - this._assertVisibilityToggle.classList.toggle('active', state.mode === 'assertingVisibility'); + this._recordToggle.classList.toggle('disabled', this._recorder.state.disableModeController); + this._pickLocatorToggle.classList.toggle('disabled', this._recorder.state.disableModeController); + + this._recordToggle.classList.toggle('toggled', state.mode === 'recording' || state.mode === 'assertingText' || state.mode === 'assertingVisibility' || state.mode === 'assertingValue' || state.mode === 'assertingSnapshot' || state.mode === 'recording-inspecting'); + this._pickLocatorToggle.classList.toggle('toggled', state.mode === 'inspecting' || state.mode === 'recording-inspecting'); + this._assertVisibilityToggle.classList.toggle('toggled', state.mode === 'assertingVisibility'); this._assertVisibilityToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); - this._assertTextToggle.classList.toggle('active', state.mode === 'assertingText'); + this._assertTextToggle.classList.toggle('toggled', state.mode === 'assertingText'); this._assertTextToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); - this._assertValuesToggle.classList.toggle('active', state.mode === 'assertingValue'); + this._assertValuesToggle.classList.toggle('toggled', state.mode === 'assertingValue'); this._assertValuesToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); - this._assertSnapshotToggle.classList.toggle('active', state.mode === 'assertingSnapshot'); + this._assertSnapshotToggle.classList.toggle('toggled', state.mode === 'assertingSnapshot'); this._assertSnapshotToggle.classList.toggle('disabled', state.mode === 'none' || state.mode === 'standby' || state.mode === 'inspecting'); if (this._offsetX !== state.overlay.offsetX) { this._offsetX = state.overlay.offsetX; @@ -1031,6 +1038,7 @@ export class Recorder { testIdAttributeName: 'data-testid', language: 'javascript', overlay: { offsetX: 0 }, + disableModeController: false, }; readonly document: Document; private _delegate: RecorderDelegate = {}; diff --git a/packages/playwright-core/src/server/recorder.ts b/packages/playwright-core/src/server/recorder.ts index 16f9d791e1610..9a482c5e23c34 100644 --- a/packages/playwright-core/src/server/recorder.ts +++ b/packages/playwright-core/src/server/recorder.ts @@ -177,6 +177,7 @@ export class Recorder implements InstrumentationListener, IRecorder { language: this._currentLanguage, testIdAttributeName: this._contextRecorder.testIdAttributeName(), overlay: this._overlayState, + disableModeController: this._recorderApp ? this._recorderApp.disableModeController() : true, }; return uiState; }); diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index f8971531cf81e..f6c68e8844b76 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -39,6 +39,7 @@ export class EmptyRecorderApp extends EventEmitter implements IRecorderApp { async updateCallLogs(callLogs: CallLog[]): Promise {} async setSources(sources: Source[]): Promise {} async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise {} + disableModeController(): boolean { return false; } } export class RecorderApp extends EventEmitter implements IRecorderApp { @@ -171,4 +172,8 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { window.playwrightUpdateLogs(callLogs); }).toString(), { isFunction: true }, callLogs).catch(() => {}); } + + disableModeController(): boolean { + return false; + } } diff --git a/packages/playwright-core/src/server/recorder/recorderFrontend.ts b/packages/playwright-core/src/server/recorder/recorderFrontend.ts index b3dc0daad9bd8..98c7fa7c3721b 100644 --- a/packages/playwright-core/src/server/recorder/recorderFrontend.ts +++ b/packages/playwright-core/src/server/recorder/recorderFrontend.ts @@ -34,6 +34,7 @@ export interface IRecorderApp extends EventEmitter { updateCallLogs(callLogs: CallLog[]): Promise; setSources(sources: Source[]): Promise; setActions(actions: actions.ActionInContext[], sources: Source[]): Promise; + disableModeController(): boolean; } export type IRecorderAppFactory = (recorder: IRecorder) => Promise; diff --git a/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts b/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts index fcfd0a36c5331..c18a82ac10e91 100644 --- a/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts +++ b/packages/playwright-core/src/server/recorder/recorderInTraceViewer.ts @@ -89,6 +89,10 @@ export class RecorderInTraceViewer extends EventEmitter implements IRecorderApp async setActions(actions: actions.ActionInContext[], sources: Source[]): Promise { this._transport.deliverEvent('setActions', { actions, sources }); } + + disableModeController(): boolean { + return true; + } } async function openApp(trace: string, options?: TraceViewerServerOptions & { headless?: boolean }): Promise<{ wsEndpointForTest: string | undefined, tracePage: Page, traceServer: HttpServer }> { diff --git a/packages/recorder/src/recorderTypes.ts b/packages/recorder/src/recorderTypes.ts index 4822dda46f2bd..817a3db2af3a2 100644 --- a/packages/recorder/src/recorderTypes.ts +++ b/packages/recorder/src/recorderTypes.ts @@ -59,6 +59,7 @@ export type UIState = { language: Language; testIdAttributeName: string; overlay: OverlayState; + disableModeController: boolean; }; export type CallLogStatus = 'in-progress' | 'done' | 'error' | 'paused'; diff --git a/packages/trace-viewer/src/ui/snapshotTab.tsx b/packages/trace-viewer/src/ui/snapshotTab.tsx index 995e2d173f7c0..f12a85c615988 100644 --- a/packages/trace-viewer/src/ui/snapshotTab.tsx +++ b/packages/trace-viewer/src/ui/snapshotTab.tsx @@ -237,6 +237,7 @@ export const InspectModeController: React.FunctionComponent<{ const actionSelector = locatorOrSelectorAsSelector(sdkLanguage, highlightedLocator, testIdAttributeName); recorder.setUIState({ mode: isInspecting ? 'inspecting' : 'none', + disableModeController: true, actionSelector: actionSelector.startsWith(frameSelector) ? actionSelector.substring(frameSelector.length).trim() : undefined, language: sdkLanguage, testIdAttributeName,