How to use isSafeCloseError method in Playwright Internal

Best JavaScript code snippet using playwright-internal

page.js

Source:page.js Github

copy

Full Screen

1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.Page = exports.BindingCall = void 0;6var _events = require("./events");7var _utils = require("../utils/utils");8var _timeoutSettings = require("../utils/timeoutSettings");9var _serializers = require("../protocol/serializers");10var _accessibility = require("./accessibility");11var _channelOwner = require("./channelOwner");12var _consoleMessage = require("./consoleMessage");13var _dialog = require("./dialog");14var _download = require("./download");15var _elementHandle = require("./elementHandle");16var _worker = require("./worker");17var _frame = require("./frame");18var _input = require("./input");19var _jsHandle = require("./jsHandle");20var _network = require("./network");21var _fileChooser = require("./fileChooser");22var _buffer = require("buffer");23var _coverage = require("./coverage");24var _waiter = require("./waiter");25var _fs = _interopRequireDefault(require("fs"));26var _path = _interopRequireDefault(require("path"));27var _clientHelper = require("./clientHelper");28var _errors = require("../utils/errors");29var _video = require("./video");30var _artifact = require("./artifact");31function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }32/**33 * Copyright 2017 Google Inc. All rights reserved.34 * Modifications copyright (c) Microsoft Corporation.35 *36 * Licensed under the Apache License, Version 2.0 (the "License");37 * you may not use this file except in compliance with the License.38 * You may obtain a copy of the License at39 *40 * http://www.apache.org/licenses/LICENSE-2.041 *42 * Unless required by applicable law or agreed to in writing, software43 * distributed under the License is distributed on an "AS IS" BASIS,44 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.45 * See the License for the specific language governing permissions and46 * limitations under the License.47 */48class Page extends _channelOwner.ChannelOwner {49 static from(page) {50 return page._object;51 }52 static fromNullable(page) {53 return page ? Page.from(page) : null;54 }55 constructor(parent, type, guid, initializer) {56 super(parent, type, guid, initializer);57 this._browserContext = void 0;58 this._ownedContext = void 0;59 this._mainFrame = void 0;60 this._frames = new Set();61 this._workers = new Set();62 this._closed = false;63 this._closedOrCrashedPromise = void 0;64 this._viewportSize = void 0;65 this._routes = [];66 this.accessibility = void 0;67 this.coverage = void 0;68 this.keyboard = void 0;69 this.mouse = void 0;70 this.request = void 0;71 this.touchscreen = void 0;72 this._bindings = new Map();73 this._timeoutSettings = void 0;74 this._video = null;75 this._opener = void 0;76 this._browserContext = parent;77 this._timeoutSettings = new _timeoutSettings.TimeoutSettings(this._browserContext._timeoutSettings);78 this.accessibility = new _accessibility.Accessibility(this._channel);79 this.keyboard = new _input.Keyboard(this);80 this.mouse = new _input.Mouse(this);81 this.request = this._browserContext.request;82 this.touchscreen = new _input.Touchscreen(this);83 this._mainFrame = _frame.Frame.from(initializer.mainFrame);84 this._mainFrame._page = this;85 this._frames.add(this._mainFrame);86 this._viewportSize = initializer.viewportSize || null;87 this._closed = initializer.isClosed;88 this._opener = Page.fromNullable(initializer.opener);89 this._channel.on('bindingCall', ({90 binding91 }) => this._onBinding(BindingCall.from(binding)));92 this._channel.on('close', () => this._onClose());93 this._channel.on('console', ({94 message95 }) => this.emit(_events.Events.Page.Console, _consoleMessage.ConsoleMessage.from(message)));96 this._channel.on('crash', () => this._onCrash());97 this._channel.on('dialog', ({98 dialog99 }) => {100 const dialogObj = _dialog.Dialog.from(dialog);101 if (!this.emit(_events.Events.Page.Dialog, dialogObj)) {102 if (dialogObj.type() === 'beforeunload') dialog.accept({}).catch(() => {});else dialog.dismiss().catch(() => {});103 }104 });105 this._channel.on('domcontentloaded', () => this.emit(_events.Events.Page.DOMContentLoaded, this));106 this._channel.on('download', ({107 url,108 suggestedFilename,109 artifact110 }) => {111 const artifactObject = _artifact.Artifact.from(artifact);112 this.emit(_events.Events.Page.Download, new _download.Download(this, url, suggestedFilename, artifactObject));113 });114 this._channel.on('fileChooser', ({115 element,116 isMultiple117 }) => this.emit(_events.Events.Page.FileChooser, new _fileChooser.FileChooser(this, _elementHandle.ElementHandle.from(element), isMultiple)));118 this._channel.on('frameAttached', ({119 frame120 }) => this._onFrameAttached(_frame.Frame.from(frame)));121 this._channel.on('frameDetached', ({122 frame123 }) => this._onFrameDetached(_frame.Frame.from(frame)));124 this._channel.on('load', () => this.emit(_events.Events.Page.Load, this));125 this._channel.on('pageError', ({126 error127 }) => this.emit(_events.Events.Page.PageError, (0, _serializers.parseError)(error)));128 this._channel.on('route', ({129 route,130 request131 }) => this._onRoute(_network.Route.from(route), _network.Request.from(request)));132 this._channel.on('video', ({133 artifact134 }) => {135 const artifactObject = _artifact.Artifact.from(artifact);136 this._forceVideo()._artifactReady(artifactObject);137 });138 this._channel.on('webSocket', ({139 webSocket140 }) => this.emit(_events.Events.Page.WebSocket, _network.WebSocket.from(webSocket)));141 this._channel.on('worker', ({142 worker143 }) => this._onWorker(_worker.Worker.from(worker)));144 this.coverage = new _coverage.Coverage(this._channel);145 this._closedOrCrashedPromise = Promise.race([new Promise(f => this.once(_events.Events.Page.Close, f)), new Promise(f => this.once(_events.Events.Page.Crash, f))]);146 }147 _onFrameAttached(frame) {148 frame._page = this;149 this._frames.add(frame);150 if (frame._parentFrame) frame._parentFrame._childFrames.add(frame);151 this.emit(_events.Events.Page.FrameAttached, frame);152 }153 _onFrameDetached(frame) {154 this._frames.delete(frame);155 frame._detached = true;156 if (frame._parentFrame) frame._parentFrame._childFrames.delete(frame);157 this.emit(_events.Events.Page.FrameDetached, frame);158 }159 _onRoute(route, request) {160 for (const routeHandler of this._routes) {161 if (routeHandler.matches(request.url())) {162 try {163 routeHandler.handle(route, request);164 } finally {165 if (!routeHandler.isActive()) {166 this._routes.splice(this._routes.indexOf(routeHandler), 1);167 if (!this._routes.length) this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});168 }169 }170 return;171 }172 }173 this._browserContext._onRoute(route, request);174 }175 async _onBinding(bindingCall) {176 const func = this._bindings.get(bindingCall._initializer.name);177 if (func) {178 await bindingCall.call(func);179 return;180 }181 await this._browserContext._onBinding(bindingCall);182 }183 _onWorker(worker) {184 this._workers.add(worker);185 worker._page = this;186 this.emit(_events.Events.Page.Worker, worker);187 }188 _onClose() {189 this._closed = true;190 this._browserContext._pages.delete(this);191 this._browserContext._backgroundPages.delete(this);192 this.emit(_events.Events.Page.Close, this);193 }194 _onCrash() {195 this.emit(_events.Events.Page.Crash, this);196 }197 context() {198 return this._browserContext;199 }200 async opener() {201 if (!this._opener || this._opener.isClosed()) return null;202 return this._opener;203 }204 mainFrame() {205 return this._mainFrame;206 }207 frame(frameSelector) {208 const name = (0, _utils.isString)(frameSelector) ? frameSelector : frameSelector.name;209 const url = (0, _utils.isObject)(frameSelector) ? frameSelector.url : undefined;210 (0, _utils.assert)(name || url, 'Either name or url matcher should be specified');211 return this.frames().find(f => {212 if (name) return f.name() === name;213 return (0, _clientHelper.urlMatches)(this._browserContext._options.baseURL, f.url(), url);214 }) || null;215 }216 frames() {217 return [...this._frames];218 }219 setDefaultNavigationTimeout(timeout) {220 this._timeoutSettings.setDefaultNavigationTimeout(timeout);221 this._wrapApiCall(async () => {222 this._channel.setDefaultNavigationTimeoutNoReply({223 timeout224 });225 }, true);226 }227 setDefaultTimeout(timeout) {228 this._timeoutSettings.setDefaultTimeout(timeout);229 this._wrapApiCall(async () => {230 this._channel.setDefaultTimeoutNoReply({231 timeout232 });233 }, true);234 }235 _forceVideo() {236 if (!this._video) this._video = new _video.Video(this, this._connection);237 return this._video;238 }239 video() {240 // Note: we are creating Video object lazily, because we do not know241 // BrowserContextOptions when constructing the page - it is assigned242 // too late during launchPersistentContext.243 if (!this._browserContext._options.recordVideo) return null;244 return this._forceVideo();245 }246 async $(selector, options) {247 return this._mainFrame.$(selector, options);248 }249 async waitForSelector(selector, options) {250 return this._mainFrame.waitForSelector(selector, options);251 }252 async dispatchEvent(selector, type, eventInit, options) {253 return this._mainFrame.dispatchEvent(selector, type, eventInit, options);254 }255 async evaluateHandle(pageFunction, arg) {256 (0, _jsHandle.assertMaxArguments)(arguments.length, 2);257 return this._mainFrame.evaluateHandle(pageFunction, arg);258 }259 async $eval(selector, pageFunction, arg) {260 (0, _jsHandle.assertMaxArguments)(arguments.length, 3);261 return this._mainFrame.$eval(selector, pageFunction, arg);262 }263 async $$eval(selector, pageFunction, arg) {264 (0, _jsHandle.assertMaxArguments)(arguments.length, 3);265 return this._mainFrame.$$eval(selector, pageFunction, arg);266 }267 async $$(selector) {268 return this._mainFrame.$$(selector);269 }270 async addScriptTag(options = {}) {271 return this._mainFrame.addScriptTag(options);272 }273 async addStyleTag(options = {}) {274 return this._mainFrame.addStyleTag(options);275 }276 async exposeFunction(name, callback) {277 await this._channel.exposeBinding({278 name279 });280 const binding = (source, ...args) => callback(...args);281 this._bindings.set(name, binding);282 }283 async exposeBinding(name, callback, options = {}) {284 await this._channel.exposeBinding({285 name,286 needsHandle: options.handle287 });288 this._bindings.set(name, callback);289 }290 async setExtraHTTPHeaders(headers) {291 (0, _network.validateHeaders)(headers);292 await this._channel.setExtraHTTPHeaders({293 headers: (0, _utils.headersObjectToArray)(headers)294 });295 }296 url() {297 return this._mainFrame.url();298 }299 async content() {300 return this._mainFrame.content();301 }302 async setContent(html, options) {303 return this._mainFrame.setContent(html, options);304 }305 async goto(url, options) {306 return this._mainFrame.goto(url, options);307 }308 async reload(options = {}) {309 const waitUntil = (0, _frame.verifyLoadState)('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);310 return _network.Response.fromNullable((await this._channel.reload({ ...options,311 waitUntil312 })).response);313 }314 async waitForLoadState(state, options) {315 return this._mainFrame.waitForLoadState(state, options);316 }317 async waitForNavigation(options) {318 return this._mainFrame.waitForNavigation(options);319 }320 async waitForURL(url, options) {321 return this._mainFrame.waitForURL(url, options);322 }323 async waitForRequest(urlOrPredicate, options = {}) {324 const predicate = request => {325 if ((0, _utils.isString)(urlOrPredicate) || (0, _utils.isRegExp)(urlOrPredicate)) return (0, _clientHelper.urlMatches)(this._browserContext._options.baseURL, request.url(), urlOrPredicate);326 return urlOrPredicate(request);327 };328 const trimmedUrl = trimUrl(urlOrPredicate);329 const logLine = trimmedUrl ? `waiting for request ${trimmedUrl}` : undefined;330 return this._waitForEvent(_events.Events.Page.Request, {331 predicate,332 timeout: options.timeout333 }, logLine);334 }335 async waitForResponse(urlOrPredicate, options = {}) {336 const predicate = response => {337 if ((0, _utils.isString)(urlOrPredicate) || (0, _utils.isRegExp)(urlOrPredicate)) return (0, _clientHelper.urlMatches)(this._browserContext._options.baseURL, response.url(), urlOrPredicate);338 return urlOrPredicate(response);339 };340 const trimmedUrl = trimUrl(urlOrPredicate);341 const logLine = trimmedUrl ? `waiting for response ${trimmedUrl}` : undefined;342 return this._waitForEvent(_events.Events.Page.Response, {343 predicate,344 timeout: options.timeout345 }, logLine);346 }347 async waitForEvent(event, optionsOrPredicate = {}) {348 return this._waitForEvent(event, optionsOrPredicate, `waiting for event "${event}"`);349 }350 async _waitForEvent(event, optionsOrPredicate, logLine) {351 return this._wrapApiCall(async () => {352 const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);353 const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;354 const waiter = _waiter.Waiter.createForEvent(this, event);355 if (logLine) waiter.log(logLine);356 waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);357 if (event !== _events.Events.Page.Crash) waiter.rejectOnEvent(this, _events.Events.Page.Crash, new Error('Page crashed'));358 if (event !== _events.Events.Page.Close) waiter.rejectOnEvent(this, _events.Events.Page.Close, new Error('Page closed'));359 const result = await waiter.waitForEvent(this, event, predicate);360 waiter.dispose();361 return result;362 });363 }364 async goBack(options = {}) {365 const waitUntil = (0, _frame.verifyLoadState)('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);366 return _network.Response.fromNullable((await this._channel.goBack({ ...options,367 waitUntil368 })).response);369 }370 async goForward(options = {}) {371 const waitUntil = (0, _frame.verifyLoadState)('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);372 return _network.Response.fromNullable((await this._channel.goForward({ ...options,373 waitUntil374 })).response);375 }376 async emulateMedia(options = {}) {377 await this._channel.emulateMedia({378 media: options.media === null ? 'null' : options.media,379 colorScheme: options.colorScheme === null ? 'null' : options.colorScheme,380 reducedMotion: options.reducedMotion === null ? 'null' : options.reducedMotion,381 forcedColors: options.forcedColors === null ? 'null' : options.forcedColors382 });383 }384 async setViewportSize(viewportSize) {385 this._viewportSize = viewportSize;386 await this._channel.setViewportSize({387 viewportSize388 });389 }390 viewportSize() {391 return this._viewportSize;392 }393 async evaluate(pageFunction, arg) {394 (0, _jsHandle.assertMaxArguments)(arguments.length, 2);395 return this._mainFrame.evaluate(pageFunction, arg);396 }397 async addInitScript(script, arg) {398 const source = await (0, _clientHelper.evaluationScript)(script, arg);399 await this._channel.addInitScript({400 source401 });402 }403 async route(url, handler, options = {}) {404 this._routes.unshift(new _network.RouteHandler(this._browserContext._options.baseURL, url, handler, options.times));405 if (this._routes.length === 1) await this._channel.setNetworkInterceptionEnabled({406 enabled: true407 });408 }409 async unroute(url, handler) {410 this._routes = this._routes.filter(route => route.url !== url || handler && route.handler !== handler);411 if (!this._routes.length) await this._disableInterception();412 }413 async _disableInterception() {414 await this._channel.setNetworkInterceptionEnabled({415 enabled: false416 });417 }418 async screenshot(options = {}) {419 const copy = { ...options,420 mask: undefined421 };422 if (!copy.type) copy.type = (0, _elementHandle.determineScreenshotType)(options);423 if (options.mask) {424 copy.mask = options.mask.map(locator => ({425 frame: locator._frame._channel,426 selector: locator._selector427 }));428 }429 const result = await this._channel.screenshot(copy);430 const buffer = _buffer.Buffer.from(result.binary, 'base64');431 if (options.path) {432 await (0, _utils.mkdirIfNeeded)(options.path);433 await _fs.default.promises.writeFile(options.path, buffer);434 }435 return buffer;436 }437 async _expectScreenshot(options) {438 var _options$screenshotOp, _options$screenshotOp2;439 const mask = (_options$screenshotOp = options.screenshotOptions) !== null && _options$screenshotOp !== void 0 && _options$screenshotOp.mask ? (_options$screenshotOp2 = options.screenshotOptions) === null || _options$screenshotOp2 === void 0 ? void 0 : _options$screenshotOp2.mask.map(locator => ({440 frame: locator._frame._channel,441 selector: locator._selector442 })) : undefined;443 const locator = options.locator ? {444 frame: options.locator._frame._channel,445 selector: options.locator._selector446 } : undefined;447 const expected = options.expected ? options.expected.toString('base64') : undefined;448 const result = await this._channel.expectScreenshot({ ...options,449 isNot: !!options.isNot,450 expected,451 locator,452 screenshotOptions: { ...options.screenshotOptions,453 mask454 }455 });456 return {457 log: result.log,458 actual: result.actual ? _buffer.Buffer.from(result.actual, 'base64') : undefined,459 previous: result.previous ? _buffer.Buffer.from(result.previous, 'base64') : undefined,460 diff: result.diff ? _buffer.Buffer.from(result.diff, 'base64') : undefined,461 errorMessage: result.errorMessage462 };463 }464 async title() {465 return this._mainFrame.title();466 }467 async bringToFront() {468 await this._channel.bringToFront();469 }470 async close(options = {471 runBeforeUnload: undefined472 }) {473 try {474 if (this._ownedContext) await this._ownedContext.close();else await this._channel.close(options);475 } catch (e) {476 if ((0, _errors.isSafeCloseError)(e)) return;477 throw e;478 }479 }480 isClosed() {481 return this._closed;482 }483 async click(selector, options) {484 return this._mainFrame.click(selector, options);485 }486 async dragAndDrop(source, target, options) {487 return this._mainFrame.dragAndDrop(source, target, options);488 }489 async dblclick(selector, options) {490 return this._mainFrame.dblclick(selector, options);491 }492 async tap(selector, options) {493 return this._mainFrame.tap(selector, options);494 }495 async fill(selector, value, options) {496 return this._mainFrame.fill(selector, value, options);497 }498 locator(selector, options) {499 return this.mainFrame().locator(selector, options);500 }501 frameLocator(selector) {502 return this.mainFrame().frameLocator(selector);503 }504 async focus(selector, options) {505 return this._mainFrame.focus(selector, options);506 }507 async textContent(selector, options) {508 return this._mainFrame.textContent(selector, options);509 }510 async innerText(selector, options) {511 return this._mainFrame.innerText(selector, options);512 }513 async innerHTML(selector, options) {514 return this._mainFrame.innerHTML(selector, options);515 }516 async getAttribute(selector, name, options) {517 return this._mainFrame.getAttribute(selector, name, options);518 }519 async inputValue(selector, options) {520 return this._mainFrame.inputValue(selector, options);521 }522 async isChecked(selector, options) {523 return this._mainFrame.isChecked(selector, options);524 }525 async isDisabled(selector, options) {526 return this._mainFrame.isDisabled(selector, options);527 }528 async isEditable(selector, options) {529 return this._mainFrame.isEditable(selector, options);530 }531 async isEnabled(selector, options) {532 return this._mainFrame.isEnabled(selector, options);533 }534 async isHidden(selector, options) {535 return this._mainFrame.isHidden(selector, options);536 }537 async isVisible(selector, options) {538 return this._mainFrame.isVisible(selector, options);539 }540 async hover(selector, options) {541 return this._mainFrame.hover(selector, options);542 }543 async selectOption(selector, values, options) {544 return this._mainFrame.selectOption(selector, values, options);545 }546 async setInputFiles(selector, files, options) {547 return this._mainFrame.setInputFiles(selector, files, options);548 }549 async type(selector, text, options) {550 return this._mainFrame.type(selector, text, options);551 }552 async press(selector, key, options) {553 return this._mainFrame.press(selector, key, options);554 }555 async check(selector, options) {556 return this._mainFrame.check(selector, options);557 }558 async uncheck(selector, options) {559 return this._mainFrame.uncheck(selector, options);560 }561 async setChecked(selector, checked, options) {562 return this._mainFrame.setChecked(selector, checked, options);563 }564 async waitForTimeout(timeout) {565 return this._mainFrame.waitForTimeout(timeout);566 }567 async waitForFunction(pageFunction, arg, options) {568 return this._mainFrame.waitForFunction(pageFunction, arg, options);569 }570 workers() {571 return [...this._workers];572 }573 on(event, listener) {574 if (event === _events.Events.Page.FileChooser && !this.listenerCount(event)) this._channel.setFileChooserInterceptedNoReply({575 intercepted: true576 });577 super.on(event, listener);578 return this;579 }580 addListener(event, listener) {581 if (event === _events.Events.Page.FileChooser && !this.listenerCount(event)) this._channel.setFileChooserInterceptedNoReply({582 intercepted: true583 });584 super.addListener(event, listener);585 return this;586 }587 off(event, listener) {588 super.off(event, listener);589 if (event === _events.Events.Page.FileChooser && !this.listenerCount(event)) this._channel.setFileChooserInterceptedNoReply({590 intercepted: false591 });592 return this;593 }594 removeListener(event, listener) {595 super.removeListener(event, listener);596 if (event === _events.Events.Page.FileChooser && !this.listenerCount(event)) this._channel.setFileChooserInterceptedNoReply({597 intercepted: false598 });599 return this;600 }601 async pause() {602 if (!require('inspector').url()) await this.context()._channel.pause();603 }604 async pdf(options = {}) {605 const transportOptions = { ...options606 };607 if (transportOptions.margin) transportOptions.margin = { ...transportOptions.margin608 };609 if (typeof options.width === 'number') transportOptions.width = options.width + 'px';610 if (typeof options.height === 'number') transportOptions.height = options.height + 'px';611 for (const margin of ['top', 'right', 'bottom', 'left']) {612 const index = margin;613 if (options.margin && typeof options.margin[index] === 'number') transportOptions.margin[index] = transportOptions.margin[index] + 'px';614 }615 const result = await this._channel.pdf(transportOptions);616 const buffer = _buffer.Buffer.from(result.pdf, 'base64');617 if (options.path) {618 await _fs.default.promises.mkdir(_path.default.dirname(options.path), {619 recursive: true620 });621 await _fs.default.promises.writeFile(options.path, buffer);622 }623 return buffer;624 }625}626exports.Page = Page;627class BindingCall extends _channelOwner.ChannelOwner {628 static from(channel) {629 return channel._object;630 }631 constructor(parent, type, guid, initializer) {632 super(parent, type, guid, initializer);633 }634 async call(func) {635 try {636 const frame = _frame.Frame.from(this._initializer.frame);637 const source = {638 context: frame._page.context(),639 page: frame._page,640 frame641 };642 let result;643 if (this._initializer.handle) result = await func(source, _jsHandle.JSHandle.from(this._initializer.handle));else result = await func(source, ...this._initializer.args.map(_jsHandle.parseResult));644 this._channel.resolve({645 result: (0, _jsHandle.serializeArgument)(result)646 }).catch(() => {});647 } catch (e) {648 this._channel.reject({649 error: (0, _serializers.serializeError)(e)650 }).catch(() => {});651 }652 }653}654exports.BindingCall = BindingCall;655function trimEnd(s) {656 if (s.length > 50) s = s.substring(0, 50) + '\u2026';657 return s;658}659function trimUrl(param) {660 if ((0, _utils.isRegExp)(param)) return `/${trimEnd(param.source)}/${param.flags}`;661 if ((0, _utils.isString)(param)) return `"${trimEnd(param)}"`;...

Full Screen

Full Screen

browserContext.js

Source:browserContext.js Github

copy

Full Screen

1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.BrowserContext = void 0;6exports.prepareBrowserContextParams = prepareBrowserContextParams;7var _page = require("./page");8var _frame = require("./frame");9var network = _interopRequireWildcard(require("./network"));10var _fs = _interopRequireDefault(require("fs"));11var _channelOwner = require("./channelOwner");12var _clientHelper = require("./clientHelper");13var _browser = require("./browser");14var _worker = require("./worker");15var _events = require("./events");16var _timeoutSettings = require("../utils/timeoutSettings");17var _waiter = require("./waiter");18var _utils = require("../utils/utils");19var _errors = require("../utils/errors");20var _cdpSession = require("./cdpSession");21var _tracing = require("./tracing");22var _artifact = require("./artifact");23var _fetch = require("./fetch");24var _clientInstrumentation = require("./clientInstrumentation");25function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }26function _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); }27function _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; }28/**29 * Copyright 2017 Google Inc. All rights reserved.30 * Modifications copyright (c) Microsoft Corporation.31 *32 * Licensed under the Apache License, Version 2.0 (the "License");33 * you may not use this file except in compliance with the License.34 * You may obtain a copy of the License at35 *36 * http://www.apache.org/licenses/LICENSE-2.037 *38 * Unless required by applicable law or agreed to in writing, software39 * distributed under the License is distributed on an "AS IS" BASIS,40 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.41 * See the License for the specific language governing permissions and42 * limitations under the License.43 */44class BrowserContext extends _channelOwner.ChannelOwner {45 static from(context) {46 return context._object;47 }48 static fromNullable(context) {49 return context ? BrowserContext.from(context) : null;50 }51 constructor(parent, type, guid, initializer) {52 var _this$_browser;53 super(parent, type, guid, initializer, (0, _clientInstrumentation.createInstrumentation)());54 this._pages = new Set();55 this._routes = [];56 this._browser = null;57 this._browserType = void 0;58 this._bindings = new Map();59 this._timeoutSettings = new _timeoutSettings.TimeoutSettings();60 this._ownerPage = void 0;61 this._closedPromise = void 0;62 this._options = {};63 this.request = void 0;64 this.tracing = void 0;65 this._backgroundPages = new Set();66 this._serviceWorkers = new Set();67 this._isChromium = void 0;68 if (parent instanceof _browser.Browser) this._browser = parent;69 this._isChromium = ((_this$_browser = this._browser) === null || _this$_browser === void 0 ? void 0 : _this$_browser._name) === 'chromium';70 this.tracing = _tracing.Tracing.from(initializer.tracing);71 this.request = _fetch.APIRequestContext.from(initializer.APIRequestContext);72 this._channel.on('bindingCall', ({73 binding74 }) => this._onBinding(_page.BindingCall.from(binding)));75 this._channel.on('close', () => this._onClose());76 this._channel.on('page', ({77 page78 }) => this._onPage(_page.Page.from(page)));79 this._channel.on('route', ({80 route,81 request82 }) => this._onRoute(network.Route.from(route), network.Request.from(request)));83 this._channel.on('backgroundPage', ({84 page85 }) => {86 const backgroundPage = _page.Page.from(page);87 this._backgroundPages.add(backgroundPage);88 this.emit(_events.Events.BrowserContext.BackgroundPage, backgroundPage);89 });90 this._channel.on('serviceWorker', ({91 worker92 }) => {93 const serviceWorker = _worker.Worker.from(worker);94 serviceWorker._context = this;95 this._serviceWorkers.add(serviceWorker);96 this.emit(_events.Events.BrowserContext.ServiceWorker, serviceWorker);97 });98 this._channel.on('request', ({99 request,100 page101 }) => this._onRequest(network.Request.from(request), _page.Page.fromNullable(page)));102 this._channel.on('requestFailed', ({103 request,104 failureText,105 responseEndTiming,106 page107 }) => this._onRequestFailed(network.Request.from(request), responseEndTiming, failureText, _page.Page.fromNullable(page)));108 this._channel.on('requestFinished', params => this._onRequestFinished(params));109 this._channel.on('response', ({110 response,111 page112 }) => this._onResponse(network.Response.from(response), _page.Page.fromNullable(page)));113 this._closedPromise = new Promise(f => this.once(_events.Events.BrowserContext.Close, f));114 }115 _setBrowserType(browserType) {116 this._browserType = browserType;117 browserType._contexts.add(this);118 }119 _onPage(page) {120 this._pages.add(page);121 this.emit(_events.Events.BrowserContext.Page, page);122 if (page._opener && !page._opener.isClosed()) page._opener.emit(_events.Events.Page.Popup, page);123 }124 _onRequest(request, page) {125 this.emit(_events.Events.BrowserContext.Request, request);126 if (page) page.emit(_events.Events.Page.Request, request);127 }128 _onResponse(response, page) {129 this.emit(_events.Events.BrowserContext.Response, response);130 if (page) page.emit(_events.Events.Page.Response, response);131 }132 _onRequestFailed(request, responseEndTiming, failureText, page) {133 request._failureText = failureText || null;134 if (request._timing) request._timing.responseEnd = responseEndTiming;135 this.emit(_events.Events.BrowserContext.RequestFailed, request);136 if (page) page.emit(_events.Events.Page.RequestFailed, request);137 }138 _onRequestFinished(params) {139 const {140 responseEndTiming141 } = params;142 const request = network.Request.from(params.request);143 const response = network.Response.fromNullable(params.response);144 const page = _page.Page.fromNullable(params.page);145 if (request._timing) request._timing.responseEnd = responseEndTiming;146 this.emit(_events.Events.BrowserContext.RequestFinished, request);147 if (page) page.emit(_events.Events.Page.RequestFinished, request);148 if (response) response._finishedPromise.resolve();149 }150 _onRoute(route, request) {151 for (const routeHandler of this._routes) {152 if (routeHandler.matches(request.url())) {153 try {154 routeHandler.handle(route, request);155 } finally {156 if (!routeHandler.isActive()) {157 this._routes.splice(this._routes.indexOf(routeHandler), 1);158 if (!this._routes.length) this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});159 }160 }161 return;162 }163 } // it can race with BrowserContext.close() which then throws since its closed164 route._internalContinue();165 }166 async _onBinding(bindingCall) {167 const func = this._bindings.get(bindingCall._initializer.name);168 if (!func) return;169 await bindingCall.call(func);170 }171 setDefaultNavigationTimeout(timeout) {172 this._timeoutSettings.setDefaultNavigationTimeout(timeout);173 this._wrapApiCall(async () => {174 this._channel.setDefaultNavigationTimeoutNoReply({175 timeout176 });177 }, true);178 }179 setDefaultTimeout(timeout) {180 this._timeoutSettings.setDefaultTimeout(timeout);181 this._wrapApiCall(async () => {182 this._channel.setDefaultTimeoutNoReply({183 timeout184 });185 }, true);186 }187 browser() {188 return this._browser;189 }190 pages() {191 return [...this._pages];192 }193 async newPage() {194 if (this._ownerPage) throw new Error('Please use browser.newContext()');195 return _page.Page.from((await this._channel.newPage()).page);196 }197 async cookies(urls) {198 if (!urls) urls = [];199 if (urls && typeof urls === 'string') urls = [urls];200 return (await this._channel.cookies({201 urls: urls202 })).cookies;203 }204 async addCookies(cookies) {205 await this._channel.addCookies({206 cookies207 });208 }209 async clearCookies() {210 await this._channel.clearCookies();211 }212 async grantPermissions(permissions, options) {213 await this._channel.grantPermissions({214 permissions,215 ...options216 });217 }218 async clearPermissions() {219 await this._channel.clearPermissions();220 }221 async setGeolocation(geolocation) {222 await this._channel.setGeolocation({223 geolocation: geolocation || undefined224 });225 }226 async setExtraHTTPHeaders(headers) {227 network.validateHeaders(headers);228 await this._channel.setExtraHTTPHeaders({229 headers: (0, _utils.headersObjectToArray)(headers)230 });231 }232 async setOffline(offline) {233 await this._channel.setOffline({234 offline235 });236 }237 async setHTTPCredentials(httpCredentials) {238 await this._channel.setHTTPCredentials({239 httpCredentials: httpCredentials || undefined240 });241 }242 async addInitScript(script, arg) {243 const source = await (0, _clientHelper.evaluationScript)(script, arg);244 await this._channel.addInitScript({245 source246 });247 }248 async exposeBinding(name, callback, options = {}) {249 await this._channel.exposeBinding({250 name,251 needsHandle: options.handle252 });253 this._bindings.set(name, callback);254 }255 async exposeFunction(name, callback) {256 await this._channel.exposeBinding({257 name258 });259 const binding = (source, ...args) => callback(...args);260 this._bindings.set(name, binding);261 }262 async route(url, handler, options = {}) {263 this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times));264 if (this._routes.length === 1) await this._channel.setNetworkInterceptionEnabled({265 enabled: true266 });267 }268 async unroute(url, handler) {269 this._routes = this._routes.filter(route => route.url !== url || handler && route.handler !== handler);270 if (!this._routes.length) await this._disableInterception();271 }272 async _disableInterception() {273 await this._channel.setNetworkInterceptionEnabled({274 enabled: false275 });276 }277 async waitForEvent(event, optionsOrPredicate = {}) {278 return this._wrapApiCall(async () => {279 const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);280 const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;281 const waiter = _waiter.Waiter.createForEvent(this, event);282 waiter.rejectOnTimeout(timeout, `Timeout ${timeout}ms exceeded while waiting for event "${event}"`);283 if (event !== _events.Events.BrowserContext.Close) waiter.rejectOnEvent(this, _events.Events.BrowserContext.Close, new Error('Context closed'));284 const result = await waiter.waitForEvent(this, event, predicate);285 waiter.dispose();286 return result;287 });288 }289 async storageState(options = {}) {290 const state = await this._channel.storageState();291 if (options.path) {292 await (0, _utils.mkdirIfNeeded)(options.path);293 await _fs.default.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');294 }295 return state;296 }297 backgroundPages() {298 return [...this._backgroundPages];299 }300 serviceWorkers() {301 return [...this._serviceWorkers];302 }303 async newCDPSession(page) {304 // channelOwner.ts's validation messages don't handle the pseudo-union type, so we're explicit here305 if (!(page instanceof _page.Page) && !(page instanceof _frame.Frame)) throw new Error('page: expected Page or Frame');306 const result = await this._channel.newCDPSession(page instanceof _page.Page ? {307 page: page._channel308 } : {309 frame: page._channel310 });311 return _cdpSession.CDPSession.from(result.session);312 }313 _onClose() {314 var _this$_browserType, _this$_browserType$_c;315 if (this._browser) this._browser._contexts.delete(this);316 (_this$_browserType = this._browserType) === null || _this$_browserType === void 0 ? void 0 : (_this$_browserType$_c = _this$_browserType._contexts) === null || _this$_browserType$_c === void 0 ? void 0 : _this$_browserType$_c.delete(this);317 this.emit(_events.Events.BrowserContext.Close, this);318 }319 async close() {320 try {321 await this._wrapApiCall(async () => {322 var _this$_browserType2, _this$_browserType2$_;323 await ((_this$_browserType2 = this._browserType) === null || _this$_browserType2 === void 0 ? void 0 : (_this$_browserType2$_ = _this$_browserType2._onWillCloseContext) === null || _this$_browserType2$_ === void 0 ? void 0 : _this$_browserType2$_.call(_this$_browserType2, this));324 if (this._options.recordHar) {325 const har = await this._channel.harExport();326 const artifact = _artifact.Artifact.from(har.artifact);327 await artifact.saveAs(this._options.recordHar.path);328 await artifact.delete();329 }330 }, true);331 await this._channel.close();332 await this._closedPromise;333 } catch (e) {334 if ((0, _errors.isSafeCloseError)(e)) return;335 throw e;336 }337 }338 async _enableRecorder(params) {339 await this._channel.recorderSupplementEnable(params);340 }341}342exports.BrowserContext = BrowserContext;343async function prepareBrowserContextParams(options) {344 if (options.videoSize && !options.videosPath) throw new Error(`"videoSize" option requires "videosPath" to be specified`);345 if (options.extraHTTPHeaders) network.validateHeaders(options.extraHTTPHeaders);346 const contextParams = { ...options,347 viewport: options.viewport === null ? undefined : options.viewport,348 noDefaultViewport: options.viewport === null,349 extraHTTPHeaders: options.extraHTTPHeaders ? (0, _utils.headersObjectToArray)(options.extraHTTPHeaders) : undefined,350 storageState: typeof options.storageState === 'string' ? JSON.parse(await _fs.default.promises.readFile(options.storageState, 'utf8')) : options.storageState351 };352 if (!contextParams.recordVideo && options.videosPath) {353 contextParams.recordVideo = {354 dir: options.videosPath,355 size: options.videoSize356 };357 }358 return contextParams;...

Full Screen

Full Screen

browser.js

Source:browser.js Github

copy

Full Screen

1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.Browser = void 0;6var _browserContext = require("./browserContext");7var _channelOwner = require("./channelOwner");8var _events = require("./events");9var _errors = require("../utils/errors");10var _cdpSession = require("./cdpSession");11/**12 * Copyright (c) Microsoft Corporation.13 *14 * Licensed under the Apache License, Version 2.0 (the "License");15 * you may not use this file except in compliance with the License.16 * You may obtain a copy of the License at17 *18 * http://www.apache.org/licenses/LICENSE-2.019 *20 * Unless required by applicable law or agreed to in writing, software21 * distributed under the License is distributed on an "AS IS" BASIS,22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.23 * See the License for the specific language governing permissions and24 * limitations under the License.25 */26class Browser extends _channelOwner.ChannelOwner {27 static from(browser) {28 return browser._object;29 }30 static fromNullable(browser) {31 return browser ? Browser.from(browser) : null;32 }33 constructor(parent, type, guid, initializer) {34 super(parent, type, guid, initializer);35 this._contexts = new Set();36 this._isConnected = true;37 this._closedPromise = void 0;38 this._shouldCloseConnectionOnClose = false;39 this._browserType = void 0;40 this._name = void 0;41 this._name = initializer.name;42 this._channel.on('close', () => this._didClose());43 this._closedPromise = new Promise(f => this.once(_events.Events.Browser.Disconnected, f));44 }45 _setBrowserType(browserType) {46 this._browserType = browserType;47 for (const context of this._contexts) context._setBrowserType(browserType);48 }49 async newContext(options = {}) {50 return this._wrapApiCall(async channel => {51 var _this$_browserType$_o, _this$_browserType;52 options = { ...this._browserType._defaultContextOptions,53 ...options54 };55 const contextOptions = await (0, _browserContext.prepareBrowserContextParams)(options);56 const context = _browserContext.BrowserContext.from((await channel.newContext(contextOptions)).context);57 context._options = contextOptions;58 this._contexts.add(context);59 context._logger = options.logger || this._logger;60 context._setBrowserType(this._browserType);61 await ((_this$_browserType$_o = (_this$_browserType = this._browserType)._onDidCreateContext) === null || _this$_browserType$_o === void 0 ? void 0 : _this$_browserType$_o.call(_this$_browserType, context));62 return context;63 });64 }65 contexts() {66 return [...this._contexts];67 }68 version() {69 return this._initializer.version;70 }71 async newPage(options = {}) {72 const context = await this.newContext(options);73 const page = await context.newPage();74 page._ownedContext = context;75 context._ownerPage = page;76 return page;77 }78 isConnected() {79 return this._isConnected;80 }81 async newBrowserCDPSession() {82 return this._wrapApiCall(async channel => {83 return _cdpSession.CDPSession.from((await channel.newBrowserCDPSession()).session);84 });85 }86 async startTracing(page, options = {}) {87 return this._wrapApiCall(async channel => {88 await channel.startTracing({ ...options,89 page: page ? page._channel : undefined90 });91 });92 }93 async stopTracing() {94 return this._wrapApiCall(async channel => {95 return Buffer.from((await channel.stopTracing()).binary, 'base64');96 });97 }98 async close() {99 try {100 await this._wrapApiCall(async channel => {101 if (this._shouldCloseConnectionOnClose) this._connection.close(_errors.kBrowserClosedError);else await channel.close();102 await this._closedPromise;103 });104 } catch (e) {105 if ((0, _errors.isSafeCloseError)(e)) return;106 throw e;107 }108 }109 _didClose() {110 this._isConnected = false;111 this.emit(_events.Events.Browser.Disconnected, this);112 }113}...

Full Screen

Full Screen

errors.js

Source:errors.js Github

copy

Full Screen

...32const kBrowserClosedError = 'Browser has been closed';33exports.kBrowserClosedError = kBrowserClosedError;34const kBrowserOrContextClosedError = 'Target page, context or browser has been closed';35exports.kBrowserOrContextClosedError = kBrowserOrContextClosedError;36function isSafeCloseError(error) {37 return error.message.endsWith(kBrowserClosedError) || error.message.endsWith(kBrowserOrContextClosedError);...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const { isSafeCloseError } = require('playwright/lib/internal/errors');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 try {8 await browser.close();9 } catch (error) {10 if (isSafeCloseError(error)) {11 }12 }13})();14### isSafeCloseError(error)15[MIT](LICENSE)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { isSafeCloseError } = require('playwright/lib/utils/utils');2const { chromium } = require('playwright-chromium');3(async () => {4 const browser = await chromium.launch();5 const context = await browser.newContext();6 const page = await context.newPage();7 try {8 await browser.close();9 } catch (e) {10 if (!isSafeCloseError(e)) {11 throw e;12 }13 }14})();15const { isSafeCloseError } = require('playwright/lib/utils/utils');16const { chromium } = require('playwright-core');17(async () => {18 const browser = await chromium.launch();19 const context = await browser.newContext();20 const page = await context.newPage();21 try {22 await browser.close();23 } catch (e) {24 if (!isSafeCloseError(e)) {25 throw e;26 }27 }28})();29const { chromium } = require('playwright');30(async () => {31 const browser = await chromium.launch();32 const context = await browser.newContext();33 const page = await context.newPage();34 try {35 await browser.close();36 } catch (e) {37 if (!e.message.includes('Target closed')) {38 throw e;39 }40 }41})();42[Apache 2.0](LICENSE)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { isSafeCloseError } = require('playwright/lib/utils/error');2const { isSafeCloseError } = require('playwright/lib/utils/error');3const { isSafeCloseError } = require('playwright/lib/utils/error');4const { isSafeCloseError } = require('playwright/lib/utils/error');5const { isSafeCloseError } = require('playwright/lib/utils/error');6const { isSafeCloseError } = require('playwright/lib/utils/error');7const { isSafeCloseError } = require('playwright/lib/utils/error');8const { isSafeCloseError } = require('playwright/lib/utils/error');9const { isSafeCloseError } = require('playwright/lib/utils/error');10const { isSafeCloseError } = require('playwright/lib/utils/error');11const { isSafeCloseError } = require('playwright/lib/utils/error');12const { isSafeCloseError } = require('playwright/lib/utils/error');13const { isSafeCloseError } = require('playwright/lib/utils/error');14const { isSafeCloseError } = require('playwright/lib/utils/error');15const { isSafeCloseError } = require('playwright/lib/utils/error');16const {

Full Screen

Using AI Code Generation

copy

Full Screen

1const { isSafeCloseError } = require('playwright/lib/server/supplements/utils/safeClose');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 browser.close();8 if (isSafeCloseError(browser._closePromise)) {9 console.log('Safe close error');10 }11})();12[Apache 2.0](LICENSE)

Full Screen

Using AI Code Generation

copy

Full Screen

1const { InternalError } = require('playwright/lib/errors');2const { isSafeCloseError } = InternalError;3- [InternalError](#internalerror)4 - [Parameters](#parameters)5 - [isSafeCloseError](#issafecloseerror)6 - [Parameters](#parameters-1)7- **See: [isSafeCloseError](

Full Screen

Using AI Code Generation

copy

Full Screen

1const { InternalError } = require('playwright/lib/utils/stackTrace');2const { isSafeCloseError } = require('playwright/lib/utils/utils');3const error = new Error('test');4const internalError = new InternalError(error);5console.log(internalError.message);6console.log(isSafeCloseError(internalError));

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