Best JavaScript code snippet using playwright-internal
frames.js
Source:frames.js
...104 }105 frameRequestedNavigation(frameId, documentId) {106 const frame = this._frames.get(frameId);107 if (!frame) return;108 for (const barrier of this._signalBarriers) barrier.addFrameNavigation(frame);109 if (frame.pendingDocument() && frame.pendingDocument().documentId === documentId) {110 // Do not override request with undefined.111 return;112 }113 frame.setPendingDocument({114 documentId,115 request: undefined116 });117 }118 frameCommittedNewDocumentNavigation(frameId, url, name, documentId, initial) {119 const frame = this._frames.get(frameId);120 this.removeChildFramesRecursively(frame);121 this.clearWebSockets(frame);122 frame._url = url;123 frame._name = name;124 let keepPending;125 const pendingDocument = frame.pendingDocument();126 if (pendingDocument) {127 if (pendingDocument.documentId === undefined) {128 // Pending with unknown documentId - assume it is the one being committed.129 pendingDocument.documentId = documentId;130 }131 if (pendingDocument.documentId === documentId) {132 // Committing a pending document.133 frame._currentDocument = pendingDocument;134 } else {135 // Sometimes, we already have a new pending when the old one commits.136 // An example would be Chromium error page followed by a new navigation request,137 // where the error page commit arrives after Network.requestWillBeSent for the138 // new navigation.139 // We commit, but keep the pending request since it's not done yet.140 keepPending = pendingDocument;141 frame._currentDocument = {142 documentId,143 request: undefined144 };145 }146 frame.setPendingDocument(undefined);147 } else {148 // No pending - just commit a new document.149 frame._currentDocument = {150 documentId,151 request: undefined152 };153 }154 frame._onClearLifecycle();155 const navigationEvent = {156 url,157 name,158 newDocument: frame._currentDocument159 };160 frame.emit(Frame.Events.Navigation, navigationEvent);161 this._responses.length = 0;162 if (!initial) {163 _debugLogger.debugLogger.log('api', ` navigated to "${url}"`);164 this._page.frameNavigatedToNewDocument(frame);165 } // Restore pending if any - see comments above about keepPending.166 frame.setPendingDocument(keepPending);167 }168 frameCommittedSameDocumentNavigation(frameId, url) {169 const frame = this._frames.get(frameId);170 if (!frame) return;171 frame._url = url;172 const navigationEvent = {173 url,174 name: frame._name175 };176 frame.emit(Frame.Events.Navigation, navigationEvent);177 _debugLogger.debugLogger.log('api', ` navigated to "${url}"`);178 }179 frameAbortedNavigation(frameId, errorText, documentId) {180 const frame = this._frames.get(frameId);181 if (!frame || !frame.pendingDocument()) return;182 if (documentId !== undefined && frame.pendingDocument().documentId !== documentId) return;183 const navigationEvent = {184 url: frame._url,185 name: frame._name,186 newDocument: frame.pendingDocument(),187 error: new Error(errorText)188 };189 frame.setPendingDocument(undefined);190 frame.emit(Frame.Events.Navigation, navigationEvent);191 }192 frameDetached(frameId) {193 const frame = this._frames.get(frameId);194 if (frame) this._removeFramesRecursively(frame);195 }196 frameStoppedLoading(frameId) {197 this.frameLifecycleEvent(frameId, 'domcontentloaded');198 this.frameLifecycleEvent(frameId, 'load');199 }200 frameLifecycleEvent(frameId, event) {201 const frame = this._frames.get(frameId);202 if (frame) frame._onLifecycleEvent(event);203 }204 requestStarted(request, route) {205 const frame = request.frame();206 this._inflightRequestStarted(request);207 if (request._documentId) frame.setPendingDocument({208 documentId: request._documentId,209 request210 });211 if (request._isFavicon) {212 if (route) route.continue(request, {});213 return;214 }215 this._page._browserContext.emit(_browserContext.BrowserContext.Events.Request, request);216 if (route) this._page._requestStarted(request, route);217 }218 requestReceivedResponse(response) {219 if (response.request()._isFavicon) return;220 this._responses.push(response);221 this._page._browserContext.emit(_browserContext.BrowserContext.Events.Response, response);222 }223 requestFinished(request) {224 this._inflightRequestFinished(request);225 if (request._isFavicon) return;226 this._page._browserContext.emit(_browserContext.BrowserContext.Events.RequestFinished, request);227 }228 requestFailed(request, canceled) {229 const frame = request.frame();230 this._inflightRequestFinished(request);231 if (frame.pendingDocument() && frame.pendingDocument().request === request) {232 let errorText = request.failure().errorText;233 if (canceled) errorText += '; maybe frame was detached?';234 this.frameAbortedNavigation(frame._id, errorText, frame.pendingDocument().documentId);235 }236 if (request._isFavicon) return;237 this._page._browserContext.emit(_browserContext.BrowserContext.Events.RequestFailed, request);238 }239 removeChildFramesRecursively(frame) {240 for (const child of frame.childFrames()) this._removeFramesRecursively(child);241 }242 _removeFramesRecursively(frame) {243 this.removeChildFramesRecursively(frame);244 frame._onDetached();245 this._frames.delete(frame._id);246 if (!this._page.isClosed()) this._page.emit(_page.Page.Events.FrameDetached, frame);247 }248 _inflightRequestFinished(request) {249 const frame = request.frame();250 if (request._isFavicon) return;251 if (!frame._inflightRequests.has(request)) return;252 frame._inflightRequests.delete(request);253 if (frame._inflightRequests.size === 0) frame._startNetworkIdleTimer();254 }255 _inflightRequestStarted(request) {256 const frame = request.frame();257 if (request._isFavicon) return;258 frame._inflightRequests.add(request);259 if (frame._inflightRequests.size === 1) frame._stopNetworkIdleTimer();260 }261 interceptConsoleMessage(message) {262 if (message.type() !== 'debug') return false;263 const tag = message.text();264 const handler = this._consoleMessageTags.get(tag);265 if (!handler) return false;266 this._consoleMessageTags.delete(tag);267 handler();268 return true;269 }270 clearWebSockets(frame) {271 // TODO: attribute sockets to frames.272 if (frame.parentFrame()) return;273 this._webSockets.clear();274 }275 onWebSocketCreated(requestId, url) {276 const ws = new network.WebSocket(this._page, url);277 this._webSockets.set(requestId, ws);278 }279 onWebSocketRequest(requestId) {280 const ws = this._webSockets.get(requestId);281 if (ws) this._page.emit(_page.Page.Events.WebSocket, ws);282 }283 onWebSocketResponse(requestId, status, statusText) {284 const ws = this._webSockets.get(requestId);285 if (status < 400) return;286 if (ws) ws.error(`${statusText}: ${status}`);287 }288 onWebSocketFrameSent(requestId, opcode, data) {289 const ws = this._webSockets.get(requestId);290 if (ws) ws.frameSent(opcode, data);291 }292 webSocketFrameReceived(requestId, opcode, data) {293 const ws = this._webSockets.get(requestId);294 if (ws) ws.frameReceived(opcode, data);295 }296 webSocketClosed(requestId) {297 const ws = this._webSockets.get(requestId);298 if (ws) ws.closed();299 this._webSockets.delete(requestId);300 }301 webSocketError(requestId, errorMessage) {302 const ws = this._webSockets.get(requestId);303 if (ws) ws.error(errorMessage);304 }305}306exports.FrameManager = FrameManager;307class Frame extends _instrumentation.SdkObject {308 constructor(page, id, parentFrame) {309 super(page, 'frame');310 this._id = void 0;311 this._firedLifecycleEvents = new Set();312 this._subtreeLifecycleEvents = new Set();313 this._currentDocument = void 0;314 this._pendingDocument = void 0;315 this._page = void 0;316 this._parentFrame = void 0;317 this._url = '';318 this._detached = false;319 this._contextData = new Map();320 this._childFrames = new Set();321 this._name = '';322 this._inflightRequests = new Set();323 this._networkIdleTimer = void 0;324 this._setContentCounter = 0;325 this._detachedPromise = void 0;326 this._detachedCallback = () => {};327 this._nonStallingEvaluations = new Set();328 this.attribution.frame = this;329 this._id = id;330 this._page = page;331 this._parentFrame = parentFrame;332 this._currentDocument = {333 documentId: undefined,334 request: undefined335 };336 this._detachedPromise = new Promise(x => this._detachedCallback = x);337 this._contextData.set('main', {338 contextPromise: new Promise(() => {}),339 contextResolveCallback: () => {},340 context: null,341 rerunnableTasks: new Set()342 });343 this._contextData.set('utility', {344 contextPromise: new Promise(() => {}),345 contextResolveCallback: () => {},346 context: null,347 rerunnableTasks: new Set()348 });349 this._setContext('main', null);350 this._setContext('utility', null);351 if (this._parentFrame) this._parentFrame._childFrames.add(this);352 }353 _onLifecycleEvent(event) {354 if (this._firedLifecycleEvents.has(event)) return;355 this._firedLifecycleEvents.add(event); // Recalculate subtree lifecycle for the whole tree - it should not be that big.356 this._page.mainFrame()._recalculateLifecycle();357 }358 _onClearLifecycle() {359 this._firedLifecycleEvents.clear(); // Recalculate subtree lifecycle for the whole tree - it should not be that big.360 this._page.mainFrame()._recalculateLifecycle(); // Keep the current navigation request if any.361 this._inflightRequests = new Set(Array.from(this._inflightRequests).filter(request => request === this._currentDocument.request));362 this._stopNetworkIdleTimer();363 if (this._inflightRequests.size === 0) this._startNetworkIdleTimer();364 }365 setPendingDocument(documentInfo) {366 this._pendingDocument = documentInfo;367 if (documentInfo) this._invalidateNonStallingEvaluations();368 }369 pendingDocument() {370 return this._pendingDocument;371 }372 async _invalidateNonStallingEvaluations() {373 if (!this._nonStallingEvaluations) return;374 const error = new Error('Navigation interrupted the evaluation');375 for (const callback of this._nonStallingEvaluations) callback(error);376 }377 async nonStallingRawEvaluateInExistingMainContext(expression) {378 if (this._pendingDocument) throw new Error('Frame is currently attempting a navigation');379 const context = this._existingMainContext();380 if (!context) throw new Error('Frame does not yet have a main execution context');381 let callback = () => {};382 const frameInvalidated = new Promise((f, r) => callback = r);383 this._nonStallingEvaluations.add(callback);384 try {385 return await Promise.race([context.rawEvaluateJSON(expression), frameInvalidated]);386 } finally {387 this._nonStallingEvaluations.delete(callback);388 }389 }390 async nonStallingEvaluateInExistingContext(expression, isFunction, world) {391 var _this$_contextData$ge;392 if (this._pendingDocument) throw new Error('Frame is currently attempting a navigation');393 const context = (_this$_contextData$ge = this._contextData.get(world)) === null || _this$_contextData$ge === void 0 ? void 0 : _this$_contextData$ge.context;394 if (!context) throw new Error('Frame does not yet have the execution context');395 let callback = () => {};396 const frameInvalidated = new Promise((f, r) => callback = r);397 this._nonStallingEvaluations.add(callback);398 try {399 return await Promise.race([context.evaluateExpression(expression, isFunction), frameInvalidated]);400 } finally {401 this._nonStallingEvaluations.delete(callback);402 }403 }404 _recalculateLifecycle() {405 const events = new Set(this._firedLifecycleEvents);406 for (const child of this._childFrames) {407 child._recalculateLifecycle(); // We require a particular lifecycle event to be fired in the whole408 // frame subtree, and then consider it done.409 for (const event of events) {410 if (!child._subtreeLifecycleEvents.has(event)) events.delete(event);411 }412 }413 const mainFrame = this._page.mainFrame();414 for (const event of events) {415 // Checking whether we have already notified about this event.416 if (!this._subtreeLifecycleEvents.has(event)) {417 this.emit(Frame.Events.AddLifecycle, event);418 if (this === mainFrame && this._url !== 'about:blank') _debugLogger.debugLogger.log('api', ` "${event}" event fired`);419 if (this === mainFrame && event === 'load') this._page.emit(_page.Page.Events.Load);420 if (this === mainFrame && event === 'domcontentloaded') this._page.emit(_page.Page.Events.DOMContentLoaded);421 }422 }423 for (const event of this._subtreeLifecycleEvents) {424 if (!events.has(event)) this.emit(Frame.Events.RemoveLifecycle, event);425 }426 this._subtreeLifecycleEvents = events;427 }428 async raceNavigationAction(action) {429 return Promise.race([this._page._disconnectedPromise.then(() => {430 throw new Error('Navigation failed because page was closed!');431 }), this._page._crashedPromise.then(() => {432 throw new Error('Navigation failed because page crashed!');433 }), this._detachedPromise.then(() => {434 throw new Error('Navigating frame was detached!');435 }), action()]);436 }437 async goto(metadata, url, options = {}) {438 const constructedNavigationURL = (0, _utils.constructURLBasedOnBaseURL)(this._page._browserContext._options.baseURL, url);439 const controller = new _progress.ProgressController(metadata, this);440 return controller.run(progress => this._goto(progress, constructedNavigationURL, options), this._page._timeoutSettings.navigationTimeout(options));441 }442 async _goto(progress, url, options) {443 return this.raceNavigationAction(async () => {444 const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);445 progress.log(`navigating to "${url}", waiting until "${waitUntil}"`);446 const headers = this._page._state.extraHTTPHeaders || [];447 const refererHeader = headers.find(h => h.name.toLowerCase() === 'referer');448 let referer = refererHeader ? refererHeader.value : undefined;449 if (options.referer !== undefined) {450 if (referer !== undefined && referer !== options.referer) throw new Error('"referer" is already specified as extra HTTP header');451 referer = options.referer;452 }453 url = _helper.helper.completeUserURL(url);454 const sameDocument = _helper.helper.waitForEvent(progress, this, Frame.Events.Navigation, e => !e.newDocument);455 const navigateResult = await this._page._delegate.navigateFrame(this, url, referer);456 let event;457 if (navigateResult.newDocumentId) {458 sameDocument.dispose();459 event = await _helper.helper.waitForEvent(progress, this, Frame.Events.Navigation, event => {460 // We are interested either in this specific document, or any other document that461 // did commit and replaced the expected document.462 return event.newDocument && (event.newDocument.documentId === navigateResult.newDocumentId || !event.error);463 }).promise;464 if (event.newDocument.documentId !== navigateResult.newDocumentId) {465 // This is just a sanity check. In practice, new navigation should466 // cancel the previous one and report "request cancelled"-like error.467 throw new Error('Navigation interrupted by another one');468 }469 if (event.error) throw event.error;470 } else {471 event = await sameDocument.promise;472 }473 if (!this._subtreeLifecycleEvents.has(waitUntil)) await _helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, e => e === waitUntil).promise;474 const request = event.newDocument ? event.newDocument.request : undefined;475 const response = request ? request._finalRequest().response() : null;476 await this._page._doSlowMo();477 return response;478 });479 }480 async _waitForNavigation(progress, options) {481 const waitUntil = verifyLifecycle('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);482 progress.log(`waiting for navigation until "${waitUntil}"`);483 const navigationEvent = await _helper.helper.waitForEvent(progress, this, Frame.Events.Navigation, event => {484 // Any failed navigation results in a rejection.485 if (event.error) return true;486 progress.log(` navigated to "${this._url}"`);487 return true;488 }).promise;489 if (navigationEvent.error) throw navigationEvent.error;490 if (!this._subtreeLifecycleEvents.has(waitUntil)) await _helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, e => e === waitUntil).promise;491 const request = navigationEvent.newDocument ? navigationEvent.newDocument.request : undefined;492 return request ? request._finalRequest().response() : null;493 }494 async _waitForLoadState(progress, state) {495 const waitUntil = verifyLifecycle('state', state);496 if (!this._subtreeLifecycleEvents.has(waitUntil)) await _helper.helper.waitForEvent(progress, this, Frame.Events.AddLifecycle, e => e === waitUntil).promise;497 }498 async frameElement() {499 return this._page._delegate.getFrameElement(this);500 }501 _context(world) {502 if (this._detached) throw new Error(`Execution Context is not available in detached frame "${this.url()}" (are you trying to evaluate?)`);503 return this._contextData.get(world).contextPromise;504 }505 _mainContext() {506 return this._context('main');507 }508 _existingMainContext() {509 var _this$_contextData$ge2;510 return ((_this$_contextData$ge2 = this._contextData.get('main')) === null || _this$_contextData$ge2 === void 0 ? void 0 : _this$_contextData$ge2.context) || null;511 }512 _utilityContext() {513 return this._context('utility');514 }515 async evaluateExpressionHandleAndWaitForSignals(expression, isFunction, arg, world = 'main') {516 const context = await this._context(world);517 const handle = await context.evaluateExpressionHandleAndWaitForSignals(expression, isFunction, arg);518 if (world === 'main') await this._page._doSlowMo();519 return handle;520 }521 async evaluateExpression(expression, isFunction, arg, world = 'main') {522 const context = await this._context(world);523 const value = await context.evaluateExpression(expression, isFunction, arg);524 if (world === 'main') await this._page._doSlowMo();525 return value;526 }527 async evaluateExpressionAndWaitForSignals(expression, isFunction, arg, world = 'main') {528 const context = await this._context(world);529 const value = await context.evaluateExpressionAndWaitForSignals(expression, isFunction, arg);530 if (world === 'main') await this._page._doSlowMo();531 return value;532 }533 async querySelector(selector, options) {534 _debugLogger.debugLogger.log('api', ` finding element using the selector "${selector}"`);535 return this._page.selectors.query(this, selector, options);536 }537 async waitForSelector(metadata, selector, options = {}) {538 const controller = new _progress.ProgressController(metadata, this);539 if (options.visibility) throw new Error('options.visibility is not supported, did you mean options.state?');540 if (options.waitFor && options.waitFor !== 'visible') throw new Error('options.waitFor is not supported, did you mean options.state?');541 const {542 state = 'visible'543 } = options;544 if (!['attached', 'detached', 'visible', 'hidden'].includes(state)) throw new Error(`state: expected one of (attached|detached|visible|hidden)`);545 const info = this._page.parseSelector(selector, options);546 const task = dom.waitForSelectorTask(info, state);547 return controller.run(async progress => {548 progress.log(`waiting for selector "${selector}"${state === 'attached' ? '' : ' to be ' + state}`);549 while (progress.isRunning()) {550 const result = await this._scheduleRerunnableHandleTask(progress, info.world, task);551 if (!result.asElement()) {552 result.dispose();553 return null;554 }555 if (options.__testHookBeforeAdoptNode) await options.__testHookBeforeAdoptNode();556 try {557 const handle = result.asElement();558 const adopted = await handle._adoptTo(await this._mainContext());559 return adopted;560 } catch (e) {561 // Navigated while trying to adopt the node.562 if (!js.isContextDestroyedError(e) && !e.message.includes(dom.kUnableToAdoptErrorMessage)) throw e;563 result.dispose();564 }565 }566 return null;567 }, this._page._timeoutSettings.timeout(options));568 }569 async dispatchEvent(metadata, selector, type, eventInit, options = {}) {570 const controller = new _progress.ProgressController(metadata, this);571 const info = this._page.parseSelector(selector, options);572 const task = dom.dispatchEventTask(info, type, eventInit || {});573 await controller.run(async progress => {574 progress.log(`Dispatching "${type}" event on selector "${selector}"...`); // Note: we always dispatch events in the main world.575 await this._scheduleRerunnableTask(progress, 'main', task);576 }, this._page._timeoutSettings.timeout(options));577 await this._page._doSlowMo();578 }579 async evalOnSelectorAndWaitForSignals(selector, strict, expression, isFunction, arg) {580 const handle = await this.querySelector(selector, {581 strict582 });583 if (!handle) throw new Error(`Error: failed to find element matching selector "${selector}"`);584 const result = await handle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);585 handle.dispose();586 return result;587 }588 async evalOnSelectorAllAndWaitForSignals(selector, expression, isFunction, arg) {589 const arrayHandle = await this._page.selectors._queryArray(this, selector);590 const result = await arrayHandle.evaluateExpressionAndWaitForSignals(expression, isFunction, true, arg);591 arrayHandle.dispose();592 return result;593 }594 async querySelectorAll(selector) {595 return this._page.selectors._queryAll(this, selector, undefined, true596 /* adoptToMain */597 );598 }599 async content() {600 const context = await this._utilityContext();601 return context.evaluate(() => {602 let retVal = '';603 if (document.doctype) retVal = new XMLSerializer().serializeToString(document.doctype);604 if (document.documentElement) retVal += document.documentElement.outerHTML;605 return retVal;606 });607 }608 async setContent(metadata, html, options = {}) {609 const controller = new _progress.ProgressController(metadata, this);610 return controller.run(progress => this.raceNavigationAction(async () => {611 const waitUntil = options.waitUntil === undefined ? 'load' : options.waitUntil;612 progress.log(`setting frame content, waiting until "${waitUntil}"`);613 const tag = `--playwright--set--content--${this._id}--${++this._setContentCounter}--`;614 const context = await this._utilityContext();615 const lifecyclePromise = new Promise((resolve, reject) => {616 this._page._frameManager._consoleMessageTags.set(tag, () => {617 // Clear lifecycle right after document.open() - see 'tag' below.618 this._onClearLifecycle();619 this._waitForLoadState(progress, waitUntil).then(resolve).catch(reject);620 });621 });622 const contentPromise = context.evaluate(({623 html,624 tag625 }) => {626 window.stop();627 document.open();628 console.debug(tag); // eslint-disable-line no-console629 document.write(html);630 document.close();631 }, {632 html,633 tag634 });635 await Promise.all([contentPromise, lifecyclePromise]);636 await this._page._doSlowMo();637 }), this._page._timeoutSettings.navigationTimeout(options));638 }639 name() {640 return this._name || '';641 }642 url() {643 return this._url;644 }645 parentFrame() {646 return this._parentFrame;647 }648 childFrames() {649 return Array.from(this._childFrames);650 }651 async addScriptTag(params) {652 const {653 url = null,654 content = null,655 type = ''656 } = params;657 if (!url && !content) throw new Error('Provide an object with a `url`, `path` or `content` property');658 const context = await this._mainContext();659 return this._raceWithCSPError(async () => {660 if (url !== null) return (await context.evaluateHandle(addScriptUrl, {661 url,662 type663 })).asElement();664 const result = (await context.evaluateHandle(addScriptContent, {665 content: content,666 type667 })).asElement(); // Another round trip to the browser to ensure that we receive CSP error messages668 // (if any) logged asynchronously in a separate task on the content main thread.669 if (this._page._delegate.cspErrorsAsynchronousForInlineScipts) await context.evaluate(() => true);670 return result;671 });672 async function addScriptUrl(params) {673 const script = document.createElement('script');674 script.src = params.url;675 if (params.type) script.type = params.type;676 const promise = new Promise((res, rej) => {677 script.onload = res;678 script.onerror = e => rej(typeof e === 'string' ? new Error(e) : new Error(`Failed to load script at ${script.src}`));679 });680 document.head.appendChild(script);681 await promise;682 return script;683 }684 function addScriptContent(params) {685 const script = document.createElement('script');686 script.type = params.type || 'text/javascript';687 script.text = params.content;688 let error = null;689 script.onerror = e => error = e;690 document.head.appendChild(script);691 if (error) throw error;692 return script;693 }694 }695 async addStyleTag(params) {696 const {697 url = null,698 content = null699 } = params;700 if (!url && !content) throw new Error('Provide an object with a `url`, `path` or `content` property');701 const context = await this._mainContext();702 return this._raceWithCSPError(async () => {703 if (url !== null) return (await context.evaluateHandle(addStyleUrl, url)).asElement();704 return (await context.evaluateHandle(addStyleContent, content)).asElement();705 });706 async function addStyleUrl(url) {707 const link = document.createElement('link');708 link.rel = 'stylesheet';709 link.href = url;710 const promise = new Promise((res, rej) => {711 link.onload = res;712 link.onerror = rej;713 });714 document.head.appendChild(link);715 await promise;716 return link;717 }718 async function addStyleContent(content) {719 const style = document.createElement('style');720 style.type = 'text/css';721 style.appendChild(document.createTextNode(content));722 const promise = new Promise((res, rej) => {723 style.onload = res;724 style.onerror = rej;725 });726 document.head.appendChild(style);727 await promise;728 return style;729 }730 }731 async _raceWithCSPError(func) {732 const listeners = [];733 let result;734 let error;735 let cspMessage;736 const actionPromise = new Promise(async resolve => {737 try {738 result = await func();739 } catch (e) {740 error = e;741 }742 resolve();743 });744 const errorPromise = new Promise(resolve => {745 listeners.push(_eventsHelper.eventsHelper.addEventListener(this._page, _page.Page.Events.Console, message => {746 if (message.type() === 'error' && message.text().includes('Content Security Policy')) {747 cspMessage = message;748 resolve();749 }750 }));751 });752 await Promise.race([actionPromise, errorPromise]);753 _eventsHelper.eventsHelper.removeEventListeners(listeners);754 if (cspMessage) throw new Error(cspMessage.text());755 if (error) throw error;756 return result;757 }758 async _retryWithProgressIfNotConnected(progress, selector, strict, action) {759 const info = this._page.parseSelector(selector, {760 strict761 });762 while (progress.isRunning()) {763 progress.log(`waiting for selector "${selector}"`);764 const task = dom.waitForSelectorTask(info, 'attached');765 const handle = await this._scheduleRerunnableHandleTask(progress, info.world, task);766 const element = handle.asElement();767 progress.cleanupWhenAborted(() => {768 // Do not await here to avoid being blocked, either by stalled769 // page (e.g. alert) or unresolved navigation in Chromium.770 element.dispose();771 });772 const result = await action(element);773 element.dispose();774 if (result === 'error:notconnected') {775 progress.log('element was detached from the DOM, retrying');776 continue;777 }778 return result;779 }780 return undefined;781 }782 async _retryWithSelectorIfNotConnected(controller, selector, options, action) {783 return controller.run(async progress => {784 return this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => action(progress, handle));785 }, this._page._timeoutSettings.timeout(options));786 }787 async click(metadata, selector, options) {788 const controller = new _progress.ProgressController(metadata, this);789 return controller.run(async progress => {790 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._click(progress, options)));791 }, this._page._timeoutSettings.timeout(options));792 }793 async dblclick(metadata, selector, options = {}) {794 const controller = new _progress.ProgressController(metadata, this);795 return controller.run(async progress => {796 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._dblclick(progress, options)));797 }, this._page._timeoutSettings.timeout(options));798 }799 async dragAndDrop(metadata, source, target, options = {}) {800 const controller = new _progress.ProgressController(metadata, this);801 await controller.run(async progress => {802 await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, source, options.strict, async handle => {803 return handle._retryPointerAction(progress, 'move and down', false, async point => {804 await this._page.mouse.move(point.x, point.y);805 await this._page.mouse.down();806 }, { ...options,807 position: options.sourcePosition,808 timeout: progress.timeUntilDeadline()809 });810 }));811 await dom.assertDone(await this._retryWithProgressIfNotConnected(progress, target, options.strict, async handle => {812 return handle._retryPointerAction(progress, 'move and up', false, async point => {813 await this._page.mouse.move(point.x, point.y);814 await this._page.mouse.up();815 }, { ...options,816 position: options.targetPosition,817 timeout: progress.timeUntilDeadline()818 });819 }));820 }, this._page._timeoutSettings.timeout(options));821 }822 async tap(metadata, selector, options) {823 const controller = new _progress.ProgressController(metadata, this);824 return controller.run(async progress => {825 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._tap(progress, options)));826 }, this._page._timeoutSettings.timeout(options));827 }828 async fill(metadata, selector, value, options) {829 const controller = new _progress.ProgressController(metadata, this);830 return controller.run(async progress => {831 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._fill(progress, value, options)));832 }, this._page._timeoutSettings.timeout(options));833 }834 async focus(metadata, selector, options = {}) {835 const controller = new _progress.ProgressController(metadata, this);836 await this._retryWithSelectorIfNotConnected(controller, selector, options, (progress, handle) => handle._focus(progress));837 await this._page._doSlowMo();838 }839 async textContent(metadata, selector, options = {}) {840 const controller = new _progress.ProgressController(metadata, this);841 const info = this._page.parseSelector(selector, options);842 const task = dom.textContentTask(info);843 return controller.run(async progress => {844 progress.log(` retrieving textContent from "${selector}"`);845 return this._scheduleRerunnableTask(progress, info.world, task);846 }, this._page._timeoutSettings.timeout(options));847 }848 async innerText(metadata, selector, options = {}) {849 const controller = new _progress.ProgressController(metadata, this);850 const info = this._page.parseSelector(selector, options);851 const task = dom.innerTextTask(info);852 return controller.run(async progress => {853 progress.log(` retrieving innerText from "${selector}"`);854 const result = dom.throwFatalDOMError(await this._scheduleRerunnableTask(progress, info.world, task));855 return result.innerText;856 }, this._page._timeoutSettings.timeout(options));857 }858 async innerHTML(metadata, selector, options = {}) {859 const controller = new _progress.ProgressController(metadata, this);860 const info = this._page.parseSelector(selector, options);861 const task = dom.innerHTMLTask(info);862 return controller.run(async progress => {863 progress.log(` retrieving innerHTML from "${selector}"`);864 return this._scheduleRerunnableTask(progress, info.world, task);865 }, this._page._timeoutSettings.timeout(options));866 }867 async getAttribute(metadata, selector, name, options = {}) {868 const controller = new _progress.ProgressController(metadata, this);869 const info = this._page.parseSelector(selector, options);870 const task = dom.getAttributeTask(info, name);871 return controller.run(async progress => {872 progress.log(` retrieving attribute "${name}" from "${selector}"`);873 return this._scheduleRerunnableTask(progress, info.world, task);874 }, this._page._timeoutSettings.timeout(options));875 }876 async inputValue(metadata, selector, options = {}) {877 const controller = new _progress.ProgressController(metadata, this);878 const info = this._page.parseSelector(selector, options);879 const task = dom.inputValueTask(info);880 return controller.run(async progress => {881 progress.log(` retrieving value from "${selector}"`);882 return dom.throwFatalDOMError(await this._scheduleRerunnableTask(progress, info.world, task));883 }, this._page._timeoutSettings.timeout(options));884 }885 async _checkElementState(metadata, selector, state, options = {}) {886 const controller = new _progress.ProgressController(metadata, this);887 const info = this._page.parseSelector(selector, options);888 const task = dom.elementStateTask(info, state);889 const result = await controller.run(async progress => {890 progress.log(` checking "${state}" state of "${selector}"`);891 return this._scheduleRerunnableTask(progress, info.world, task);892 }, this._page._timeoutSettings.timeout(options));893 return dom.throwFatalDOMError(dom.throwRetargetableDOMError(result));894 }895 async isVisible(metadata, selector, options = {}) {896 const controller = new _progress.ProgressController(metadata, this);897 return controller.run(async progress => {898 progress.log(` checking visibility of "${selector}"`);899 const element = await this.querySelector(selector, options);900 return element ? await element.isVisible() : false;901 }, this._page._timeoutSettings.timeout(options));902 }903 async isHidden(metadata, selector, options = {}) {904 return !(await this.isVisible(metadata, selector, options));905 }906 async isDisabled(metadata, selector, options = {}) {907 return this._checkElementState(metadata, selector, 'disabled', options);908 }909 async isEnabled(metadata, selector, options = {}) {910 return this._checkElementState(metadata, selector, 'enabled', options);911 }912 async isEditable(metadata, selector, options = {}) {913 return this._checkElementState(metadata, selector, 'editable', options);914 }915 async isChecked(metadata, selector, options = {}) {916 return this._checkElementState(metadata, selector, 'checked', options);917 }918 async hover(metadata, selector, options = {}) {919 const controller = new _progress.ProgressController(metadata, this);920 return controller.run(async progress => {921 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._hover(progress, options)));922 }, this._page._timeoutSettings.timeout(options));923 }924 async selectOption(metadata, selector, elements, values, options = {}) {925 const controller = new _progress.ProgressController(metadata, this);926 return controller.run(async progress => {927 return await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._selectOption(progress, elements, values, options));928 }, this._page._timeoutSettings.timeout(options));929 }930 async setInputFiles(metadata, selector, files, options = {}) {931 const controller = new _progress.ProgressController(metadata, this);932 return controller.run(async progress => {933 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._setInputFiles(progress, files, options)));934 }, this._page._timeoutSettings.timeout(options));935 }936 async type(metadata, selector, text, options = {}) {937 const controller = new _progress.ProgressController(metadata, this);938 return controller.run(async progress => {939 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._type(progress, text, options)));940 }, this._page._timeoutSettings.timeout(options));941 }942 async press(metadata, selector, key, options = {}) {943 const controller = new _progress.ProgressController(metadata, this);944 return controller.run(async progress => {945 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._press(progress, key, options)));946 }, this._page._timeoutSettings.timeout(options));947 }948 async check(metadata, selector, options = {}) {949 const controller = new _progress.ProgressController(metadata, this);950 return controller.run(async progress => {951 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._setChecked(progress, true, options)));952 }, this._page._timeoutSettings.timeout(options));953 }954 async uncheck(metadata, selector, options = {}) {955 const controller = new _progress.ProgressController(metadata, this);956 return controller.run(async progress => {957 return dom.assertDone(await this._retryWithProgressIfNotConnected(progress, selector, options.strict, handle => handle._setChecked(progress, false, options)));958 }, this._page._timeoutSettings.timeout(options));959 }960 async _waitForFunctionExpression(metadata, expression, isFunction, arg, options, world = 'main') {961 const controller = new _progress.ProgressController(metadata, this);962 if (typeof options.pollingInterval === 'number') (0, _utils.assert)(options.pollingInterval > 0, 'Cannot poll with non-positive interval: ' + options.pollingInterval);963 expression = js.normalizeEvaluationExpression(expression, isFunction);964 const task = injectedScript => injectedScript.evaluateHandle((injectedScript, {965 expression,966 isFunction,967 polling,968 arg969 }) => {970 const predicate = arg => {971 let result = self.eval(expression);972 if (isFunction === true) {973 result = result(arg);974 } else if (isFunction === false) {975 result = result;976 } else {977 // auto detect.978 if (typeof result === 'function') result = result(arg);979 }980 return result;981 };982 if (typeof polling !== 'number') return injectedScript.pollRaf((progress, continuePolling) => predicate(arg) || continuePolling);983 return injectedScript.pollInterval(polling, (progress, continuePolling) => predicate(arg) || continuePolling);984 }, {985 expression,986 isFunction,987 polling: options.pollingInterval,988 arg989 });990 return controller.run(progress => this._scheduleRerunnableHandleTask(progress, world, task), this._page._timeoutSettings.timeout(options));991 }992 async waitForFunctionValueInUtility(progress, pageFunction) {993 const expression = `() => {994 const result = (${pageFunction})();995 if (!result)996 return result;997 return JSON.stringify(result);998 }`;999 const handle = await this._waitForFunctionExpression((0, _instrumentation.internalCallMetadata)(), expression, true, undefined, {1000 timeout: progress.timeUntilDeadline()1001 }, 'utility');1002 return JSON.parse(handle.rawValue());1003 }1004 async title() {1005 const context = await this._utilityContext();1006 return context.evaluate(() => document.title);1007 }1008 _onDetached() {1009 this._stopNetworkIdleTimer();1010 this._detached = true;1011 this._detachedCallback();1012 for (const data of this._contextData.values()) {1013 for (const rerunnableTask of data.rerunnableTasks) rerunnableTask.terminate(new Error('waitForFunction failed: frame got detached.'));1014 }1015 if (this._parentFrame) this._parentFrame._childFrames.delete(this);1016 this._parentFrame = null;1017 }1018 _scheduleRerunnableTask(progress, world, task) {1019 const data = this._contextData.get(world);1020 const rerunnableTask = new RerunnableTask(data, progress, task, true1021 /* returnByValue */1022 );1023 if (this._detached) rerunnableTask.terminate(new Error('waitForFunction failed: frame got detached.'));1024 if (data.context) rerunnableTask.rerun(data.context);1025 return rerunnableTask.promise;1026 }1027 _scheduleRerunnableHandleTask(progress, world, task) {1028 const data = this._contextData.get(world);1029 const rerunnableTask = new RerunnableTask(data, progress, task, false1030 /* returnByValue */1031 );1032 if (this._detached) rerunnableTask.terminate(new Error('waitForFunction failed: frame got detached.'));1033 if (data.context) rerunnableTask.rerun(data.context);1034 return rerunnableTask.promise;1035 }1036 _setContext(world, context) {1037 const data = this._contextData.get(world);1038 data.context = context;1039 if (context) {1040 data.contextResolveCallback.call(null, context);1041 for (const rerunnableTask of data.rerunnableTasks) rerunnableTask.rerun(context);1042 } else {1043 data.contextPromise = new Promise(fulfill => {1044 data.contextResolveCallback = fulfill;1045 });1046 }1047 }1048 _contextCreated(world, context) {1049 const data = this._contextData.get(world); // In case of multiple sessions to the same target, there's a race between1050 // connections so we might end up creating multiple isolated worlds.1051 // We can use either.1052 if (data.context) this._setContext(world, null);1053 this._setContext(world, context);1054 }1055 _contextDestroyed(context) {1056 for (const [world, data] of this._contextData) {1057 if (data.context === context) this._setContext(world, null);1058 }1059 }1060 _startNetworkIdleTimer() {1061 (0, _utils.assert)(!this._networkIdleTimer); // We should not start a timer and report networkidle in detached frames.1062 // This happens at least in Firefox for child frames, where we may get requestFinished1063 // after the frame was detached - probably a race in the Firefox itself.1064 if (this._firedLifecycleEvents.has('networkidle') || this._detached) return;1065 this._networkIdleTimer = setTimeout(() => this._onLifecycleEvent('networkidle'), 500);1066 }1067 _stopNetworkIdleTimer() {1068 if (this._networkIdleTimer) clearTimeout(this._networkIdleTimer);1069 this._networkIdleTimer = undefined;1070 }1071 async extendInjectedScript(world, source, arg) {1072 const context = await this._context(world);1073 const injectedScriptHandle = await context.injectedScript();1074 return injectedScriptHandle.evaluateHandle((injectedScript, {1075 source,1076 arg1077 }) => {1078 return injectedScript.extend(source, arg);1079 }, {1080 source,1081 arg1082 });1083 }1084}1085exports.Frame = Frame;1086Frame.Events = {1087 Navigation: 'navigation',1088 AddLifecycle: 'addlifecycle',1089 RemoveLifecycle: 'removelifecycle'1090};1091class RerunnableTask {1092 constructor(data, progress, task, returnByValue) {1093 this.promise = void 0;1094 this._task = void 0;1095 this._resolve = () => {};1096 this._reject = () => {};1097 this._progress = void 0;1098 this._returnByValue = void 0;1099 this._contextData = void 0;1100 this._task = task;1101 this._progress = progress;1102 this._returnByValue = returnByValue;1103 this._contextData = data;1104 this._contextData.rerunnableTasks.add(this);1105 this.promise = new Promise((resolve, reject) => {1106 // The task is either resolved with a value, or rejected with a meaningful evaluation error.1107 this._resolve = resolve;1108 this._reject = reject;1109 });1110 }1111 terminate(error) {1112 this._reject(error);1113 }1114 async rerun(context) {1115 try {1116 const injectedScript = await context.injectedScript();1117 const pollHandler = new dom.InjectedScriptPollHandler(this._progress, await this._task(injectedScript));1118 const result = this._returnByValue ? await pollHandler.finish() : await pollHandler.finishHandle();1119 this._contextData.rerunnableTasks.delete(this);1120 this._resolve(result);1121 } catch (e) {1122 // We will try again in the new execution context.1123 if (js.isContextDestroyedError(e)) return;1124 this._contextData.rerunnableTasks.delete(this);1125 this._reject(e);1126 }1127 }1128}1129class SignalBarrier {1130 constructor(progress) {1131 this._progress = void 0;1132 this._protectCount = 0;1133 this._promise = void 0;1134 this._promiseCallback = () => {};1135 this._progress = progress;1136 this._promise = new Promise(f => this._promiseCallback = f);1137 this.retain();1138 }1139 waitFor() {1140 this.release();1141 return this._promise;1142 }1143 async addFrameNavigation(frame) {1144 // Auto-wait top-level navigations only.1145 if (frame.parentFrame()) return;1146 this.retain();1147 const waiter = _helper.helper.waitForEvent(null, frame, Frame.Events.Navigation, e => {1148 if (!e.error && this._progress) this._progress.log(` navigated to "${frame._url}"`);1149 return true;1150 });1151 await Promise.race([frame._page._disconnectedPromise, frame._page._crashedPromise, frame._detachedPromise, waiter.promise]).catch(e => {});1152 waiter.dispose();1153 this.release();1154 }1155 retain() {1156 ++this._protectCount;1157 }...
Using AI Code Generation
1const {chromium} = require('playwright');2(async () => {3 const browser = await chromium.launch({headless: false});4 const context = await browser.newContext();5 const page = await context.newPage();6 await page.addInitScript(() => {7 window.__playwright__ = {8 addFrameNavigation: (url) => {9 window.addEventListener('load', () => {10 if (window.location.href === url) {11 window.__playwright__ = undefined;12 window.dispatchEvent(new CustomEvent('frameNavigated'));13 }14 });15 }16 };17 });18 await page.waitForEvent('frameNavigated');19 console.log('Frame navigated');20 await browser.close();21})();22const {chromium} = require('playwright');23(async () => {24 const browser = await chromium.launch({headless: false});25 const context = await browser.newContext();26 const page = await context.newPage();27 await page.addInitScript(() => {28 window.__playwright__ = {29 addFrameNavigation: (url) => {30 window.addEventListener('load', () => {31 if (window.location.href === url) {32 window.__playwright__ = undefined;33 window.dispatchEvent(new CustomEvent('frameNavigated'));34 }35 });36 }37 };38 });39 await page.waitForEvent('frameNavigated');40 console.log('Frame navigated');41 await browser.close();42})();
Using AI Code Generation
1const { addFrameNavigation } = require('playwright/lib/internal/frames');2const { chromium } = require('playwright');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 await page.waitForLoadState();8 console.log(page.url());9})();10const { helper } = require('./helper');11const { assert } = helper;12const { Page } = require('./page');13const { JSHandle } = require('./jsHandle');14const { TimeoutError } = require('./errors');15const { Events } = require('./events');16class Frame {17 async addFrameNavigation(frame, url) {18 await frame._page._delegate.navigateFrame(frame, url);19 }20}21module.exports = { Frame };
Using AI Code Generation
1const { addFrameNavigation } = require('@playwright/test/lib/server/frames');2const { test } = require('@playwright/test');3test('test', async ({ page }) => {4 await page.evaluate(addFrameNavigation, page.frames()[0]);5 await page.frames()[0].waitForNavigation();6 await page.frames()[0].waitForNavigation();7});8const { addFrameNavigation } = require('@playwright/test/lib/server/frames');9const { test } = require('@playwright/test');10test('test', async ({ page }) => {11 await page.evaluate(addFrameNavigation, page.frames()[0]);12});13const { waitForLoadState } = require('@playwright/test/lib/server/page');14const { test } = require('@playwright/test');15test('test', async ({ page }) => {16 await page.evaluate(waitForLoadState, 'domcontentloaded');17 await page.evaluate(waitForLoadState, 'networkidle');18});19const { addFrameNavigation, waitForLoadState } = require('@playwright/test/lib/server/frames');20module.exports = {21 use: {22 },23};24const { test } = require
Using AI Code Generation
1const { addFrameNavigation } = require('playwright/lib/server/chromium/crNetworkManager');2const { chromium } = require('playwright');3const browser = await chromium.launch();4const context = await browser.newContext();5const page = await context.newPage();6await browser.close();
Using AI Code Generation
1const { addFrameNavigation } = require('@playwright/test/lib/internal/page');2const frame = page.frames()[1];3await frame.waitForLoadState('load');4console.log(await frame.title());5const { addFrameNavigation } = require('@playwright/test/lib/internal/browserContext');6await frame.waitForLoadState('load');7console.log(await frame.title());8const { addFrameNavigation } = require('@playwright/test/lib/internal/browser');9await frame.waitForLoadState('load');10console.log(await frame.title());
Using AI Code Generation
1await context.addFrameNavigation({ url: newUrl, name: "frame1" });2const value = await frame1.evaluate(() => {3 return document.querySelector("input").value;4});5console.log(value);6await frame1.evaluate((value) => {7 document.querySelector("input").value = value;8}, "new value");9const value2 = await frame1.evaluate(() => {10 return document.querySelector("input").value;11});12console.log(value2);13await frame1.evaluate((value) => {14 document.querySelector("input").value = value;15}, "new value");16const value3 = await frame1.evaluate(() => {17 return document.querySelector("input").value;18});19console.log(value3);20await frame1.evaluate((value) => {21 document.querySelector("input").value = value;22}, "new value");23const value4 = await frame1.evaluate(() => {24 return document.querySelector("input").value;25});26console.log(value4);27await frame1.evaluate((value) => {28 document.querySelector("input").value = value;29}, "new value");30const value5 = await frame1.evaluate(() => {31 return document.querySelector("input").value;32});33console.log(value5);
Using AI Code Generation
1const frame = await page.frames()[1];2await frame.fill("input[name=q]", "playwright");3await frame.click("input[value=Google Search]");4await frame.click("text=Playwright - GitHub");5await frame.waitForLoadState("domcontentloaded");6await frame.click("text=Playwright is a Node library to automate Chromium, Firefox and WebKit with a single API");7await frame.waitForLoadState("domcontentloaded");8await frame.click("text=Documentation");9await frame.waitForLoadState("domcontentloaded");10await frame.click("text=API");11await frame.waitForLoadState("domcontentloaded");12await frame.click("text=Page");13await frame.waitForLoadState("domcontentloaded");14const frame = await page.frames()[1];15await frame.fill("input[name=q]", "playwright");16await frame.click("input[value=Google Search]");17await frame.click("text=Playwright - GitHub");18await frame.waitForLoadState("domcontentloaded");19await frame.click("text=Playwright is a Node library to automate Chromium, Firefox and WebKit with a single API");20await frame.waitForLoadState("domcontentloaded");21await frame.click("text=Documentation");22await frame.waitForLoadState("domcontentloaded");23await frame.click("text=API");24await frame.waitForLoadState("domcontentloaded");25await frame.click("text=Page");26await frame.waitForLoadState("domcontentloaded");27const frame = await page.frames()[1];28await frame.fill("input[name=q]", "playwright");29await frame.click("input[value=Google Search]");30await frame.click("text=Playwright - GitHub");31await frame.waitForLoadState("dom
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.
Get 100 minutes of automation test minutes FREE!!