212 lines
7.4 KiB
JavaScript
212 lines
7.4 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
Object.defineProperty(exports, "__esModule", {
|
||
|
value: true
|
||
|
});
|
||
|
exports.DebugController = void 0;
|
||
|
var _instrumentation = require("./instrumentation");
|
||
|
var _processLauncher = require("./utils/processLauncher");
|
||
|
var _recorder = require("./recorder");
|
||
|
var _utils = require("../utils");
|
||
|
var _ariaSnapshot = require("../utils/isomorphic/ariaSnapshot");
|
||
|
var _utilsBundle = require("../utilsBundle");
|
||
|
var _recorderApp = require("./recorder/recorderApp");
|
||
|
var _locatorParser = require("../utils/isomorphic/locatorParser");
|
||
|
/**
|
||
|
* 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.
|
||
|
*/
|
||
|
|
||
|
const internalMetadata = (0, _instrumentation.serverSideCallMetadata)();
|
||
|
class DebugController extends _instrumentation.SdkObject {
|
||
|
constructor(playwright) {
|
||
|
super({
|
||
|
attribution: {
|
||
|
isInternalPlaywright: true
|
||
|
},
|
||
|
instrumentation: (0, _instrumentation.createInstrumentation)()
|
||
|
}, undefined, 'DebugController');
|
||
|
this._trackHierarchyListener = void 0;
|
||
|
this._playwright = void 0;
|
||
|
this._sdkLanguage = 'javascript';
|
||
|
this._codegenId = 'playwright-test';
|
||
|
this._playwright = playwright;
|
||
|
}
|
||
|
initialize(codegenId, sdkLanguage) {
|
||
|
this._codegenId = codegenId;
|
||
|
this._sdkLanguage = sdkLanguage;
|
||
|
}
|
||
|
dispose() {
|
||
|
this.setReportStateChanged(false);
|
||
|
}
|
||
|
setReportStateChanged(enabled) {
|
||
|
if (enabled && !this._trackHierarchyListener) {
|
||
|
this._trackHierarchyListener = {
|
||
|
onPageOpen: () => this._emitSnapshot(false),
|
||
|
onPageClose: () => this._emitSnapshot(false)
|
||
|
};
|
||
|
this._playwright.instrumentation.addListener(this._trackHierarchyListener, null);
|
||
|
this._emitSnapshot(true);
|
||
|
} else if (!enabled && this._trackHierarchyListener) {
|
||
|
this._playwright.instrumentation.removeListener(this._trackHierarchyListener);
|
||
|
this._trackHierarchyListener = undefined;
|
||
|
}
|
||
|
}
|
||
|
async resetForReuse() {
|
||
|
const contexts = new Set();
|
||
|
for (const page of this._playwright.allPages()) contexts.add(page.context());
|
||
|
for (const context of contexts) await context.resetForReuse(internalMetadata, null);
|
||
|
}
|
||
|
async navigate(url) {
|
||
|
for (const p of this._playwright.allPages()) await p.mainFrame().goto(internalMetadata, url);
|
||
|
}
|
||
|
async setRecorderMode(params) {
|
||
|
// TODO: |file| is only used in the legacy mode.
|
||
|
await this._closeBrowsersWithoutPages();
|
||
|
if (params.mode === 'none') {
|
||
|
for (const recorder of await this._allRecorders()) {
|
||
|
recorder.hideHighlightedSelector();
|
||
|
recorder.setMode('none');
|
||
|
}
|
||
|
return;
|
||
|
}
|
||
|
if (!this._playwright.allBrowsers().length) await this._playwright.chromium.launch(internalMetadata, {
|
||
|
headless: !!process.env.PW_DEBUG_CONTROLLER_HEADLESS
|
||
|
});
|
||
|
// Create page if none.
|
||
|
const pages = this._playwright.allPages();
|
||
|
if (!pages.length) {
|
||
|
const [browser] = this._playwright.allBrowsers();
|
||
|
const {
|
||
|
context
|
||
|
} = await browser.newContextForReuse({}, internalMetadata);
|
||
|
await context.newPage(internalMetadata);
|
||
|
}
|
||
|
// Update test id attribute.
|
||
|
if (params.testIdAttributeName) {
|
||
|
for (const page of this._playwright.allPages()) page.context().selectors().setTestIdAttributeName(params.testIdAttributeName);
|
||
|
}
|
||
|
// Toggle the mode.
|
||
|
for (const recorder of await this._allRecorders()) {
|
||
|
recorder.hideHighlightedSelector();
|
||
|
if (params.mode !== 'inspecting') recorder.setOutput(this._codegenId, params.file);
|
||
|
recorder.setMode(params.mode);
|
||
|
}
|
||
|
}
|
||
|
async highlight(params) {
|
||
|
// Assert parameters validity.
|
||
|
if (params.selector) (0, _locatorParser.unsafeLocatorOrSelectorAsSelector)(this._sdkLanguage, params.selector, 'data-testid');
|
||
|
const ariaTemplate = params.ariaTemplate ? (0, _ariaSnapshot.parseAriaSnapshotUnsafe)(_utilsBundle.yaml, params.ariaTemplate) : undefined;
|
||
|
for (const recorder of await this._allRecorders()) {
|
||
|
if (ariaTemplate) recorder.setHighlightedAriaTemplate(ariaTemplate);else if (params.selector) recorder.setHighlightedSelector(this._sdkLanguage, params.selector);
|
||
|
}
|
||
|
}
|
||
|
async hideHighlight() {
|
||
|
// Hide all active recorder highlights.
|
||
|
for (const recorder of await this._allRecorders()) recorder.hideHighlightedSelector();
|
||
|
// Hide all locator.highlight highlights.
|
||
|
await this._playwright.hideHighlight();
|
||
|
}
|
||
|
allBrowsers() {
|
||
|
return [...this._playwright.allBrowsers()];
|
||
|
}
|
||
|
async resume() {
|
||
|
for (const recorder of await this._allRecorders()) recorder.resume();
|
||
|
}
|
||
|
async kill() {
|
||
|
(0, _processLauncher.gracefullyProcessExitDoNotHang)(0);
|
||
|
}
|
||
|
async closeAllBrowsers() {
|
||
|
await Promise.all(this.allBrowsers().map(browser => browser.close({
|
||
|
reason: 'Close all browsers requested'
|
||
|
})));
|
||
|
}
|
||
|
_emitSnapshot(initial) {
|
||
|
const pageCount = this._playwright.allPages().length;
|
||
|
if (initial && !pageCount) return;
|
||
|
this.emit(DebugController.Events.StateChanged, {
|
||
|
pageCount
|
||
|
});
|
||
|
}
|
||
|
async _allRecorders() {
|
||
|
const contexts = new Set();
|
||
|
for (const page of this._playwright.allPages()) contexts.add(page.context());
|
||
|
const result = await Promise.all([...contexts].map(c => _recorder.Recorder.showInspector(c, {
|
||
|
omitCallTracking: true
|
||
|
}, () => Promise.resolve(new InspectingRecorderApp(this)))));
|
||
|
return result.filter(Boolean);
|
||
|
}
|
||
|
async _closeBrowsersWithoutPages() {
|
||
|
for (const browser of this._playwright.allBrowsers()) {
|
||
|
for (const context of browser.contexts()) {
|
||
|
if (!context.pages().length) await context.close({
|
||
|
reason: 'Browser collected'
|
||
|
});
|
||
|
}
|
||
|
if (!browser.contexts()) await browser.close({
|
||
|
reason: 'Browser collected'
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
exports.DebugController = DebugController;
|
||
|
DebugController.Events = {
|
||
|
StateChanged: 'stateChanged',
|
||
|
InspectRequested: 'inspectRequested',
|
||
|
SourceChanged: 'sourceChanged',
|
||
|
Paused: 'paused',
|
||
|
SetModeRequested: 'setModeRequested'
|
||
|
};
|
||
|
class InspectingRecorderApp extends _recorderApp.EmptyRecorderApp {
|
||
|
constructor(debugController) {
|
||
|
super();
|
||
|
this._debugController = void 0;
|
||
|
this._debugController = debugController;
|
||
|
}
|
||
|
async elementPicked(elementInfo) {
|
||
|
const locator = (0, _utils.asLocator)(this._debugController._sdkLanguage, elementInfo.selector);
|
||
|
this._debugController.emit(DebugController.Events.InspectRequested, {
|
||
|
selector: elementInfo.selector,
|
||
|
locator,
|
||
|
ariaSnapshot: elementInfo.ariaSnapshot
|
||
|
});
|
||
|
}
|
||
|
async setSources(sources) {
|
||
|
const source = sources.find(s => s.id === this._debugController._codegenId);
|
||
|
const {
|
||
|
text,
|
||
|
header,
|
||
|
footer,
|
||
|
actions
|
||
|
} = source || {
|
||
|
text: ''
|
||
|
};
|
||
|
this._debugController.emit(DebugController.Events.SourceChanged, {
|
||
|
text,
|
||
|
header,
|
||
|
footer,
|
||
|
actions
|
||
|
});
|
||
|
}
|
||
|
async setPaused(paused) {
|
||
|
this._debugController.emit(DebugController.Events.Paused, {
|
||
|
paused
|
||
|
});
|
||
|
}
|
||
|
async setMode(mode) {
|
||
|
this._debugController.emit(DebugController.Events.SetModeRequested, {
|
||
|
mode
|
||
|
});
|
||
|
}
|
||
|
}
|