How to use splitSelectorByFrame method in Playwright Internal

Best JavaScript code snippet using playwright-internal

frames.js

Source:frames.js Github

copy

Full Screen

1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.FrameManager = exports.Frame = void 0;6var dom = _interopRequireWildcard(require("./dom"));7var _helper = require("./helper");8var _eventsHelper = require("../utils/eventsHelper");9var js = _interopRequireWildcard(require("./javascript"));10var network = _interopRequireWildcard(require("./network"));11var _page = require("./page");12var types = _interopRequireWildcard(require("./types"));13var _browserContext = require("./browserContext");14var _progress = require("./progress");15var _utils = require("../utils/utils");16var _async = require("../utils/async");17var _debugLogger = require("../utils/debugLogger");18var _instrumentation = require("./instrumentation");19var _protocolError = require("./common/protocolError");20var _selectorParser = require("./common/selectorParser");21var _selectorErrors = require("./common/selectorErrors");22function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }23function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }24/**25 * Copyright 2017 Google Inc. All rights reserved.26 * Modifications copyright (c) Microsoft Corporation.27 *28 * Licensed under the Apache License, Version 2.0 (the "License");29 * you may not use this file except in compliance with the License.30 * You may obtain a copy of the License at31 *32 * http://www.apache.org/licenses/LICENSE-2.033 *34 * Unless required by applicable law or agreed to in writing, software35 * distributed under the License is distributed on an "AS IS" BASIS,36 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.37 * See the License for the specific language governing permissions and38 * limitations under the License.39 */40class FrameManager {41 constructor(page) {42 this._page = void 0;43 this._frames = new Map();44 this._mainFrame = void 0;45 this._consoleMessageTags = new Map();46 this._signalBarriers = new Set();47 this._webSockets = new Map();48 this._dialogCounter = 0;49 this._page = page;50 this._mainFrame = undefined;51 }52 dispose() {53 for (const frame of this._frames.values()) frame._stopNetworkIdleTimer();54 }55 mainFrame() {56 return this._mainFrame;57 }58 frames() {59 const frames = [];60 collect(this._mainFrame);61 return frames;62 function collect(frame) {63 frames.push(frame);64 for (const subframe of frame.childFrames()) collect(subframe);65 }66 }67 frame(frameId) {68 return this._frames.get(frameId) || null;69 }70 frameAttached(frameId, parentFrameId) {71 const parentFrame = parentFrameId ? this._frames.get(parentFrameId) : null;72 if (!parentFrame) {73 if (this._mainFrame) {74 // Update frame id to retain frame identity on cross-process navigation.75 this._frames.delete(this._mainFrame._id);76 this._mainFrame._id = frameId;77 } else {78 (0, _utils.assert)(!this._frames.has(frameId));79 this._mainFrame = new Frame(this._page, frameId, parentFrame);80 }81 this._frames.set(frameId, this._mainFrame);82 return this._mainFrame;83 } else {84 (0, _utils.assert)(!this._frames.has(frameId));85 const frame = new Frame(this._page, frameId, parentFrame);86 this._frames.set(frameId, frame);87 this._page.emit(_page.Page.Events.FrameAttached, frame);88 return frame;89 }90 }91 async waitForSignalsCreatedBy(progress, noWaitAfter, action, source) {92 if (noWaitAfter) return action();93 const barrier = new SignalBarrier(progress);94 this._signalBarriers.add(barrier);95 if (progress) progress.cleanupWhenAborted(() => this._signalBarriers.delete(barrier));96 const result = await action();97 if (source === 'input') await this._page._delegate.inputActionEpilogue();98 await barrier.waitFor();99 this._signalBarriers.delete(barrier); // Resolve in the next task, after all waitForNavigations.100 await new Promise((0, _utils.makeWaitForNextTask)());101 return result;102 }103 frameWillPotentiallyRequestNavigation() {104 for (const barrier of this._signalBarriers) barrier.retain();105 }106 frameDidPotentiallyRequestNavigation() {107 for (const barrier of this._signalBarriers) barrier.release();108 }109 frameRequestedNavigation(frameId, documentId) {110 const frame = this._frames.get(frameId);111 if (!frame) return;112 for (const barrier of this._signalBarriers) barrier.addFrameNavigation(frame);113 if (frame.pendingDocument() && frame.pendingDocument().documentId === documentId) {114 // Do not override request with undefined.115 return;116 }117 frame.setPendingDocument({118 documentId,119 request: undefined120 });121 }122 frameCommittedNewDocumentNavigation(frameId, url, name, documentId, initial) {123 const frame = this._frames.get(frameId);124 this.removeChildFramesRecursively(frame);125 this.clearWebSockets(frame);126 frame._url = url;127 frame._name = name;128 let keepPending;129 const pendingDocument = frame.pendingDocument();130 if (pendingDocument) {131 if (pendingDocument.documentId === undefined) {132 // Pending with unknown documentId - assume it is the one being committed.133 pendingDocument.documentId = documentId;134 }135 if (pendingDocument.documentId === documentId) {136 // Committing a pending document.137 frame._currentDocument = pendingDocument;138 } else {139 // Sometimes, we already have a new pending when the old one commits.140 // An example would be Chromium error page followed by a new navigation request,141 // where the error page commit arrives after Network.requestWillBeSent for the142 // new navigation.143 // We commit, but keep the pending request since it's not done yet.144 keepPending = pendingDocument;145 frame._currentDocument = {146 documentId,147 request: undefined148 };149 }150 frame.setPendingDocument(undefined);151 } else {152 // No pending - just commit a new document.153 frame._currentDocument = {154 documentId,155 request: undefined156 };157 }158 frame._onClearLifecycle();159 const navigationEvent = {160 url,161 name,162 newDocument: frame._currentDocument163 };164 frame.emit(Frame.Events.Navigation, navigationEvent);165 if (!initial) {166 _debugLogger.debugLogger.log('api', ` navigated to "${url}"`);167 this._page.frameNavigatedToNewDocument(frame);168 } // Restore pending if any - see comments above about keepPending.169 frame.setPendingDocument(keepPending);170 }171 frameCommittedSameDocumentNavigation(frameId, url) {172 const frame = this._frames.get(frameId);173 if (!frame) return;174 frame._url = url;175 const navigationEvent = {176 url,177 name: frame._name178 };179 frame.emit(Frame.Events.Navigation, navigationEvent);180 _debugLogger.debugLogger.log('api', ` navigated to "${url}"`);181 }182 frameAbortedNavigation(frameId, errorText, documentId) {183 const frame = this._frames.get(frameId);184 if (!frame || !frame.pendingDocument()) return;185 if (documentId !== undefined && frame.pendingDocument().documentId !== documentId) return;186 const navigationEvent = {187 url: frame._url,188 name: frame._name,189 newDocument: frame.pendingDocument(),190 error: new Error(errorText)191 };192 frame.setPendingDocument(undefined);193 frame.emit(Frame.Events.Navigation, navigationEvent);194 }195 frameDetached(frameId) {196 const frame = this._frames.get(frameId);197 if (frame) this._removeFramesRecursively(frame);198 }199 frameStoppedLoading(frameId) {200 this.frameLifecycleEvent(frameId, 'domcontentloaded');201 this.frameLifecycleEvent(frameId, 'load');202 }203 frameLifecycleEvent(frameId, event) {204 const frame = this._frames.get(frameId);205 if (frame) frame._onLifecycleEvent(event);206 }207 requestStarted(request, route) {208 const frame = request.frame();209 this._inflightRequestStarted(request);210 if (request._documentId) frame.setPendingDocument({211 documentId: request._documentId,212 request213 });214 if (request._isFavicon) {215 if (route) route.continue(request, {});216 return;217 }218 this._page._browserContext.emit(_browserContext.BrowserContext.Events.Request, request);219 if (route) this._page._requestStarted(request, route);220 }221 requestReceivedResponse(response) {222 if (response.request()._isFavicon) return;223 this._page._browserContext.emit(_browserContext.BrowserContext.Events.Response, response);224 }225 reportRequestFinished(request, response) {226 this._inflightRequestFinished(request);227 if (request._isFavicon) return;228 this._page._browserContext.emit(_browserContext.BrowserContext.Events.RequestFinished, {229 request,230 response231 });232 }233 requestFailed(request, canceled) {234 const frame = request.frame();235 this._inflightRequestFinished(request);236 if (frame.pendingDocument() && frame.pendingDocument().request === request) {237 let errorText = request.failure().errorText;238 if (canceled) errorText += '; maybe frame was detached?';239 this.frameAbortedNavigation(frame._id, errorText, frame.pendingDocument().documentId);240 }241 if (request._isFavicon) return;242 this._page._browserContext.emit(_browserContext.BrowserContext.Events.RequestFailed, request);243 }244 dialogDidOpen() {245 // Any ongoing evaluations will be stalled until the dialog is closed.246 for (const frame of this._frames.values()) frame._invalidateNonStallingEvaluations('JavaScript dialog interrupted evaluation');247 this._dialogCounter++;248 }249 dialogWillClose() {250 this._dialogCounter--;251 }252 removeChildFramesRecursively(frame) {253 for (const child of frame.childFrames()) this._removeFramesRecursively(child);254 }255 _removeFramesRecursively(frame) {256 this.removeChildFramesRecursively(frame);257 frame._onDetached();258 this._frames.delete(frame._id);259 if (!this._page.isClosed()) this._page.emit(_page.Page.Events.FrameDetached, frame);260 }261 _inflightRequestFinished(request) {262 const frame = request.frame();263 if (request._isFavicon) return;264 if (!frame._inflightRequests.has(request)) return;265 frame._inflightRequests.delete(request);266 if (frame._inflightRequests.size === 0) frame._startNetworkIdleTimer();267 }268 _inflightRequestStarted(request) {269 const frame = request.frame();270 if (request._isFavicon) return;271 frame._inflightRequests.add(request);272 if (frame._inflightRequests.size === 1) frame._stopNetworkIdleTimer();273 }274 interceptConsoleMessage(message) {275 if (message.type() !== 'debug') return false;276 const tag = message.text();277 const handler = this._consoleMessageTags.get(tag);278 if (!handler) return false;279 this._consoleMessageTags.delete(tag);280 handler();281 return true;282 }283 clearWebSockets(frame) {284 // TODO: attribute sockets to frames.285 if (frame.parentFrame()) return;286 this._webSockets.clear();287 }288 onWebSocketCreated(requestId, url) {289 const ws = new network.WebSocket(this._page, url);290 this._webSockets.set(requestId, ws);291 }292 onWebSocketRequest(requestId) {293 const ws = this._webSockets.get(requestId);294 if (ws && ws.markAsNotified()) this._page.emit(_page.Page.Events.WebSocket, ws);295 }296 onWebSocketResponse(requestId, status, statusText) {297 const ws = this._webSockets.get(requestId);298 if (status < 400) return;299 if (ws) ws.error(`${statusText}: ${status}`);300 }301 onWebSocketFrameSent(requestId, opcode, data) {302 const ws = this._webSockets.get(requestId);303 if (ws) ws.frameSent(opcode, data);304 }305 webSocketFrameReceived(requestId, opcode, data) {306 const ws = this._webSockets.get(requestId);307 if (ws) ws.frameReceived(opcode, data);308 }309 webSocketClosed(requestId) {310 const ws = this._webSockets.get(requestId);311 if (ws) ws.closed();312 this._webSockets.delete(requestId);313 }314 webSocketError(requestId, errorMessage) {315 const ws = this._webSockets.get(requestId);316 if (ws) ws.error(errorMessage);317 }318}319exports.FrameManager = FrameManager;320class Frame extends _instrumentation.SdkObject {321 constructor(page, id, parentFrame) {322 super(page, 'frame');323 this._id = void 0;324 this._firedLifecycleEvents = new Set();325 this._subtreeLifecycleEvents = new Set();326 this._currentDocument = void 0;327 this._pendingDocument = void 0;328 this._page = void 0;329 this._parentFrame = void 0;330 this._url = '';331 this._detached = false;332 this._contextData = new Map();333 this._childFrames = new Set();334 this._name = '';335 this._inflightRequests = new Set();336 this._networkIdleTimer = void 0;337 this._setContentCounter = 0;338 this._detachedPromise = void 0;339 this._detachedCallback = () => {};340 this._nonStallingEvaluations = new Set();341 this.attribution.frame = this;342 this._id = id;343 this._page = page;344 this._parentFrame = parentFrame;345 this._currentDocument = {346 documentId: undefined,347 request: undefined348 };349 this._detachedPromise = new Promise(x => this._detachedCallback = x);350 this._contextData.set('main', {351 contextPromise: new _async.ManualPromise(),352 context: null,353 rerunnableTasks: new Set()354 });355 this._contextData.set('utility', {356 contextPromise: new _async.ManualPromise(),357 context: null,358 rerunnableTasks: new Set()359 });360 this._setContext('main', null);361 this._setContext('utility', null);362 if (this._parentFrame) this._parentFrame._childFrames.add(this);363 this._firedLifecycleEvents.add('commit');364 this._subtreeLifecycleEvents.add('commit');365 }366 isDetached() {367 return this._detached;368 }369 _onLifecycleEvent(event) {370 if (this._firedLifecycleEvents.has(event)) return;371 this._firedLifecycleEvents.add(event); // Recalculate subtree lifecycle for the whole tree - it should not be that big.372 this._page.mainFrame()._recalculateLifecycle();373 }374 _onClearLifecycle() {375 this._firedLifecycleEvents.clear(); // Recalculate subtree lifecycle for the whole tree - it should not be that big.376 this._page.mainFrame()._recalculateLifecycle(); // Keep the current navigation request if any.377 this._inflightRequests = new Set(Array.from(this._inflightRequests).filter(request => request === this._currentDocument.request));378 this._stopNetworkIdleTimer();379 if (this._inflightRequests.size === 0) this._startNetworkIdleTimer();380 this._onLifecycleEvent('commit');381 }382 setPendingDocument(documentInfo) {383 this._pendingDocument = documentInfo;384 if (documentInfo) this._invalidateNonStallingEvaluations('Navigation interrupted the evaluation');385 }386 pendingDocument() {387 return this._pendingDocument;388 }389 _invalidateNonStallingEvaluations(message) {390 if (!this._nonStallingEvaluations) return;391 const error = new Error(message);392 for (const callback of this._nonStallingEvaluations) callback(error);393 }394 async nonStallingRawEvaluateInExistingMainContext(expression) {395 if (this._pendingDocument) throw new Error('Frame is currently attempting a navigation');396 if (this._page._frameManager._dialogCounter) throw new Error('Open JavaScript dialog prevents evaluation');397 const context = this._existingMainContext();398 if (!context) throw new Error('Frame does not yet have a main execution context');399 let callback = () => {};400 const frameInvalidated = new Promise((f, r) => callback = r);401 this._nonStallingEvaluations.add(callback);402 try {403 return await Promise.race([context.rawEvaluateJSON(expression), frameInvalidated]);404 } finally {405 this._nonStallingEvaluations.delete(callback);406 }407 }408 async nonStallingEvaluateInExistingContext(expression, isFunction, world) {409 var _this$_contextData$ge;410 if (this._pendingDocument) throw new Error('Frame is currently attempting a navigation');411 const context = (_this$_contextData$ge = this._contextData.get(world)) === null || _this$_contextData$ge === void 0 ? void 0 : _this$_contextData$ge.context;412 if (!context) throw new Error('Frame does not yet have the execution context');413 let callback = () => {};414 const frameInvalidated = new Promise((f, r) => callback = r);415 this._nonStallingEvaluations.add(callback);416 try {417 return await Promise.race([context.evaluateExpression(expression, isFunction), frameInvalidated]);418 } finally {419 this._nonStallingEvaluations.delete(callback);420 }421 }422 _recalculateLifecycle() {423 const events = new Set(this._firedLifecycleEvents);424 for (const child of this._childFrames) {425 child._recalculateLifecycle(); // We require a particular lifecycle event to be fired in the whole426 // frame subtree, and then consider it done.427 for (const event of events) {428 if (!child._subtreeLifecycleEvents.has(event)) events.delete(event);429 }430 }431 const mainFrame = this._page.mainFrame();432 for (const event of events) {433 // Checking whether we have already notified about this event.434 if (!this._subtreeLifecycleEvents.has(event)) {435 this.emit(Frame.Events.AddLifecycle, event);436 if (this === mainFrame && this._url !== 'about:blank') _debugLogger.debugLogger.log('api', ` "${event}" event fired`);437 if (this === mainFrame && event === 'load') this._page.emit(_page.Page.Events.Load);438 if (this === mainFrame && event === 'domcontentloaded') this._page.emit(_page.Page.Events.DOMContentLoaded);439 }440 }441 for (const event of this._subtreeLifecycleEvents) {442 if (!events.has(event)) this.emit(Frame.Events.RemoveLifecycle, event);443 }444 this._subtreeLifecycleEvents = events;445 }446 async raceNavigationAction(action) {447 return Promise.race([this._page._disconnectedPromise.then(() => {448 throw new Error('Navigation failed because page was closed!');449 }), this._page._crashedPromise.then(() => {450 throw new Error('Navigation failed because page crashed!');451 }), this._detachedPromise.then(() => {452 throw new Error('Navigating frame was detached!');453 }), action()]);454 }455 async goto(metadata, url, options = {}) {456 const constructedNavigationURL = (0, _utils.constructURLBasedOnBaseURL)(this._page._browserContext._options.baseURL, url);457 const controller = new _progress.ProgressController(metadata, this);458 return controller.run(progress => this._goto(progress, constructedNavigationURL, options), this._page._timeoutSettings.navigationTimeout(options));459 }460 async _goto(progress, url, options) {461 return this.raceNavigationAction(async () => {462 const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);463 progress.log(`navigating to "${url}", waiting until "${waitUntil}"`);464 const headers = this._page._state.extraHTTPHeaders || [];465 const refererHeader = headers.find(h => h.name.toLowerCase() === 'referer');466 let referer = refererHeader ? refererHeader.value : undefined;467 if (options.referer !== undefined) {468 if (referer !== undefined && referer !== options.referer) throw new Error('"referer" is already specified as extra HTTP header');469 referer = options.referer;470 }471 url = _helper.helper.completeUserURL(url);472 const sameDocument = _helper.helper.waitForEvent(progress, this, Frame.Events.Navigation, e => !e.newDocument);473 const navigateResult = await this._page._delegate.navigateFrame(this, url, referer);474 let event;475 if (navigateResult.newDocumentId) {476 sameDocument.dispose();477 event = await _helper.helper.waitForEvent(progress, this, Frame.Events.Navigation, event => {478 // We are interested either in this specific document, or any other document that479 // did commit and replaced the expected document.480 return event.newDocument && (event.newDocument.documentId === navigateResult.newDocumentId || !event.error);481 }).promise;482 if (event.newDocument.documentId !== navigateResult.newDocumentId) {483 // This is just a sanity check. In practice, new navigation should484 // cancel the previous one and report "request cancelled"-like error.485 throw new Error('Navigation interrupted by another one');486 }487 if (event.error) throw event.error;488 } else {489 event = await sameDocument.promise;490 }491 if (!this._subtreeLifecycleEvents.has(waitUntil)) await _helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, e => e === waitUntil).promise;492 const request = event.newDocument ? event.newDocument.request : undefined;493 const response = request ? request._finalRequest().response() : null;494 await this._page._doSlowMo();495 return response;496 });497 }498 async _waitForNavigation(progress, options) {499 const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);500 progress.log(`waiting for navigation until "${waitUntil}"`);501 const navigationEvent = await _helper.helper.waitForEvent(progress, this, Frame.Events.Navigation, event => {502 // Any failed navigation results in a rejection.503 if (event.error) return true;504 progress.log(` navigated to "${this._url}"`);505 return true;506 }).promise;507 if (navigationEvent.error) throw navigationEvent.error;508 if (!this._subtreeLifecycleEvents.has(waitUntil)) await _helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, e => e === waitUntil).promise;509 const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : undefined;510 return request ? request._finalRequest().response() : null;511 }512 async _waitForLoadState(progress, state) {513 const waitUntil = verifyLifecycle('state', state);514 if (!this._subtreeLifecycleEvents.has(waitUntil)) await _helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, e => e === waitUntil).promise;515 }516 async frameElement() {517 return this._page._delegate.getFrameElement(this);518 }519 _context(world) {520 return this._contextData.get(world).contextPromise.then(contextOrError => {521 if (contextOrError instanceof js.ExecutionContext) return contextOrError;522 throw contextOrError;523 });524 }525 _mainContext() {526 return this._context('main');527 }528 _existingMainContext() {529 var _this$_contextData$ge2;530 return ((_this$_contextData$ge2 = this._contextData.get('main')) === null || _this$_contextData$ge2 === void 0 ? void 0 : _this$_contextData$ge2.context) || null;531 }532 _utilityContext() {533 return this._context('utility');534 }535 async evaluateExpressionHandleAndWaitForSignals(expression, isFunction, arg, world = 'main') {536 const context = await this._context(world);537 const handle = await context.evaluateExpressionHandleAndWaitForSignals(expression, isFunction, arg);538 if (world === 'main') await this._page._doSlowMo();539 return handle;540 }541 async evaluateExpression(expression, isFunction, arg, world = 'main') {542 const context = await this._context(world);543 const value = await context.evaluateExpression(expression, isFunction, arg);544 if (world === 'main') await this._page._doSlowMo();545 return value;546 }547 async evaluateExpressionAndWaitForSignals(expression, isFunction, arg, world = 'main') {548 const context = await this._context(world);549 const value = await context.evaluateExpressionAndWaitForSignals(expression, isFunction, arg);550 if (world === 'main') await this._page._doSlowMo();551 return value;552 }553 async querySelector(selector, options) {554 _debugLogger.debugLogger.log('api', ` finding element using the selector "${selector}"`);555 const result = await this.resolveFrameForSelectorNoWait(selector, options);556 if (!result) return null;557 return this._page.selectors.query(result.frame, result.info);558 }559 async waitForSelector(metadata, selector, options, scope) {560 const controller = new _progress.ProgressController(metadata, this);561 if (options.visibility) throw new Error('options.visibility is not supported, did you mean options.state?');562 if (options.waitFor && options.waitFor !== 'visible') throw new Error('options.waitFor is not supported, did you mean options.state?');563 const {564 state = 'visible'565 } = options;566 if (!['attached', 'detached', 'visible', 'hidden'].includes(state)) throw new Error(`state: expected one of (attached|detached|visible|hidden)`);567 return controller.run(async progress => {568 progress.log(`waiting for selector "${selector}"${state === 'attached' ? '' : ' to be ' + state}`);569 return this.retryWithProgress(progress, selector, options, async (selectorInFrame, continuePolling) => {570 // Be careful, |this| can be different from |frame|.571 // We did not pass omitAttached, so it is non-null.572 const {573 frame,574 info575 } = selectorInFrame;576 const actualScope = this === frame ? scope : undefined;577 const task = dom.waitForSelectorTask(info, state, options.omitReturnValue, actualScope);578 const result = actualScope ? await frame._runWaitForSelectorTaskOnce(progress, (0, _selectorParser.stringifySelector)(info.parsed), info.world, task) : await frame._scheduleRerunnableHandleTask(progress, info.world, task);579 if (!result.asElement()) {580 result.dispose();581 return null;582 }583 if (options.__testHookBeforeAdoptNode) await options.__testHookBeforeAdoptNode();584 const handle = result.asElement();585 try {586 return await handle._adoptTo(await frame._mainContext());587 } catch (e) {588 return continuePolling;589 }590 }, scope);591 }, this._page._timeoutSettings.timeout(options));592 }593 async dispatchEvent(metadata, selector, type, eventInit = {}, options = {}) {594 await this._scheduleRerunnableTask(metadata, selector, (progress, element, data) => {595 progress.injectedScript.dispatchEvent(element, data.type, data.eventInit);596 }, {597 type,598 eventInit599 }, {600 mainWorld: true,601 ...options602 });603 await this._page._doSlowMo();604 }605 async evalOnSelectorAndWaitForSignals(selector, strict, expression, isFunction, arg) {606 const pair = await this.resolveFrameForSelectorNoWait(selector, {607 strict608 });609 const handle = pair ? await this._page.selectors.query(pair.frame, pair.info) : null;610 if (!handle) throw new Error(`Error: failed to find element matching selector "${selector}"`);611 const result = await handle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);612 handle.dispose();613 return result;614 }615 async evalOnSelectorAllAndWaitForSignals(selector, expression, isFunction, arg) {616 const pair = await this.resolveFrameForSelectorNoWait(selector, {});617 if (!pair) throw new Error(`Error: failed to find frame for selector "${selector}"`);618 const arrayHandle = await this._page.selectors._queryArrayInMainWorld(pair.frame, pair.info);619 const result = await arrayHandle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);620 arrayHandle.dispose();621 return result;622 }623 async querySelectorAll(selector) {624 const pair = await this.resolveFrameForSelectorNoWait(selector, {});625 if (!pair) return [];626 return this._page.selectors._queryAll(pair.frame, pair.info, undefined, true627 /* adoptToMain */628 );629 }630 async queryCount(selector) {631 const pair = await this.resolveFrameForSelectorNoWait(selector);632 if (!pair) throw new Error(`Error: failed to find frame for selector "${selector}"`);633 return await this._page.selectors._queryCount(pair.frame, pair.info);634 }635 async content() {636 try {637 const context = await this._utilityContext();638 return await context.evaluate(() => {639 let retVal = '';640 if (document.doctype) retVal = new XMLSerializer().serializeToString(document.doctype);641 if (document.documentElement) retVal += document.documentElement.outerHTML;642 return retVal;643 });644 } catch (e) {645 if (js.isJavaScriptErrorInEvaluate(e) || (0, _protocolError.isSessionClosedError)(e)) throw e;646 throw new Error(`Unable to retrieve content because the page is navigating and changing the content.`);647 }648 }649 async setContent(metadata, html, options = {}) {650 const controller = new _progress.ProgressController(metadata, this);651 return controller.run(progress => this.raceNavigationAction(async () => {652 const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil;653 progress.log(`setting frame content, waiting until "${waitUntil}"`);654 const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`;655 const context = await this._utilityContext();656 const lifecyclePromise = new Promise((resolve, reject) => {657 this._page._frameManager._consoleMessageTags.set(tag, () => {658 // Clear lifecycle right after document.open() - see 'tag' below.659 this._onClearLifecycle();660 this._waitForLoadState(progress, waitUntil).then(resolve).catch(reject);661 });662 });663 const contentPromise = context.evaluate(({664 html,665 tag666 }) => {667 window.stop();668 document.open();669 console.debug(tag); // eslint-disable-line no-console670 document.write(html);671 document.close();672 }, {673 html,674 tag675 });676 await Promise.all([contentPromise, lifecyclePromise]);677 await this._page._doSlowMo();678 }), this._page._timeoutSettings.navigationTimeout(options));679 }680 name() {681 return this._name || '';682 }683 url() {684 return this._url;685 }686 parentFrame() {687 return this._parentFrame;688 }689 childFrames() {690 return Array.from(this._childFrames);691 }692 async addScriptTag(params) {693 const {694 url = null,695 content = null,696 type = ''697 } = params;698 if (!url && !content) throw new Error('Provide an object with a `url`, `path` or `content` property');699 const context = await this._mainContext();700 return this._raceWithCSPError(async () => {701 if (url !== null) return (await context.evaluateHandle(addScriptUrl, {702 url,703 type704 })).asElement();705 const result = (await context.evaluateHandle(addScriptContent, {706 content: content,707 type708 })).asElement(); // Another round trip to the browser to ensure that we receive CSP error messages709 // (if any) logged asynchronously in a separate task on the content main thread.710 if (this._page._delegate.cspErrorsAsynchronousForInlineScipts) await context.evaluate(() => true);711 return result;712 });713 async function addScriptUrl(params) {714 const script = document.createElement('script');715 script.src = params.url;716 if (params.type) script.type = params.type;717 const promise = new Promise((res, rej) => {718 script.onload = res;719 script.onerror = e => rej(typeof e === 'string' ? new Error(e) : new Error(`Failed to load script at ${script.src}`));720 });721 document.head.appendChild(script);722 await promise;723 return script;724 }725 function addScriptContent(params) {726 const script = document.createElement('script');727 script.type = params.type || 'text/javascript';728 script.text = params.content;729 let error = null;730 script.onerror = e => error = e;731 document.head.appendChild(script);732 if (error) throw error;733 return script;734 }735 }736 async addStyleTag(params) {737 const {738 url = null,739 content = null740 } = params;741 if (!url && !content) throw new Error('Provide an object with a `url`, `path` or `content` property');742 const context = await this._mainContext();743 return this._raceWithCSPError(async () => {744 if (url !== null) return (await context.evaluateHandle(addStyleUrl, url)).asElement();745 return (await context.evaluateHandle(addStyleContent, content)).asElement();746 });747 async function addStyleUrl(url) {748 const link = document.createElement('link');749 link.rel = 'stylesheet';750 link.href = url;751 const promise = new Promise((res, rej) => {752 link.onload = res;753 link.onerror = rej;754 });755 document.head.appendChild(link);756 await promise;757 return link;758 }759 async function addStyleContent(content) {760 const style = document.createElement('style');761 style.type = 'text/css';762 style.appendChild(document.createTextNode(content));763 const promise = new Promise((res, rej) => {764 style.onload = res;765 style.onerror = rej;766 });767 document.head.appendChild(style);768 await promise;769 return style;770 }771 }772 async _raceWithCSPError(func) {773 const listeners = [];774 let result;775 let error;776 let cspMessage;777 const actionPromise = func().then(r => result = r).catch(e => error = e);778 const errorPromise = new Promise(resolve => {779 listeners.push(_eventsHelper.eventsHelper.addEventListener(this._page, _page.Page.Events.Console, message => {780 if (message.type() === 'error' && message.text().includes('Content Security Policy')) {781 cspMessage = message;782 resolve();783 }784 }));785 });786 await Promise.race([actionPromise, errorPromise]);787 _eventsHelper.eventsHelper.removeEventListeners(listeners);788 if (cspMessage) throw new Error(cspMessage.text());789 if (error) throw error;790 return result;791 }792 async retryWithProgress(progress, selector, options, action, scope) {793 const continuePolling = Symbol('continuePolling');794 while (progress.isRunning()) {795 let selectorInFrame;796 if (options.omitAttached) {797 selectorInFrame = await this.resolveFrameForSelectorNoWait(selector, options, scope);798 } else {799 selectorInFrame = await this._resolveFrameForSelector(progress, selector, options, scope);800 if (!selectorInFrame) {801 // Missing content frame.802 await new Promise(f => setTimeout(f, 100));803 continue;804 }805 }806 try {807 const result = await action(selectorInFrame, continuePolling);808 if (result === continuePolling) continue;809 return result;810 } catch (e) {811 var _selectorInFrame;812 // Always fail on JavaScript errors or when the main connection is closed.813 if (js.isJavaScriptErrorInEvaluate(e) || (0, _protocolError.isSessionClosedError)(e)) throw e; // Certain error opt-out of the retries, throw.814 if (dom.isNonRecoverableDOMError(e)) throw e; // If the call is made on the detached frame - throw.815 if (this.isDetached()) throw e; // If there is scope, and scope is within the frame we use to select, assume context is destroyed and816 // operation is not recoverable.817 if (scope && scope._context.frame === ((_selectorInFrame = selectorInFrame) === null || _selectorInFrame === void 0 ? void 0 : _selectorInFrame.frame)) throw e; // Retry upon all other errors.818 continue;819 }820 }821 progress.throwIfAborted();822 return undefined;823 }824 async _retryWithProgressIfNotConnected(progress, selector, strict, action) {825 return this.retryWithProgress(progress, selector, {826 strict827 }, async (selectorInFrame, continuePolling) => {828 // We did not pass omitAttached, so selectorInFrame is not null.829 const {830 frame,831 info832 } = selectorInFrame; // Be careful, |this| can be different from |frame|.833 const task = dom.waitForSelectorTask(info, 'attached');834 progress.log(`waiting for selector "${selector}"`);835 const handle = await frame._scheduleRerunnableHandleTask(progress, info.world, task);836 const element = handle.asElement();837 try {838 const result = await action(element);839 if (result === 'error:notconnected') {840 progress.log('element was detached from the DOM, retrying');841 return continuePolling;842 }843 return result;844 } finally {845 element === null || element === void 0 ? void 0 : element.dispose();846 }847 });848 }849 async click(metadata, selector, options) {850 const controller = new _progress.ProgressController(metadata, this);851 return controller.run(async progress => {852 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._click(progress, options)));853 }, this._page._timeoutSettings.timeout(options));854 }855 async dblclick(metadata, selector, options = {}) {856 const controller = new _progress.ProgressController(metadata, this);857 return controller.run(async progress => {858 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._dblclick(progress, options)));859 }, this._page._timeoutSettings.timeout(options));860 }861 async dragAndDrop(metadata, source, target, options = {}) {862 const controller = new _progress.ProgressController(metadata, this);863 await controller.run(async progress => {864 dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, async handle => {865 return handle._retryPointerAction(progress, 'move and down', false, async point => {866 await this._page.mouse.move(point.x, point.y);867 await this._page.mouse.down();868 }, { ...options,869 position: options.sourcePosition,870 timeout: progress.timeUntilDeadline()871 });872 }));873 dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, async handle => {874 return handle._retryPointerAction(progress, 'move and up', false, async point => {875 await this._page.mouse.move(point.x, point.y);876 await this._page.mouse.up();877 }, { ...options,878 position: options.targetPosition,879 timeout: progress.timeUntilDeadline()880 });881 }));882 }, this._page._timeoutSettings.timeout(options));883 }884 async tap(metadata, selector, options) {885 const controller = new _progress.ProgressController(metadata, this);886 return controller.run(async progress => {887 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._tap(progress, options)));888 }, this._page._timeoutSettings.timeout(options));889 }890 async fill(metadata, selector, value, options) {891 const controller = new _progress.ProgressController(metadata, this);892 return controller.run(async progress => {893 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._fill(progress, value, options)));894 }, this._page._timeoutSettings.timeout(options));895 }896 async focus(metadata, selector, options = {}) {897 const controller = new _progress.ProgressController(metadata, this);898 await controller.run(async progress => {899 dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._focus(progress)));900 await this._page._doSlowMo();901 }, this._page._timeoutSettings.timeout(options));902 }903 async textContent(metadata, selector, options = {}) {904 return this._scheduleRerunnableTask(metadata, selector, (progress, element) => element.textContent, undefined, options);905 }906 async innerText(metadata, selector, options = {}) {907 return this._scheduleRerunnableTask(metadata, selector, (progress, element) => {908 if (element.namespaceURI !== 'http://www.w3.org/1999/xhtml') throw progress.injectedScript.createStacklessError('Node is not an HTMLElement');909 return element.innerText;910 }, undefined, options);911 }912 async innerHTML(metadata, selector, options = {}) {913 return this._scheduleRerunnableTask(metadata, selector, (progress, element) => element.innerHTML, undefined, options);914 }915 async getAttribute(metadata, selector, name, options = {}) {916 return this._scheduleRerunnableTask(metadata, selector, (progress, element, data) => element.getAttribute(data.name), {917 name918 }, options);919 }920 async inputValue(metadata, selector, options = {}) {921 return this._scheduleRerunnableTask(metadata, selector, (progress, node) => {922 const element = progress.injectedScript.retarget(node, 'follow-label');923 if (!element || element.nodeName !== 'INPUT' && element.nodeName !== 'TEXTAREA' && element.nodeName !== 'SELECT') throw progress.injectedScript.createStacklessError('Node is not an <input>, <textarea> or <select> element');924 return element.value;925 }, undefined, options);926 }927 async highlight(selector) {928 const pair = await this.resolveFrameForSelectorNoWait(selector);929 if (!pair) return;930 const context = await this._utilityContext();931 const injectedScript = await context.injectedScript();932 return await injectedScript.evaluate((injected, {933 parsed934 }) => {935 return injected.highlight(parsed);936 }, {937 parsed: pair.info.parsed938 });939 }940 async hideHighlight() {941 const context = await this._utilityContext();942 const injectedScript = await context.injectedScript();943 return await injectedScript.evaluate(injected => {944 return injected.hideHighlight();945 });946 }947 async _elementState(metadata, selector, state, options = {}) {948 const result = await this._scheduleRerunnableTask(metadata, selector, (progress, element, data) => {949 const injected = progress.injectedScript;950 return injected.elementState(element, data.state);951 }, {952 state953 }, options);954 return dom.throwRetargetableDOMError(result);955 }956 async isVisible(metadata, selector, options = {}) {957 const controller = new _progress.ProgressController(metadata, this);958 return controller.run(async progress => {959 progress.log(` checking visibility of "${selector}"`);960 const pair = await this.resolveFrameForSelectorNoWait(selector, options);961 if (!pair) return false;962 const element = await this._page.selectors.query(pair.frame, pair.info);963 return element ? await element.isVisible() : false;964 }, this._page._timeoutSettings.timeout({}));965 }966 async isHidden(metadata, selector, options = {}) {967 return !(await this.isVisible(metadata, selector, options));968 }969 async isDisabled(metadata, selector, options = {}) {970 return this._elementState(metadata, selector, 'disabled', options);971 }972 async isEnabled(metadata, selector, options = {}) {973 return this._elementState(metadata, selector, 'enabled', options);974 }975 async isEditable(metadata, selector, options = {}) {976 return this._elementState(metadata, selector, 'editable', options);977 }978 async isChecked(metadata, selector, options = {}) {979 return this._elementState(metadata, selector, 'checked', options);980 }981 async hover(metadata, selector, options = {}) {982 const controller = new _progress.ProgressController(metadata, this);983 return controller.run(async progress => {984 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._hover(progress, options)));985 }, this._page._timeoutSettings.timeout(options));986 }987 async selectOption(metadata, selector, elements, values, options = {}) {988 const controller = new _progress.ProgressController(metadata, this);989 return controller.run(async progress => {990 return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._selectOption(progress, elements, values, options));991 }, this._page._timeoutSettings.timeout(options));992 }993 async setInputFiles(metadata, selector, files, options = {}) {994 const controller = new _progress.ProgressController(metadata, this);995 return controller.run(async progress => {996 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._setInputFiles(progress, files, options)));997 }, this._page._timeoutSettings.timeout(options));998 }999 async type(metadata, selector, text, options = {}) {1000 const controller = new _progress.ProgressController(metadata, this);1001 return controller.run(async progress => {1002 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._type(progress, text, options)));1003 }, this._page._timeoutSettings.timeout(options));1004 }1005 async press(metadata, selector, key, options = {}) {1006 const controller = new _progress.ProgressController(metadata, this);1007 return controller.run(async progress => {1008 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._press(progress, key, options)));1009 }, this._page._timeoutSettings.timeout(options));1010 }1011 async check(metadata, selector, options = {}) {1012 const controller = new _progress.ProgressController(metadata, this);1013 return controller.run(async progress => {1014 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._setChecked(progress, true, options)));1015 }, this._page._timeoutSettings.timeout(options));1016 }1017 async uncheck(metadata, selector, options = {}) {1018 const controller = new _progress.ProgressController(metadata, this);1019 return controller.run(async progress => {1020 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._setChecked(progress, false, options)));1021 }, this._page._timeoutSettings.timeout(options));1022 }1023 async waitForTimeout(metadata, timeout) {1024 const controller = new _progress.ProgressController(metadata, this);1025 return controller.run(async () => {1026 await new Promise(resolve => setTimeout(resolve, timeout));1027 });1028 }1029 async expect(metadata, selector, options) {1030 const controller = new _progress.ProgressController(metadata, this);1031 const isArray = options.expression === 'to.have.count' || options.expression.endsWith('.array');1032 const mainWorld = options.expression === 'to.have.property';1033 const timeout = this._page._timeoutSettings.timeout(options); // List all combinations that are satisfied with the detached node(s).1034 let omitAttached = false;1035 if (!options.isNot && options.expression === 'to.be.hidden') omitAttached = true;else if (options.isNot && options.expression === 'to.be.visible') omitAttached = true;else if (!options.isNot && options.expression === 'to.have.count' && options.expectedNumber === 0) omitAttached = true;else if (options.isNot && options.expression === 'to.have.count' && options.expectedNumber !== 0) omitAttached = true;else if (!options.isNot && options.expression.endsWith('.array') && options.expectedText.length === 0) omitAttached = true;else if (options.isNot && options.expression.endsWith('.array') && options.expectedText.length > 0) omitAttached = true;1036 return controller.run(async outerProgress => {1037 outerProgress.log(`${metadata.apiName}${timeout ? ` with timeout ${timeout}ms` : ''}`);1038 return await this._scheduleRerunnableTaskWithProgress(outerProgress, selector, (progress, element, options, elements) => {1039 let result;1040 if (options.isArray) {1041 result = progress.injectedScript.expectArray(elements, options);1042 } else {1043 if (!element) {1044 // expect(locator).toBeHidden() passes when there is no element.1045 if (!options.isNot && options.expression === 'to.be.hidden') return {1046 matches: true1047 }; // expect(locator).not.toBeVisible() passes when there is no element.1048 if (options.isNot && options.expression === 'to.be.visible') return {1049 matches: false1050 }; // When none of the above applies, keep waiting for the element.1051 return progress.continuePolling;1052 }1053 result = progress.injectedScript.expectSingleElement(progress, element, options);1054 }1055 if (result.matches === options.isNot) {1056 // Keep waiting in these cases:1057 // expect(locator).conditionThatDoesNotMatch1058 // expect(locator).not.conditionThatDoesMatch1059 progress.setIntermediateResult(result.received);1060 if (!Array.isArray(result.received)) progress.log(` unexpected value "${result.received}"`);1061 return progress.continuePolling;1062 } // Reached the expected state!1063 return result;1064 }, { ...options,1065 isArray1066 }, {1067 strict: true,1068 querySelectorAll: isArray,1069 mainWorld,1070 omitAttached,1071 logScale: true,1072 ...options1073 });1074 }, timeout).catch(e => {1075 // Q: Why not throw upon isSessionClosedError(e) as in other places?1076 // A: We want user to receive a friendly message containing the last intermediate result.1077 if (js.isJavaScriptErrorInEvaluate(e) || (0, _selectorErrors.isInvalidSelectorError)(e)) throw e;1078 return {1079 received: controller.lastIntermediateResult(),1080 matches: options.isNot,1081 log: metadata.log1082 };1083 });1084 }1085 async _waitForFunctionExpression(metadata, expression, isFunction, arg, options, world = 'main') {1086 const controller = new _progress.ProgressController(metadata, this);1087 if (typeof options.pollingInterval === 'number') (0, _utils.assert)(options.pollingInterval > 0, 'Cannot poll with non-positive interval: ' + options.pollingInterval);1088 expression = js.normalizeEvaluationExpression(expression, isFunction);1089 const task = injectedScript => injectedScript.evaluateHandle((injectedScript, {1090 expression,1091 isFunction,1092 polling,1093 arg1094 }) => {1095 const predicate = arg => {1096 let result = self.eval(expression);1097 if (isFunction === true) {1098 result = result(arg);1099 } else if (isFunction === false) {1100 result = result;1101 } else {1102 // auto detect.1103 if (typeof result === 'function') result = result(arg);1104 }1105 return result;1106 };1107 if (typeof polling !== 'number') return injectedScript.pollRaf(progress => predicate(arg) || progress.continuePolling);1108 return injectedScript.pollInterval(polling, progress => predicate(arg) || progress.continuePolling);1109 }, {1110 expression,1111 isFunction,1112 polling: options.pollingInterval,1113 arg1114 });1115 return controller.run(progress => this._scheduleRerunnableHandleTask(progress, world, task), this._page._timeoutSettings.timeout(options));1116 }1117 async waitForFunctionValueInUtility(progress, pageFunction) {1118 const expression = `() => {1119 const result = (${pageFunction})();1120 if (!result)1121 return result;1122 return JSON.stringify(result);1123 }`;1124 const handle = await this._waitForFunctionExpression((0, _instrumentation.internalCallMetadata)(), expression, true, undefined, {1125 timeout: progress.timeUntilDeadline()1126 }, 'utility');1127 return JSON.parse(handle.rawValue());1128 }1129 async title() {1130 const context = await this._utilityContext();1131 return context.evaluate(() => document.title);1132 }1133 _onDetached() {1134 this._stopNetworkIdleTimer();1135 this._detached = true;1136 this._detachedCallback();1137 const error = new Error('Frame was detached');1138 for (const data of this._contextData.values()) {1139 if (data.context) data.context.contextDestroyed(error);1140 data.contextPromise.resolve(error);1141 for (const rerunnableTask of data.rerunnableTasks) rerunnableTask.terminate(error);1142 }1143 if (this._parentFrame) this._parentFrame._childFrames.delete(this);1144 this._parentFrame = null;1145 }1146 async _scheduleRerunnableTask(metadata, selector, body, taskData, options = {}) {1147 const controller = new _progress.ProgressController(metadata, this);1148 return controller.run(async progress => {1149 return await this._scheduleRerunnableTaskWithProgress(progress, selector, body, taskData, options);1150 }, this._page._timeoutSettings.timeout(options));1151 }1152 async _scheduleRerunnableTaskWithProgress(progress, selector, body, taskData, options = {}) {1153 const callbackText = body.toString();1154 return this.retryWithProgress(progress, selector, options, async selectorInFrame => {1155 // Be careful, |this| can be different from |frame|.1156 progress.log(`waiting for selector "${selector}"`);1157 const {1158 frame,1159 info1160 } = selectorInFrame || {1161 frame: this,1162 info: {1163 parsed: {1164 parts: [{1165 name: 'control',1166 body: 'return-empty',1167 source: 'control=return-empty'1168 }]1169 },1170 world: 'utility',1171 strict: !!options.strict1172 }1173 };1174 return await frame._scheduleRerunnableTaskInFrame(progress, info, callbackText, taskData, options);1175 });1176 }1177 async _scheduleRerunnableTaskInFrame(progress, info, callbackText, taskData, options) {1178 progress.throwIfAborted();1179 const data = this._contextData.get(options.mainWorld ? 'main' : info.world); // This potentially runs in a sub-frame.1180 {1181 const rerunnableTask = new RerunnableTask(data, progress, injectedScript => {1182 return injectedScript.evaluateHandle((injected, {1183 info,1184 taskData,1185 callbackText,1186 querySelectorAll,1187 logScale,1188 omitAttached,1189 snapshotName1190 }) => {1191 const callback = injected.eval(callbackText);1192 const poller = logScale ? injected.pollLogScale.bind(injected) : injected.pollRaf.bind(injected);1193 let markedElements = new Set();1194 return poller(progress => {1195 let element;1196 let elements = [];1197 if (querySelectorAll) {1198 elements = injected.querySelectorAll(info.parsed, document);1199 element = elements[0];1200 progress.logRepeating(` selector resolved to ${elements.length} element${elements.length === 1 ? '' : 's'}`);1201 } else {1202 element = injected.querySelector(info.parsed, document, info.strict);1203 elements = element ? [element] : [];1204 if (element) progress.logRepeating(` selector resolved to ${injected.previewNode(element)}`);1205 }1206 if (!element && !omitAttached) return progress.continuePolling;1207 if (snapshotName) {1208 const previouslyMarkedElements = markedElements;1209 markedElements = new Set(elements);1210 for (const e of previouslyMarkedElements) {1211 if (!markedElements.has(e)) e.removeAttribute('__playwright_target__');1212 }1213 for (const e of markedElements) {1214 if (!previouslyMarkedElements.has(e)) e.setAttribute('__playwright_target__', snapshotName);1215 }1216 }1217 return callback(progress, element, taskData, elements);1218 });1219 }, {1220 info,1221 taskData,1222 callbackText,1223 querySelectorAll: options.querySelectorAll,1224 logScale: options.logScale,1225 omitAttached: options.omitAttached,1226 snapshotName: progress.metadata.afterSnapshot1227 });1228 }, true);1229 if (this._detached) rerunnableTask.terminate(new Error('Frame got detached.'));1230 if (data.context) rerunnableTask.rerun(data.context);1231 return await rerunnableTask.promise;1232 }1233 }1234 _scheduleRerunnableHandleTask(progress, world, task) {1235 const data = this._contextData.get(world);1236 const rerunnableTask = new RerunnableTask(data, progress, task, false1237 /* returnByValue */1238 );1239 if (this._detached) rerunnableTask.terminate(new Error('waitForFunction failed: frame got detached.'));1240 if (data.context) rerunnableTask.rerun(data.context);1241 return rerunnableTask.handlePromise;1242 }1243 _setContext(world, context) {1244 const data = this._contextData.get(world);1245 data.context = context;1246 if (context) {1247 data.contextPromise.resolve(context);1248 for (const rerunnableTask of data.rerunnableTasks) rerunnableTask.rerun(context);1249 } else {1250 data.contextPromise = new _async.ManualPromise();1251 }1252 }1253 _contextCreated(world, context) {1254 const data = this._contextData.get(world); // In case of multiple sessions to the same target, there's a race between1255 // connections so we might end up creating multiple isolated worlds.1256 // We can use either.1257 if (data.context) {1258 data.context.contextDestroyed(new Error('Execution context was destroyed, most likely because of a navigation'));1259 this._setContext(world, null);1260 }1261 this._setContext(world, context);1262 }1263 _contextDestroyed(context) {1264 // Sometimes we get this after detach, in which case we should not reset1265 // our already destroyed contexts to something that will never resolve.1266 if (this._detached) return;1267 context.contextDestroyed(new Error('Execution context was destroyed, most likely because of a navigation'));1268 for (const [world, data] of this._contextData) {1269 if (data.context === context) this._setContext(world, null);1270 }1271 }1272 _startNetworkIdleTimer() {1273 (0, _utils.assert)(!this._networkIdleTimer); // We should not start a timer and report networkidle in detached frames.1274 // This happens at least in Firefox for child frames, where we may get requestFinished1275 // after the frame was detached - probably a race in the Firefox itself.1276 if (this._firedLifecycleEvents.has('networkidle') || this._detached) return;1277 this._networkIdleTimer = setTimeout(() => this._onLifecycleEvent('networkidle'), 500);1278 }1279 _stopNetworkIdleTimer() {1280 if (this._networkIdleTimer) clearTimeout(this._networkIdleTimer);1281 this._networkIdleTimer = undefined;1282 }1283 async extendInjectedScript(source, arg) {1284 const context = await this._context('main');1285 const injectedScriptHandle = await context.injectedScript();1286 return injectedScriptHandle.evaluateHandle((injectedScript, {1287 source,1288 arg1289 }) => {1290 return injectedScript.extend(source, arg);1291 }, {1292 source,1293 arg1294 });1295 }1296 async _resolveFrameForSelector(progress, selector, options, scope) {1297 const elementPath = [];1298 progress.cleanupWhenAborted(() => {1299 // Do not await here to avoid being blocked, either by stalled1300 // page (e.g. alert) or unresolved navigation in Chromium.1301 for (const element of elementPath) element.dispose();1302 });1303 let frame = this;1304 const frameChunks = (0, _selectorParser.splitSelectorByFrame)(selector);1305 for (let i = 0; i < frameChunks.length - 1 && progress.isRunning(); ++i) {1306 const info = this._page.parseSelector(frameChunks[i], options);1307 const task = dom.waitForSelectorTask(info, 'attached', false, i === 0 ? scope : undefined);1308 progress.log(` waiting for frame "${(0, _selectorParser.stringifySelector)(frameChunks[i])}"`);1309 const handle = i === 0 && scope ? await frame._runWaitForSelectorTaskOnce(progress, (0, _selectorParser.stringifySelector)(info.parsed), info.world, task) : await frame._scheduleRerunnableHandleTask(progress, info.world, task);1310 const element = handle.asElement();1311 const isIframe = await element.isIframeElement();1312 if (isIframe === 'error:notconnected') return null; // retry1313 if (!isIframe) throw new Error(`Selector "${(0, _selectorParser.stringifySelector)(info.parsed)}" resolved to ${element.preview()}, <iframe> was expected`);1314 frame = await element.contentFrame();1315 element.dispose();1316 if (!frame) return null; // retry1317 }1318 return {1319 frame,1320 info: this._page.parseSelector(frameChunks[frameChunks.length - 1], options)1321 };1322 }1323 async resolveFrameForSelectorNoWait(selector, options = {}, scope) {1324 let frame = this;1325 const frameChunks = (0, _selectorParser.splitSelectorByFrame)(selector);1326 for (let i = 0; i < frameChunks.length - 1; ++i) {1327 const info = this._page.parseSelector(frameChunks[i], options);1328 const element = await this._page.selectors.query(frame, info, i === 0 ? scope : undefined);1329 if (!element) return null;1330 frame = await element.contentFrame();1331 element.dispose();1332 if (!frame) throw new Error(`Selector "${(0, _selectorParser.stringifySelector)(info.parsed)}" resolved to ${element.preview()}, <iframe> was expected`);1333 }1334 return {1335 frame,1336 info: this._page.parseSelector(frameChunks[frameChunks.length - 1], options)1337 };1338 }1339 async _runWaitForSelectorTaskOnce(progress, selector, world, task) {1340 const context = await this._context(world);1341 const injected = await context.injectedScript();1342 try {1343 const pollHandler = new dom.InjectedScriptPollHandler(progress, await task(injected));1344 const result = await pollHandler.finishHandle();1345 progress.cleanupWhenAborted(() => result.dispose());1346 return result;1347 } catch (e) {1348 throw new Error(`Error: frame navigated while waiting for selector "${selector}"`);1349 }1350 }1351}1352exports.Frame = Frame;1353Frame.Events = {1354 Navigation: 'navigation',1355 AddLifecycle: 'addlifecycle',1356 RemoveLifecycle: 'removelifecycle'1357};1358class RerunnableTask {1359 constructor(data, progress, task, returnByValue) {1360 this.promise = void 0;1361 this.handlePromise = void 0;1362 this._task = void 0;1363 this._progress = void 0;1364 this._returnByValue = void 0;1365 this._contextData = void 0;1366 this._task = task;1367 this._progress = progress;1368 this._returnByValue = returnByValue;1369 if (returnByValue) this.promise = new _async.ManualPromise();else this.handlePromise = new _async.ManualPromise();1370 this._contextData = data;1371 this._contextData.rerunnableTasks.add(this);1372 }1373 terminate(error) {1374 this._reject(error);1375 }1376 _resolve(value) {1377 if (this.promise) this.promise.resolve(value);1378 if (this.handlePromise) this.handlePromise.resolve(value);1379 }1380 _reject(error) {1381 if (this.promise) this.promise.reject(error);1382 if (this.handlePromise) this.handlePromise.reject(error);1383 }1384 async rerun(context) {1385 try {1386 const injectedScript = await context.injectedScript();1387 const pollHandler = new dom.InjectedScriptPollHandler(this._progress, await this._task(injectedScript));1388 const result = this._returnByValue ? await pollHandler.finish() : await pollHandler.finishHandle();1389 this._contextData.rerunnableTasks.delete(this);1390 this._resolve(result);1391 } catch (e) {1392 if (js.isJavaScriptErrorInEvaluate(e) || (0, _protocolError.isSessionClosedError)(e)) {1393 this._contextData.rerunnableTasks.delete(this);1394 this._reject(e);1395 } // Unlike other places, we don't check frame for being detached since the whole scope of this1396 // evaluation is within the frame's execution context. So we only let JavaScript errors and1397 // session termination errors go through.1398 // We will try again in the new execution context.1399 }1400 }1401}1402class SignalBarrier {1403 constructor(progress) {1404 this._progress = void 0;1405 this._protectCount = 0;1406 this._promise = new _async.ManualPromise();1407 this._progress = progress;1408 this.retain();1409 }1410 waitFor() {1411 this.release();1412 return this._promise;1413 }1414 async addFrameNavigation(frame) {1415 // Auto-wait top-level navigations only.1416 if (frame.parentFrame()) return;1417 this.retain();1418 const waiter = _helper.helper.waitForEvent(null, frame, Frame.Events.Navigation, e => {1419 if (!e.error && this._progress) this._progress.log(` navigated to "${frame._url}"`);1420 return true;1421 });1422 await Promise.race([frame._page._disconnectedPromise, frame._page._crashedPromise, frame._detachedPromise, waiter.promise]).catch(e => {});1423 waiter.dispose();1424 this.release();1425 }1426 retain() {1427 ++this._protectCount;1428 }1429 release() {1430 --this._protectCount;1431 if (!this._protectCount) this._promise.resolve();1432 }1433}1434function verifyLifecycle(name, waitUntil) {1435 if (waitUntil === 'networkidle0') waitUntil = 'networkidle';1436 if (!types.kLifecycleEvents.has(waitUntil)) throw new Error(`${name}: expected one of (load|domcontentloaded|networkidle|commit)`);1437 return waitUntil;...

Full Screen

Full Screen

selectorParser.js

Source:selectorParser.js Github

copy

Full Screen

...45 capture: result.capture,46 parts47 };48}49function splitSelectorByFrame(selectorText) {50 const selector = parseSelector(selectorText);51 const result = [];52 let chunk = {53 parts: []54 };55 let chunkStartIndex = 0;56 for (let i = 0; i < selector.parts.length; ++i) {57 const part = selector.parts[i];58 if (part.name === 'control' && part.body === 'enter-frame') {59 if (!chunk.parts.length) throw new _selectorErrors.InvalidSelectorError('Selector cannot start with entering frame, select the iframe first');60 result.push(chunk);61 chunk = {62 parts: []63 };...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('playwright/lib/server/dom.js');2const { ElementHandle } = require('playwright/lib/server/dom.js');3const { Frame } = require('playwright/lib/server/dom.js');4const frame = new Frame();5const elementHandle = new ElementHandle();6const result = splitSelectorByFrame(frame, elementHandle, selector);7console.log(result);

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;2const { Frame } = require('@playwright/test/lib/server/frames');3const { ElementHandle } = require('@playwright/test/lib/server/dom');4const { Page } = require('@playwright/test/lib/server/page');5const { selectors } = require('@playwright/test/lib/server/selectors');6const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');7const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;8const { Frame } = require('@playwright/test/lib/server/frames');9const { ElementHandle } = require('@playwright/test/lib/server/dom');10const { Page } = require('@playwright/test/lib/server/page');11const { selectors } = require('@playwright/test/lib/server/selectors');12const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');13const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;14const { Frame } = require('@playwright/test/lib/server/frames');15const { ElementHandle } = require('@playwright/test/lib/server/dom');16const { Page } = require('@playwright/test/lib/server/page');17const { selectors } = require('@playwright/test/lib/server/selectors');18const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');19const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;20const { Frame } = require('@playwright/test/lib/server/frames');21const { ElementHandle } = require('@playwright/test/lib/server/dom');22const { Page } = require('@playwright/test/lib/server/page');23const { selectors } = require('@playwright/test/lib/server/selectors');24const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');25const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;26const { Frame } = require('@playwright/test/lib/server/frames');27const { ElementHandle } = require('@playwright/test/lib/server/dom');28const { Page }

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;2const { Frame } = require('@playwright/test/lib/server/frames');3const { ElementHandle } = require('@playwright/test/lib/server/dom');4const { Page } = require('@playwright/test/lib/server/page');5const { selectors } = require('@playwright/test/lib/server/selectors');6const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');7const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;8const { Frame } = require('@playwright/test/lib/server/frames');9const { ElementHandle } = require('@playwright/test/lib/server/dom');10const { Page } = require('@playwright/test/lib/server/page');11const { selectors } = require('@playwright/test/lib/server/selectors');12const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');13const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;14const { Frame } = require('@playwright/test/lib/server/frames');15const { ElementHandle } = require('@playwright/test/lib/server/dom');16const { Page } = require('@playwright/test/lib/server/page');17const { selectors } = require('@playwright/test/lib/server/selectors');18const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');19const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;20const { Frame } = require('@playwright/test/lib/server/frames');21const { ElementHandle } = require('@playwright/test/lib/server/dom');22const { Page } = require('@playwright/test/lib/server/page');23const { selectors } = require('@playwright/test/lib/server/selectors');24const { Selector } = require('@playwright/test/lib/server/selectors/selectorImpl');25const { splitSelectorByFrame } = require('@playwright/test/lib/utils').internalAPI;26const { Frame } = require('@playwright/test/lib/server/frames');27const { ElementHandle } = require('@playwright/test/lib/server/dom');28const { Page }

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require("playwright/lib/server/dom");2const { Frame, Page } = require("playwright/lib/server/chromium/crPage");3const { ElementHandle } = require("playwright/lib/server/chromium/crElementHandle");4const { JSHandle } = require("playwright/lib/server/chromium/crJSHandle");5const { BrowserContext } = require("playwright/lib/server/chromium/crBrowser");6const { Browser } = require("playwright/lib/server/chromium/crBrowser");7const { splitSelectorByFrame } = require("playwright/lib/server/dom");8const { Frame, Page } = require("playwright/lib/server/chromium/crPage");9const { ElementHandle } = require("playwright/lib/server/chromium/crElementHandle");10const { JSHandle } = require("playwright/lib/server/chromium/crJSHandle");11const { BrowserContext } = require("playwright/lib/server/chromium/crBrowser");12const { Browser } = require("playwright/lib/server/chromium/crBrowser");13async function test() {14 const browser = await chromium.launch({15 });16 const context = await browser.newContext();17 const page = await context.newPage();18 const frame = page.mainFrame();19 const elementHandle = await frame.$('input[name="q"]');20 const jsHandle = await elementHandle.getProperty('value');21 console.log(await jsHandle.jsonValue());22 await browser.close();23}24test();25const { splitSelectorByFrame } = require("playwright/lib/server/dom");26const { Frame, Page } = require("playwright/lib/server/chromium/crPage");27const { ElementHandle } = require("playwright/lib/server/chromium/crElementHandle");28const { JSHandle } = require("playwright/lib/server/chromium/crJSHandle");29const { BrowserContext } = require("playwright/lib/server/chromium/crBrowser");30const { Browser } = require("playwright/lib/server/chromium/crBrowser");31async function test() {32 const browser = await chromium.launch({

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('playwright/lib/server/dom');2const { parseSelector } = require('playwright/lib/server/dom');3const { parseSelectorV2 } = require('playwright/lib/server/dom');4const { parseSelectorV1 } = require('playwright/lib/server/dom');5const { parseSelectorV0 } = require('playwright/lib/server/dom');6const { parseSelectorV3 } = require('playwright/lib/server/dom');7const { frame, selector: frameSelector } = splitSelectorByFrame(selector);8console.log(frame, frameSelector);

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('playwright/lib/server/dom');2const { parseSelector } = require('playwright/lib/serverselectorsselectorParser');3const selector = arseSeector('css=div#frame1 >> css=div#frame2 >> css=div#frame3 >> css=div#frame4 >> css=div#frame5 >> css=div#frame6 >> css=div#frame7 >> css=div#frame8 >> css=div#frame9 >> css=div#frame10 >> css=div#frame11 >> css=div#frame12 >> css=div#frame13 >> css=div#frame14 >> css=div#frame15 >> css=div#frame16 >> css=div#frame17 >> css=div#frame18 >> css=div#frame19 >> css=div#frame20 >> css=div#frame21 >> css=div#frame22 >> css=div#frame23 >> css=div#frame24 >> css=div#frame25 >> css=div#frame26 >> css=div#frame27 >> css=div#frame28 >> css=div#frame29 >> css=div#frame30 >> css=div#frame31 >> css=div#frame32 >> css=div#frame33 >> css=div#frame34 >> css=div#frame35 >> css=div#frame36 >> css=div#frame37 >> css=div#frame38 >> css=div#frame39 >> css=div#frame40 >> css=div#frame41 >> css=div#frame42 >> css=div#frame43 >> css=div#frame44 >> css=div#frame45 >> css=div#frame46 >> css=div#frame47 >> css=div#frame48 >> css=div#frame49 >> css=div#frame50 >> css=div#frame51 >> css=div#frme52 >> css=div#frame53 >> css=div#frame54 >> css=div#frame55 >> css=div#frame56 >> css=div#frame57 >> css=div#frame58 >> css=div#frame59 >> css=div#frame60 >> css=div#frame61 >> css=div#frame62 >> css=div#frame63 >> css=div#frame64 >> css=div#frame65 >> css=4const { frame, selector: frameSelector } = splitSelectorByFrame(selector);5console.log(frame, frameSelector);6const { frame, selector: frameSelector } = splitSelectorByFrame(selector);7console.log(frame, frameSelector);8const { frame, selector: frameSelector } = splitSelectorByFrame(selector);9console.log(frame, frameSelector);10const { frame, selector: frameSelector } = sp

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('@playwright/test/lib/server/frames');2const selector = 'css=div > iframe css=div;3const { frame, selector: remainingSelector } = await splitSelectorByFrame(page, selector4con.t { sdev/delectorByFrame } = require('@playwright/test/lib/server/channels');5const selector = 'css=div > iframe > css=div';6const { frame, socs/sel: remainingSelector } = await splitSelectorByFrame(page, selector);7const element = await frame.waitForSelector('css=div');8const element = await page.waitForSelector('css=div');9const element = await frame.waitForSelector('css=div', { timeout: 2000 });10const element = await page.waitForSelector('css=div', { timeout: 2000 });

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('playwright/lib/server/frames');2const { context } = require('playwright/lib/server/chromium');3const { frame, selector } = splitSelectorByFrame(context, '.frame1 .frame2 #id');4const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>');5const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id');6const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', '.frame1 .frame2 #id');7const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', 'data:text/html, <h1>Hi</h1>');8const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id');9const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', '.frame1 .frame2 #id');10const { frame, selector } = splitSelectorByFrame(context, 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', 'data:text/html, <h1>Hi</h1>.frame1 .frame2 #id', 'data:text/html, <h1>Hi</h1>');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('@playwright/test/lib/server/frames');2const selector = 'css=div > iframe > css=div';3const { frame, selector: remainingSelector } = await splitSelectorByFrame(page, selector);4const { splitSelectorByFrame } = require('@playwright/test/lib/server/channels');5const selector = 'css=div > iframe > css=div';6const { frame, selector: remainingSelector } = await splitSelectorByFrame(page, selector);7const element = await frame.waitForSelector('css=div');8const element = await page.waitForSelector('css=div');9const element = await frame.waitForSelector('css=div', { timeout: 2000 });10const element = await page.waitForSelector('css=div', { timeout: 2000 });

Full Screen

Using AI Code Generation

copy

Full Screen

1const { splitSelectorByFrame } = require('playwright/lib/client/helper');2const { parseSelector } = require('playwright/lib/client/selectorParser');3const result = splitSelectorByFrame(selector);4console.log(result);5 {6 selector: { engine: 'css', selector: 'body' }7 },8 {9 selector: {10 }11 },12 {13 selector: {14 }15 }16const { splitSelectorByFrame } = require('playwright/lib/client/helper');17const { parseSelector } = require('playwright/lib/client/selectorParser');18const result = splitSelectorByFrame(selector);19console.log(result);20 {21 selector: { engine: 'css', selector: 'body' }22 },23 {24 selector: {25 }26 },27 {28 selector: {29 }30 }

Full Screen

Playwright tutorial

LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.

Chapters:

  1. What is Playwright : Playwright is comparatively new but has gained good popularity. Get to know some history of the Playwright with some interesting facts connected with it.
  2. How To Install Playwright : Learn in detail about what basic configuration and dependencies are required for installing Playwright and run a test. Get a step-by-step direction for installing the Playwright automation framework.
  3. Playwright Futuristic Features: Launched in 2020, Playwright gained huge popularity quickly because of some obliging features such as Playwright Test Generator and Inspector, Playwright Reporter, Playwright auto-waiting mechanism and etc. Read up on those features to master Playwright testing.
  4. What is Component Testing: Component testing in Playwright is a unique feature that allows a tester to test a single component of a web application without integrating them with other elements. Learn how to perform Component testing on the Playwright automation framework.
  5. Inputs And Buttons In Playwright: Every website has Input boxes and buttons; learn about testing inputs and buttons with different scenarios and examples.
  6. Functions and Selectors in Playwright: Learn how to launch the Chromium browser with Playwright. Also, gain a better understanding of some important functions like “BrowserContext,” which allows you to run multiple browser sessions, and “newPage” which interacts with a page.
  7. Handling Alerts and Dropdowns in Playwright : Playwright interact with different types of alerts and pop-ups, such as simple, confirmation, and prompt, and different types of dropdowns, such as single selector and multi-selector get your hands-on with handling alerts and dropdown in Playright testing.
  8. Playwright vs Puppeteer: Get to know about the difference between two testing frameworks and how they are different than one another, which browsers they support, and what features they provide.
  9. Run Playwright Tests on LambdaTest: Playwright testing with LambdaTest leverages test performance to the utmost. You can run multiple Playwright tests in Parallel with the LammbdaTest test cloud. Get a step-by-step guide to run your Playwright test on the LambdaTest platform.
  10. Playwright Python Tutorial: Playwright automation framework support all major languages such as Python, JavaScript, TypeScript, .NET and etc. However, there are various advantages to Python end-to-end testing with Playwright because of its versatile utility. Get the hang of Playwright python testing with this chapter.
  11. Playwright End To End Testing Tutorial: Get your hands on with Playwright end-to-end testing and learn to use some exciting features such as TraceViewer, Debugging, Networking, Component testing, Visual testing, and many more.
  12. Playwright Video Tutorial: Watch the video tutorials on Playwright testing from experts and get a consecutive in-depth explanation of Playwright automation testing.

Run Playwright Internal automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful