How to use buildBasePlaywrightCLICommand method in Playwright Internal

Best JavaScript code snippet using playwright-internal

cli.ts

Source:cli.ts Github

copy

Full Screen

...39import { registry, writeDockerVersion } from '../server';40const packageJSON = require('../../package.json');41program42 .version('Version ' + (process.env.PW_CLI_DISPLAY_VERSION || packageJSON.version))43 .name(buildBasePlaywrightCLICommand(process.env.PW_LANG_NAME));44program45 .command('mark-docker-image [dockerImageNameTemplate]', { hidden: true })46 .description('mark docker image')47 .allowUnknownOption(true)48 .action(function(dockerImageNameTemplate) {49 assert(dockerImageNameTemplate, 'dockerImageNameTemplate is required');50 writeDockerVersion(dockerImageNameTemplate).catch(logErrorAndExit);51 });52commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', [])53 .action(function(url, options) {54 open(options, url, language()).catch(logErrorAndExit);55 })56 .addHelpText('afterAll', `57Examples:58 $ open $ open -b webkit https://example.com`);59commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions',60 [61 ['-o, --output <file name>', 'saves the generated script to a file'],62 ['--target <language>', `language to generate, one of javascript, test, python, python-async, csharp`, language()],63 ]).action(function(url, options) {64 codegen(options, url, options.target, options.output).catch(logErrorAndExit);65}).addHelpText('afterAll', `66Examples:67 $ codegen68 $ codegen --target=python69 $ codegen -b webkit https://example.com`);70program71 .command('debug <app> [args...]', { hidden: true })72 .description('run command in debug mode: disable timeout, open inspector')73 .allowUnknownOption(true)74 .action(function(app, options) {75 spawn(app, options, {76 env: { ...process.env, PWDEBUG: '1' },77 stdio: 'inherit'78 });79 }).addHelpText('afterAll', `80Examples:81 $ debug node test.js82 $ debug npm run test`);83function suggestedBrowsersToInstall() {84 return registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');85}86function checkBrowsersToInstall(args: string[]): Executable[] {87 const faultyArguments: string[] = [];88 const executables: Executable[] = [];89 for (const arg of args) {90 const executable = registry.findExecutable(arg);91 if (!executable || executable.installType === 'none')92 faultyArguments.push(arg);93 else94 executables.push(executable);95 }96 if (faultyArguments.length) {97 console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);98 process.exit(1);99 }100 return executables;101}102program103 .command('install [browser...]')104 .description('ensure browsers necessary for this version of Playwright are installed')105 .option('--with-deps', 'install system dependencies for browsers')106 .option('--force', 'force reinstall of stable browser channels')107 .action(async function(args: string[], options: { withDeps?: boolean, force?: boolean }) {108 if (isLikelyNpxGlobal()) {109 console.error(wrapInASCIIBox([110 `WARNING: It looks like you are running 'npx playwright install' without first`,111 `installing your project's dependencies.`,112 ``,113 `To avoid unexpected behavior, please install your dependencies first, and`,114 `then run Playwright's install command:`,115 ``,116 ` npm install`,117 ` npx playwright install`,118 ``,119 `If your project does not yet depend on Playwright, first install the`,120 `applicable npm package (most commonly @playwright/test), and`,121 `then run Playwright's install command to download the browsers:`,122 ``,123 ` npm install @playwright/test`,124 ` npx playwright install`,125 ``,126 ].join('\n'), 1));127 }128 try {129 if (!args.length) {130 const executables = registry.defaultExecutables();131 if (options.withDeps)132 await registry.installDeps(executables, false);133 await registry.install(executables, false /* forceReinstall */);134 } else {135 const installDockerImage = args.some(arg => arg === 'docker-image');136 args = args.filter(arg => arg !== 'docker-image');137 if (installDockerImage) {138 const imageName = `mcr.microsoft.com/playwright:v${getPlaywrightVersion()}-focal`;139 const { code } = await spawnAsync('docker', ['pull', imageName], { stdio: 'inherit' });140 if (code !== 0) {141 console.log('Failed to pull docker image');142 process.exit(1);143 }144 }145 const executables = checkBrowsersToInstall(args);146 if (options.withDeps)147 await registry.installDeps(executables, false);148 await registry.install(executables, !!options.force /* forceReinstall */);149 }150 } catch (e) {151 console.log(`Failed to install browsers\n${e}`);152 process.exit(1);153 }154 }).addHelpText('afterAll', `155Examples:156 - $ install157 Install default browsers.158 - $ install chrome firefox159 Install custom browsers, supports ${suggestedBrowsersToInstall()}.`);160program161 .command('install-deps [browser...]')162 .description('install dependencies necessary to run browsers (will ask for sudo permissions)')163 .option('--dry-run', 'Do not execute installation commands, only print them')164 .action(async function(args: string[], options: { dryRun?: boolean }) {165 try {166 if (!args.length)167 await registry.installDeps(registry.defaultExecutables(), !!options.dryRun);168 else169 await registry.installDeps(checkBrowsersToInstall(args), !!options.dryRun);170 } catch (e) {171 console.log(`Failed to install browser dependencies\n${e}`);172 process.exit(1);173 }174 }).addHelpText('afterAll', `175Examples:176 - $ install-deps177 Install dependencies for default browsers.178 - $ install-deps chrome firefox179 Install dependencies for specific browsers, supports ${suggestedBrowsersToInstall()}.`);180const browsers = [181 { alias: 'cr', name: 'Chromium', type: 'chromium' },182 { alias: 'ff', name: 'Firefox', type: 'firefox' },183 { alias: 'wk', name: 'WebKit', type: 'webkit' },184];185for (const { alias, name, type } of browsers) {186 commandWithOpenOptions(`${alias} [url]`, `open page in ${name}`, [])187 .action(function(url, options) {188 open({ ...options, browser: type }, url, options.target).catch(logErrorAndExit);189 }).addHelpText('afterAll', `190Examples:191 $ ${alias} https://example.com`);192}193commandWithOpenOptions('screenshot <url> <filename>', 'capture a page screenshot',194 [195 ['--wait-for-selector <selector>', 'wait for selector before taking a screenshot'],196 ['--wait-for-timeout <timeout>', 'wait for timeout in milliseconds before taking a screenshot'],197 ['--full-page', 'whether to take a full page screenshot (entire scrollable area)'],198 ]).action(function(url, filename, command) {199 screenshot(command, command, url, filename).catch(logErrorAndExit);200}).addHelpText('afterAll', `201Examples:202 $ screenshot -b webkit https://example.com example.png`);203commandWithOpenOptions('pdf <url> <filename>', 'save page as pdf',204 [205 ['--wait-for-selector <selector>', 'wait for given selector before saving as pdf'],206 ['--wait-for-timeout <timeout>', 'wait for given timeout in milliseconds before saving as pdf'],207 ]).action(function(url, filename, options) {208 pdf(options, options, url, filename).catch(logErrorAndExit);209}).addHelpText('afterAll', `210Examples:211 $ pdf https://example.com example.pdf`);212program213 .command('experimental-grid-server', { hidden: true })214 .option('--port <port>', 'grid port; defaults to 3333')215 .option('--address <address>', 'address of the server')216 .option('--agent-factory <factory>', 'path to grid agent factory or npm package')217 .option('--auth-token <authToken>', 'optional authentication token')218 .action(function(options) {219 launchGridServer(options.agentFactory, options.port || 3333, options.address, options.authToken);220 });221program222 .command('experimental-grid-agent', { hidden: true })223 .requiredOption('--agent-id <agentId>', 'agent ID')224 .requiredOption('--grid-url <gridURL>', 'grid URL')225 .option('--run-id <github run_id>', 'Workflow run_id')226 .action(function(options) {227 launchGridAgent(options.agentId, options.gridUrl, options.runId);228 });229program230 .command('run-driver', { hidden: true })231 .action(function(options) {232 runDriver();233 });234program235 .command('run-server', { hidden: true })236 .option('--port <port>', 'Server port')237 .option('--path <path>', 'Endpoint Path', '/')238 .option('--max-clients <maxClients>', 'Maximum clients')239 .option('--no-socks-proxy', 'Disable Socks Proxy')240 .action(function(options) {241 runServer(options.port ? +options.port : undefined, options.path, options.maxClients ? +options.maxClients : Infinity, options.socksProxy).catch(logErrorAndExit);242 });243program244 .command('print-api-json', { hidden: true })245 .action(function(options) {246 printApiJson();247 });248program249 .command('launch-server', { hidden: true })250 .requiredOption('--browser <browserName>', 'Browser name, one of "chromium", "firefox" or "webkit"')251 .option('--config <path-to-config-file>', 'JSON file with launchServer options')252 .action(function(options) {253 launchBrowserServer(options.browser, options.config);254 });255program256 .command('show-trace [trace...]')257 .option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium')258 .description('Show trace viewer')259 .action(function(traces, options) {260 if (options.browser === 'cr')261 options.browser = 'chromium';262 if (options.browser === 'ff')263 options.browser = 'firefox';264 if (options.browser === 'wk')265 options.browser = 'webkit';266 showTraceViewer(traces, options.browser, false, 9322).catch(logErrorAndExit);267 }).addHelpText('afterAll', `268Examples:269 $ show-trace https://example.com/trace.zip`);270if (!process.env.PW_LANG_NAME) {271 let playwrightTestPackagePath = null;272 try {273 playwrightTestPackagePath = require.resolve('@playwright/test/lib/cli', {274 paths: [__dirname, process.cwd()]275 });276 } catch {}277 if (playwrightTestPackagePath) {278 require(playwrightTestPackagePath).addTestCommand(program);279 require(playwrightTestPackagePath).addShowReportCommand(program);280 require(playwrightTestPackagePath).addListFilesCommand(program);281 } else {282 {283 const command = program.command('test').allowUnknownOption(true);284 command.description('Run tests with Playwright Test. Available in @playwright/test package.');285 command.action(async () => {286 console.error('Please install @playwright/test package to use Playwright Test.');287 console.error(' npm install -D @playwright/test');288 process.exit(1);289 });290 }291 {292 const command = program.command('show-report').allowUnknownOption(true);293 command.description('Show Playwright Test HTML report. Available in @playwright/test package.');294 command.action(async () => {295 console.error('Please install @playwright/test package to use Playwright Test.');296 console.error(' npm install -D @playwright/test');297 process.exit(1);298 });299 }300 }301}302program.parse(process.argv);303type Options = {304 browser: string;305 channel?: string;306 colorScheme?: string;307 device?: string;308 geolocation?: string;309 ignoreHttpsErrors?: boolean;310 lang?: string;311 loadStorage?: string;312 proxyServer?: string;313 proxyBypass?: string;314 saveStorage?: string;315 saveTrace?: string;316 timeout: string;317 timezone?: string;318 viewportSize?: string;319 userAgent?: string;320};321type CaptureOptions = {322 waitForSelector?: string;323 waitForTimeout?: string;324 fullPage: boolean;325};326async function launchContext(options: Options, headless: boolean, executablePath?: string): Promise<{ browser: Browser, browserName: string, launchOptions: LaunchOptions, contextOptions: BrowserContextOptions, context: BrowserContext }> {327 validateOptions(options);328 const browserType = lookupBrowserType(options);329 const launchOptions: LaunchOptions = { headless, executablePath };330 if (options.channel)331 launchOptions.channel = options.channel as any;332 const contextOptions: BrowserContextOptions =333 // Copy the device descriptor since we have to compare and modify the options.334 options.device ? { ...playwright.devices[options.device] } : {};335 // In headful mode, use host device scale factor for things to look nice.336 // In headless, keep things the way it works in Playwright by default.337 // Assume high-dpi on MacOS. TODO: this is not perfect.338 if (!headless)339 contextOptions.deviceScaleFactor = os.platform() === 'darwin' ? 2 : 1;340 // Work around the WebKit GTK scrolling issue.341 if (browserType.name() === 'webkit' && process.platform === 'linux') {342 delete contextOptions.hasTouch;343 delete contextOptions.isMobile;344 }345 if (contextOptions.isMobile && browserType.name() === 'firefox')346 contextOptions.isMobile = undefined;347 // Proxy348 if (options.proxyServer) {349 launchOptions.proxy = {350 server: options.proxyServer351 };352 if (options.proxyBypass)353 launchOptions.proxy.bypass = options.proxyBypass;354 }355 const browser = await browserType.launch(launchOptions);356 // Viewport size357 if (options.viewportSize) {358 try {359 const [ width, height ] = options.viewportSize.split(',').map(n => parseInt(n, 10));360 contextOptions.viewport = { width, height };361 } catch (e) {362 console.log('Invalid window size format: use "width, height", for example --window-size=800,600');363 process.exit(0);364 }365 }366 // Geolocation367 if (options.geolocation) {368 try {369 const [latitude, longitude] = options.geolocation.split(',').map(n => parseFloat(n.trim()));370 contextOptions.geolocation = {371 latitude,372 longitude373 };374 } catch (e) {375 console.log('Invalid geolocation format: user lat, long, for example --geolocation="37.819722,-122.478611"');376 process.exit(0);377 }378 contextOptions.permissions = ['geolocation'];379 }380 // User agent381 if (options.userAgent)382 contextOptions.userAgent = options.userAgent;383 // Lang384 if (options.lang)385 contextOptions.locale = options.lang;386 // Color scheme387 if (options.colorScheme)388 contextOptions.colorScheme = options.colorScheme as 'dark' | 'light';389 // Timezone390 if (options.timezone)391 contextOptions.timezoneId = options.timezone;392 // Storage393 if (options.loadStorage)394 contextOptions.storageState = options.loadStorage;395 if (options.ignoreHttpsErrors)396 contextOptions.ignoreHTTPSErrors = true;397 // Close app when the last window closes.398 const context = await browser.newContext(contextOptions);399 let closingBrowser = false;400 async function closeBrowser() {401 // We can come here multiple times. For example, saving storage creates402 // a temporary page and we call closeBrowser again when that page closes.403 if (closingBrowser)404 return;405 closingBrowser = true;406 if (options.saveTrace)407 await context.tracing.stop({ path: options.saveTrace });408 if (options.saveStorage)409 await context.storageState({ path: options.saveStorage }).catch(e => null);410 await browser.close();411 }412 context.on('page', page => {413 page.on('dialog', () => {}); // Prevent dialogs from being automatically dismissed.414 page.on('close', () => {415 const hasPage = browser.contexts().some(context => context.pages().length > 0);416 if (hasPage)417 return;418 // Avoid the error when the last page is closed because the browser has been closed.419 closeBrowser().catch(e => null);420 });421 });422 if (options.timeout) {423 context.setDefaultTimeout(parseInt(options.timeout, 10));424 context.setDefaultNavigationTimeout(parseInt(options.timeout, 10));425 }426 if (options.saveTrace)427 await context.tracing.start({ screenshots: true, snapshots: true });428 // Omit options that we add automatically for presentation purpose.429 delete launchOptions.headless;430 delete launchOptions.executablePath;431 delete contextOptions.deviceScaleFactor;432 return { browser, browserName: browserType.name(), context, contextOptions, launchOptions };433}434async function openPage(context: BrowserContext, url: string | undefined): Promise<Page> {435 const page = await context.newPage();436 if (url) {437 if (fs.existsSync(url))438 url = 'file://' + path.resolve(url);439 else if (!url.startsWith('http') && !url.startsWith('file://') && !url.startsWith('about:') && !url.startsWith('data:'))440 url = 'http://' + url;441 await page.goto(url);442 }443 return page;444}445async function open(options: Options, url: string | undefined, language: string) {446 const { context, launchOptions, contextOptions } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS, process.env.PWTEST_CLI_EXECUTABLE_PATH);447 await context._enableRecorder({448 language,449 launchOptions,450 contextOptions,451 device: options.device,452 saveStorage: options.saveStorage,453 });454 await openPage(context, url);455 if (process.env.PWTEST_CLI_EXIT)456 await Promise.all(context.pages().map(p => p.close()));457}458async function codegen(options: Options, url: string | undefined, language: string, outputFile?: string) {459 const { context, launchOptions, contextOptions } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS, process.env.PWTEST_CLI_EXECUTABLE_PATH);460 await context._enableRecorder({461 language,462 launchOptions,463 contextOptions,464 device: options.device,465 saveStorage: options.saveStorage,466 startRecording: true,467 outputFile: outputFile ? path.resolve(outputFile) : undefined468 });469 await openPage(context, url);470 if (process.env.PWTEST_CLI_EXIT)471 await Promise.all(context.pages().map(p => p.close()));472}473async function waitForPage(page: Page, captureOptions: CaptureOptions) {474 if (captureOptions.waitForSelector) {475 console.log(`Waiting for selector ${captureOptions.waitForSelector}...`);476 await page.waitForSelector(captureOptions.waitForSelector);477 }478 if (captureOptions.waitForTimeout) {479 console.log(`Waiting for timeout ${captureOptions.waitForTimeout}...`);480 await page.waitForTimeout(parseInt(captureOptions.waitForTimeout, 10));481 }482}483async function screenshot(options: Options, captureOptions: CaptureOptions, url: string, path: string) {484 const { browser, context } = await launchContext(options, true);485 console.log('Navigating to ' + url);486 const page = await openPage(context, url);487 await waitForPage(page, captureOptions);488 console.log('Capturing screenshot into ' + path);489 await page.screenshot({ path, fullPage: !!captureOptions.fullPage });490 await browser.close();491}492async function pdf(options: Options, captureOptions: CaptureOptions, url: string, path: string) {493 if (options.browser !== 'chromium') {494 console.error('PDF creation is only working with Chromium');495 process.exit(1);496 }497 const { browser, context } = await launchContext({ ...options, browser: 'chromium' }, true);498 console.log('Navigating to ' + url);499 const page = await openPage(context, url);500 await waitForPage(page, captureOptions);501 console.log('Saving as pdf into ' + path);502 await page.pdf!({ path });503 await browser.close();504}505function lookupBrowserType(options: Options): BrowserType {506 let name = options.browser;507 if (options.device) {508 const device = playwright.devices[options.device];509 name = device.defaultBrowserType;510 }511 let browserType: any;512 switch (name) {513 case 'chromium': browserType = playwright.chromium; break;514 case 'webkit': browserType = playwright.webkit; break;515 case 'firefox': browserType = playwright.firefox; break;516 case 'cr': browserType = playwright.chromium; break;517 case 'wk': browserType = playwright.webkit; break;518 case 'ff': browserType = playwright.firefox; break;519 }520 if (browserType)521 return browserType;522 program.help();523 process.exit(1);524}525function validateOptions(options: Options) {526 if (options.device && !(options.device in playwright.devices)) {527 console.log(`Device descriptor not found: '${options.device}', available devices are:`);528 for (const name in playwright.devices)529 console.log(` "${name}"`);530 process.exit(0);531 }532 if (options.colorScheme && !['light', 'dark'].includes(options.colorScheme)) {533 console.log('Invalid color scheme, should be one of "light", "dark"');534 process.exit(0);535 }536}537function logErrorAndExit(e: Error) {538 console.error(e);539 process.exit(1);540}541function language(): string {542 return process.env.PW_LANG_NAME || 'test';543}544function commandWithOpenOptions(command: string, description: string, options: any[][]): Command {545 let result = program.command(command).description(description);546 for (const option of options)547 result = result.option(option[0], ...option.slice(1));548 return result549 .option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium')550 .option('--channel <channel>', 'Chromium distribution channel, "chrome", "chrome-beta", "msedge-dev", etc')551 .option('--color-scheme <scheme>', 'emulate preferred color scheme, "light" or "dark"')552 .option('--device <deviceName>', 'emulate device, for example "iPhone 11"')553 .option('--geolocation <coordinates>', 'specify geolocation coordinates, for example "37.819722,-122.478611"')554 .option('--ignore-https-errors', 'ignore https errors')555 .option('--load-storage <filename>', 'load context storage state from the file, previously saved with --save-storage')556 .option('--lang <language>', 'specify language / locale, for example "en-GB"')557 .option('--proxy-server <proxy>', 'specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"')558 .option('--proxy-bypass <bypass>', 'comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"')559 .option('--save-storage <filename>', 'save context storage state at the end, for later use with --load-storage')560 .option('--save-trace <filename>', 'record a trace for the session and save it to a file')561 .option('--timezone <time zone>', 'time zone to emulate, for example "Europe/Rome"')562 .option('--timeout <timeout>', 'timeout for Playwright actions in milliseconds', '10000')563 .option('--user-agent <ua string>', 'specify user agent string')564 .option('--viewport-size <size>', 'specify browser viewport size in pixels, for example "1280, 720"');565}566async function launchGridServer(factoryPathOrPackageName: string, port: number, address: string | undefined, authToken: string | undefined): Promise<void> {567 if (!factoryPathOrPackageName)568 factoryPathOrPackageName = path.join('..', 'grid', 'simpleGridFactory');569 let factory;570 try {571 factory = require(path.resolve(factoryPathOrPackageName));572 } catch (e) {573 factory = require(factoryPathOrPackageName);574 }575 if (factory && typeof factory === 'object' && ('default' in factory))576 factory = factory['default'];577 if (!factory || !factory.launch || typeof factory.launch !== 'function')578 throw new Error('factory does not export `launch` method');579 factory.name = factory.name || factoryPathOrPackageName;580 const gridServer = new GridServer(factory as GridFactory, authToken, address);581 await gridServer.start(port);582 console.log('Grid server is running at ' + gridServer.gridURL());583}584function buildBasePlaywrightCLICommand(cliTargetLang: string | undefined): string {585 switch (cliTargetLang) {586 case 'python':587 return `playwright`;588 case 'java':589 return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="...options.."`;590 case 'csharp':591 return `pwsh bin\\Debug\\netX\\playwright.ps1`;592 default:593 return `npx playwright`;594 }...

Full Screen

Full Screen

cli.js

Source:cli.js Github

copy

Full Screen

...31function _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); }32function _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; }33function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }34const packageJSON = require('../../package.json');35_commander.program.version('Version ' + (process.env.PW_CLI_DISPLAY_VERSION || packageJSON.version)).name(buildBasePlaywrightCLICommand(process.env.PW_LANG_NAME));36commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', []).action(function (url, options) {37 open(options, url, language()).catch(logErrorAndExit);38}).addHelpText('afterAll', `39Examples:40 $ open $ open -b webkit https://example.com`);41commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [['-o, --output <file name>', 'saves the generated script to a file'], ['--target <language>', `language to generate, one of javascript, test, python, python-async, csharp`, language()]]).action(function (url, options) {42 codegen(options, url, options.target, options.output).catch(logErrorAndExit);43}).addHelpText('afterAll', `44Examples:45 $ codegen46 $ codegen --target=python47 $ codegen -b webkit https://example.com`);48_commander.program.command('debug <app> [args...]', {49 hidden: true50}).description('run command in debug mode: disable timeout, open inspector').allowUnknownOption(true).action(function (app, options) {51 (0, _child_process.spawn)(app, options, {52 env: { ...process.env,53 PWDEBUG: '1'54 },55 stdio: 'inherit'56 });57}).addHelpText('afterAll', `58Examples:59 $ debug node test.js60 $ debug npm run test`);61function suggestedBrowsersToInstall() {62 return _registry.registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');63}64function checkBrowsersToInstall(args) {65 const faultyArguments = [];66 const executables = [];67 for (const arg of args) {68 const executable = _registry.registry.findExecutable(arg);69 if (!executable || executable.installType === 'none') faultyArguments.push(arg);else executables.push(executable);70 }71 if (faultyArguments.length) {72 console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);73 process.exit(1);74 }75 return executables;76}77_commander.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').action(async function (args, options) {78 try {79 if (!args.length) {80 const executables = _registry.registry.defaultExecutables();81 if (options.withDeps) await _registry.registry.installDeps(executables, false);82 await _registry.registry.install(executables);83 } else {84 const installDockerImage = args.some(arg => arg === 'docker-image');85 args = args.filter(arg => arg !== 'docker-image');86 if (installDockerImage) {87 const imageName = `mcr.microsoft.com/playwright:v${(0, _utils.getPlaywrightVersion)()}-focal`;88 const {89 code90 } = await (0, _utils.spawnAsync)('docker', ['pull', imageName], {91 stdio: 'inherit'92 });93 if (code !== 0) {94 console.log('Failed to pull docker image');95 process.exit(1);96 }97 }98 const executables = checkBrowsersToInstall(args);99 if (options.withDeps) await _registry.registry.installDeps(executables, false);100 await _registry.registry.install(executables);101 }102 } catch (e) {103 console.log(`Failed to install browsers\n${e}`);104 process.exit(1);105 }106}).addHelpText('afterAll', `107Examples:108 - $ install109 Install default browsers.110 - $ install chrome firefox111 Install custom browsers, supports ${suggestedBrowsersToInstall()}.`);112_commander.program.command('install-deps [browser...]').description('install dependencies necessary to run browsers (will ask for sudo permissions)').option('--dry-run', 'Do not execute installation commands, only print them').action(async function (args, options) {113 try {114 if (!args.length) await _registry.registry.installDeps(_registry.registry.defaultExecutables(), !!options.dryRun);else await _registry.registry.installDeps(checkBrowsersToInstall(args), !!options.dryRun);115 } catch (e) {116 console.log(`Failed to install browser dependencies\n${e}`);117 process.exit(1);118 }119}).addHelpText('afterAll', `120Examples:121 - $ install-deps122 Install dependencies for default browsers.123 - $ install-deps chrome firefox124 Install dependencies for specific browsers, supports ${suggestedBrowsersToInstall()}.`);125const browsers = [{126 alias: 'cr',127 name: 'Chromium',128 type: 'chromium'129}, {130 alias: 'ff',131 name: 'Firefox',132 type: 'firefox'133}, {134 alias: 'wk',135 name: 'WebKit',136 type: 'webkit'137}];138for (const {139 alias,140 name,141 type142} of browsers) {143 commandWithOpenOptions(`${alias} [url]`, `open page in ${name}`, []).action(function (url, options) {144 open({ ...options,145 browser: type146 }, url, options.target).catch(logErrorAndExit);147 }).addHelpText('afterAll', `148Examples:149 $ ${alias} https://example.com`);150}151commandWithOpenOptions('screenshot <url> <filename>', 'capture a page screenshot', [['--wait-for-selector <selector>', 'wait for selector before taking a screenshot'], ['--wait-for-timeout <timeout>', 'wait for timeout in milliseconds before taking a screenshot'], ['--full-page', 'whether to take a full page screenshot (entire scrollable area)']]).action(function (url, filename, command) {152 screenshot(command, command, url, filename).catch(logErrorAndExit);153}).addHelpText('afterAll', `154Examples:155 $ screenshot -b webkit https://example.com example.png`);156commandWithOpenOptions('pdf <url> <filename>', 'save page as pdf', [['--wait-for-selector <selector>', 'wait for given selector before saving as pdf'], ['--wait-for-timeout <timeout>', 'wait for given timeout in milliseconds before saving as pdf']]).action(function (url, filename, options) {157 pdf(options, options, url, filename).catch(logErrorAndExit);158}).addHelpText('afterAll', `159Examples:160 $ pdf https://example.com example.pdf`);161_commander.program.command('experimental-grid-server', {162 hidden: true163}).option('--port <port>', 'grid port; defaults to 3333').option('--agent-factory <factory>', 'path to grid agent factory or npm package').option('--auth-token <authToken>', 'optional authentication token').action(function (options) {164 launchGridServer(options.agentFactory, options.port || 3333, options.authToken);165});166_commander.program.command('experimental-grid-agent', {167 hidden: true168}).requiredOption('--agent-id <agentId>', 'agent ID').requiredOption('--grid-url <gridURL>', 'grid URL').action(function (options) {169 (0, _gridAgent.launchGridAgent)(options.agentId, options.gridUrl);170});171_commander.program.command('run-driver', {172 hidden: true173}).action(function (options) {174 (0, _driver.runDriver)();175});176_commander.program.command('run-server', {177 hidden: true178}).option('--port <port>', 'Server port').option('--path <path>', 'Endpoint Path', '/').option('--max-clients <maxClients>', 'Maximum clients').option('--no-socks-proxy', 'Disable Socks Proxy').action(function (options) {179 (0, _driver.runServer)(options.port ? +options.port : undefined, options.path, options.maxClients ? +options.maxClients : Infinity, options.socksProxy).catch(logErrorAndExit);180});181_commander.program.command('print-api-json', {182 hidden: true183}).action(function (options) {184 (0, _driver.printApiJson)();185});186_commander.program.command('launch-server', {187 hidden: true188}).requiredOption('--browser <browserName>', 'Browser name, one of "chromium", "firefox" or "webkit"').option('--config <path-to-config-file>', 'JSON file with launchServer options').action(function (options) {189 (0, _driver.launchBrowserServer)(options.browser, options.config);190});191_commander.program.command('show-trace [trace...]').option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium').description('Show trace viewer').action(function (traces, options) {192 if (options.browser === 'cr') options.browser = 'chromium';193 if (options.browser === 'ff') options.browser = 'firefox';194 if (options.browser === 'wk') options.browser = 'webkit';195 (0, _traceViewer.showTraceViewer)(traces, options.browser, false, 9322).catch(logErrorAndExit);196}).addHelpText('afterAll', `197Examples:198 $ show-trace https://example.com/trace.zip`);199if (!process.env.PW_LANG_NAME) {200 let playwrightTestPackagePath = null;201 try {202 playwrightTestPackagePath = require.resolve('@playwright/test/lib/cli', {203 paths: [__dirname, process.cwd()]204 });205 } catch {}206 if (playwrightTestPackagePath) {207 require(playwrightTestPackagePath).addTestCommand(_commander.program);208 require(playwrightTestPackagePath).addShowReportCommand(_commander.program);209 require(playwrightTestPackagePath).addListFilesCommand(_commander.program);210 } else {211 {212 const command = _commander.program.command('test').allowUnknownOption(true);213 command.description('Run tests with Playwright Test. Available in @playwright/test package.');214 command.action(async () => {215 console.error('Please install @playwright/test package to use Playwright Test.');216 console.error(' npm install -D @playwright/test');217 process.exit(1);218 });219 }220 {221 const command = _commander.program.command('show-report').allowUnknownOption(true);222 command.description('Show Playwright Test HTML report. Available in @playwright/test package.');223 command.action(async () => {224 console.error('Please install @playwright/test package to use Playwright Test.');225 console.error(' npm install -D @playwright/test');226 process.exit(1);227 });228 }229 }230}231_commander.program.parse(process.argv);232async function launchContext(options, headless, executablePath) {233 validateOptions(options);234 const browserType = lookupBrowserType(options);235 const launchOptions = {236 headless,237 executablePath238 };239 if (options.channel) launchOptions.channel = options.channel;240 const contextOptions = // Copy the device descriptor since we have to compare and modify the options.241 options.device ? { ...playwright.devices[options.device]242 } : {}; // In headful mode, use host device scale factor for things to look nice.243 // In headless, keep things the way it works in Playwright by default.244 // Assume high-dpi on MacOS. TODO: this is not perfect.245 if (!headless) contextOptions.deviceScaleFactor = _os.default.platform() === 'darwin' ? 2 : 1; // Work around the WebKit GTK scrolling issue.246 if (browserType.name() === 'webkit' && process.platform === 'linux') {247 delete contextOptions.hasTouch;248 delete contextOptions.isMobile;249 }250 if (contextOptions.isMobile && browserType.name() === 'firefox') contextOptions.isMobile = undefined; // Proxy251 if (options.proxyServer) {252 launchOptions.proxy = {253 server: options.proxyServer254 };255 if (options.proxyBypass) launchOptions.proxy.bypass = options.proxyBypass;256 }257 const browser = await browserType.launch(launchOptions); // Viewport size258 if (options.viewportSize) {259 try {260 const [width, height] = options.viewportSize.split(',').map(n => parseInt(n, 10));261 contextOptions.viewport = {262 width,263 height264 };265 } catch (e) {266 console.log('Invalid window size format: use "width, height", for example --window-size=800,600');267 process.exit(0);268 }269 } // Geolocation270 if (options.geolocation) {271 try {272 const [latitude, longitude] = options.geolocation.split(',').map(n => parseFloat(n.trim()));273 contextOptions.geolocation = {274 latitude,275 longitude276 };277 } catch (e) {278 console.log('Invalid geolocation format: user lat, long, for example --geolocation="37.819722,-122.478611"');279 process.exit(0);280 }281 contextOptions.permissions = ['geolocation'];282 } // User agent283 if (options.userAgent) contextOptions.userAgent = options.userAgent; // Lang284 if (options.lang) contextOptions.locale = options.lang; // Color scheme285 if (options.colorScheme) contextOptions.colorScheme = options.colorScheme; // Timezone286 if (options.timezone) contextOptions.timezoneId = options.timezone; // Storage287 if (options.loadStorage) contextOptions.storageState = options.loadStorage;288 if (options.ignoreHttpsErrors) contextOptions.ignoreHTTPSErrors = true; // Close app when the last window closes.289 const context = await browser.newContext(contextOptions);290 let closingBrowser = false;291 async function closeBrowser() {292 // We can come here multiple times. For example, saving storage creates293 // a temporary page and we call closeBrowser again when that page closes.294 if (closingBrowser) return;295 closingBrowser = true;296 if (options.saveTrace) await context.tracing.stop({297 path: options.saveTrace298 });299 if (options.saveStorage) await context.storageState({300 path: options.saveStorage301 }).catch(e => null);302 await browser.close();303 }304 context.on('page', page => {305 page.on('dialog', () => {}); // Prevent dialogs from being automatically dismissed.306 page.on('close', () => {307 const hasPage = browser.contexts().some(context => context.pages().length > 0);308 if (hasPage) return; // Avoid the error when the last page is closed because the browser has been closed.309 closeBrowser().catch(e => null);310 });311 });312 if (options.timeout) {313 context.setDefaultTimeout(parseInt(options.timeout, 10));314 context.setDefaultNavigationTimeout(parseInt(options.timeout, 10));315 }316 if (options.saveTrace) await context.tracing.start({317 screenshots: true,318 snapshots: true319 }); // Omit options that we add automatically for presentation purpose.320 delete launchOptions.headless;321 delete launchOptions.executablePath;322 delete contextOptions.deviceScaleFactor;323 return {324 browser,325 browserName: browserType.name(),326 context,327 contextOptions,328 launchOptions329 };330}331async function openPage(context, url) {332 const page = await context.newPage();333 if (url) {334 if (_fs.default.existsSync(url)) url = 'file://' + _path.default.resolve(url);else if (!url.startsWith('http') && !url.startsWith('file://') && !url.startsWith('about:') && !url.startsWith('data:')) url = 'http://' + url;335 await page.goto(url);336 }337 return page;338}339async function open(options, url, language) {340 const {341 context,342 launchOptions,343 contextOptions344 } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS, process.env.PWTEST_CLI_EXECUTABLE_PATH);345 await context._enableRecorder({346 language,347 launchOptions,348 contextOptions,349 device: options.device,350 saveStorage: options.saveStorage351 });352 await openPage(context, url);353 if (process.env.PWTEST_CLI_EXIT) await Promise.all(context.pages().map(p => p.close()));354}355async function codegen(options, url, language, outputFile) {356 const {357 context,358 launchOptions,359 contextOptions360 } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS, process.env.PWTEST_CLI_EXECUTABLE_PATH);361 await context._enableRecorder({362 language,363 launchOptions,364 contextOptions,365 device: options.device,366 saveStorage: options.saveStorage,367 startRecording: true,368 outputFile: outputFile ? _path.default.resolve(outputFile) : undefined369 });370 await openPage(context, url);371 if (process.env.PWTEST_CLI_EXIT) await Promise.all(context.pages().map(p => p.close()));372}373async function waitForPage(page, captureOptions) {374 if (captureOptions.waitForSelector) {375 console.log(`Waiting for selector ${captureOptions.waitForSelector}...`);376 await page.waitForSelector(captureOptions.waitForSelector);377 }378 if (captureOptions.waitForTimeout) {379 console.log(`Waiting for timeout ${captureOptions.waitForTimeout}...`);380 await page.waitForTimeout(parseInt(captureOptions.waitForTimeout, 10));381 }382}383async function screenshot(options, captureOptions, url, path) {384 const {385 browser,386 context387 } = await launchContext(options, true);388 console.log('Navigating to ' + url);389 const page = await openPage(context, url);390 await waitForPage(page, captureOptions);391 console.log('Capturing screenshot into ' + path);392 await page.screenshot({393 path,394 fullPage: !!captureOptions.fullPage395 });396 await browser.close();397}398async function pdf(options, captureOptions, url, path) {399 if (options.browser !== 'chromium') {400 console.error('PDF creation is only working with Chromium');401 process.exit(1);402 }403 const {404 browser,405 context406 } = await launchContext({ ...options,407 browser: 'chromium'408 }, true);409 console.log('Navigating to ' + url);410 const page = await openPage(context, url);411 await waitForPage(page, captureOptions);412 console.log('Saving as pdf into ' + path);413 await page.pdf({414 path415 });416 await browser.close();417}418function lookupBrowserType(options) {419 let name = options.browser;420 if (options.device) {421 const device = playwright.devices[options.device];422 name = device.defaultBrowserType;423 }424 let browserType;425 switch (name) {426 case 'chromium':427 browserType = playwright.chromium;428 break;429 case 'webkit':430 browserType = playwright.webkit;431 break;432 case 'firefox':433 browserType = playwright.firefox;434 break;435 case 'cr':436 browserType = playwright.chromium;437 break;438 case 'wk':439 browserType = playwright.webkit;440 break;441 case 'ff':442 browserType = playwright.firefox;443 break;444 }445 if (browserType) return browserType;446 _commander.program.help();447}448function validateOptions(options) {449 if (options.device && !(options.device in playwright.devices)) {450 console.log(`Device descriptor not found: '${options.device}', available devices are:`);451 for (const name in playwright.devices) console.log(` "${name}"`);452 process.exit(0);453 }454 if (options.colorScheme && !['light', 'dark'].includes(options.colorScheme)) {455 console.log('Invalid color scheme, should be one of "light", "dark"');456 process.exit(0);457 }458}459function logErrorAndExit(e) {460 console.error(e);461 process.exit(1);462}463function language() {464 return process.env.PW_LANG_NAME || 'test';465}466function commandWithOpenOptions(command, description, options) {467 let result = _commander.program.command(command).description(description);468 for (const option of options) result = result.option(option[0], ...option.slice(1));469 return result.option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium').option('--channel <channel>', 'Chromium distribution channel, "chrome", "chrome-beta", "msedge-dev", etc').option('--color-scheme <scheme>', 'emulate preferred color scheme, "light" or "dark"').option('--device <deviceName>', 'emulate device, for example "iPhone 11"').option('--geolocation <coordinates>', 'specify geolocation coordinates, for example "37.819722,-122.478611"').option('--ignore-https-errors', 'ignore https errors').option('--load-storage <filename>', 'load context storage state from the file, previously saved with --save-storage').option('--lang <language>', 'specify language / locale, for example "en-GB"').option('--proxy-server <proxy>', 'specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"').option('--proxy-bypass <bypass>', 'comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"').option('--save-storage <filename>', 'save context storage state at the end, for later use with --load-storage').option('--save-trace <filename>', 'record a trace for the session and save it to a file').option('--timezone <time zone>', 'time zone to emulate, for example "Europe/Rome"').option('--timeout <timeout>', 'timeout for Playwright actions in milliseconds', '10000').option('--user-agent <ua string>', 'specify user agent string').option('--viewport-size <size>', 'specify browser viewport size in pixels, for example "1280, 720"');470}471async function launchGridServer(factoryPathOrPackageName, port, authToken) {472 if (!factoryPathOrPackageName) factoryPathOrPackageName = _path.default.join('..', 'grid', 'simpleGridFactory');473 let factory;474 try {475 factory = require(_path.default.resolve(factoryPathOrPackageName));476 } catch (e) {477 factory = require(factoryPathOrPackageName);478 }479 if (factory && typeof factory === 'object' && 'default' in factory) factory = factory['default'];480 if (!factory || !factory.launch || typeof factory.launch !== 'function') throw new Error('factory does not export `launch` method');481 factory.name = factory.name || factoryPathOrPackageName;482 const gridServer = new _gridServer.GridServer(factory, authToken);483 await gridServer.start(port);484 console.log('Grid server is running at ' + gridServer.urlPrefix());485}486function buildBasePlaywrightCLICommand(cliTargetLang) {487 switch (cliTargetLang) {488 case 'python':489 return `playwright`;490 case 'java':491 return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="...options.."`;492 case 'csharp':493 return `pwsh bin\\Debug\\netX\\playwright.ps1`;494 default:495 return `npx playwright`;496 }...

Full Screen

Full Screen

innerCli.js

Source:innerCli.js Github

copy

Full Screen

...30 * limitations under the License.31 */32/* eslint-disable no-console */33const packageJSON = require('../../package.json');34_commander.program.version('Version ' + (process.env.PW_CLI_DISPLAY_VERSION || packageJSON.version)).name(buildBasePlaywrightCLICommand(process.env.PW_CLI_TARGET_LANG));35commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', []).action(function (url, options) {36 open(options, url, language()).catch(logErrorAndExit);37}).addHelpText('afterAll', `38Examples:39 $ open $ open -b webkit https://example.com`);40commandWithOpenOptions('codegen [url]', 'open page and generate code for user actions', [['-o, --output <file name>', 'saves the generated script to a file'], ['--target <language>', `language to generate, one of javascript, test, python, python-async, csharp`, language()]]).action(function (url, options) {41 codegen(options, url, options.target, options.output).catch(logErrorAndExit);42}).addHelpText('afterAll', `43Examples:44 $ codegen45 $ codegen --target=python46 $ codegen -b webkit https://example.com`);47_commander.program.command('debug <app> [args...]', {48 hidden: true49}).description('run command in debug mode: disable timeout, open inspector').allowUnknownOption(true).action(function (app, options) {50 (0, _child_process.spawn)(app, options, {51 env: { ...process.env,52 PWDEBUG: '1'53 },54 stdio: 'inherit'55 });56}).addHelpText('afterAll', `57Examples:58 $ debug node test.js59 $ debug npm run test`);60function suggestedBrowsersToInstall() {61 return _registry.registry.executables().filter(e => e.installType !== 'none' && e.type !== 'tool').map(e => e.name).join(', ');62}63function checkBrowsersToInstall(args) {64 const faultyArguments = [];65 const executables = [];66 for (const arg of args) {67 const executable = _registry.registry.findExecutable(arg);68 if (!executable || executable.installType === 'none') faultyArguments.push(arg);else executables.push(executable);69 }70 if (faultyArguments.length) {71 console.log(`Invalid installation targets: ${faultyArguments.map(name => `'${name}'`).join(', ')}. Expecting one of: ${suggestedBrowsersToInstall()}`);72 process.exit(1);73 }74 return executables;75}76_commander.program.command('install [browser...]').description('ensure browsers necessary for this version of Playwright are installed').option('--with-deps', 'install system dependencies for browsers').action(async function (args, options) {77 try {78 if (!args.length) {79 const executables = _registry.registry.defaultExecutables();80 if (options.withDeps) await _registry.registry.installDeps(executables, false);81 await _registry.registry.install(executables);82 } else {83 const installDockerImage = args.some(arg => arg === 'docker-image');84 args = args.filter(arg => arg !== 'docker-image');85 if (installDockerImage) {86 const imageName = `mcr.microsoft.com/playwright:v${(0, _utils.getPlaywrightVersion)()}-focal`;87 const {88 code89 } = await (0, _utils.spawnAsync)('docker', ['pull', imageName], {90 stdio: 'inherit'91 });92 if (code !== 0) {93 console.log('Failed to pull docker image');94 process.exit(1);95 }96 }97 const executables = checkBrowsersToInstall(args);98 if (options.withDeps) await _registry.registry.installDeps(executables, false);99 await _registry.registry.install(executables);100 }101 } catch (e) {102 console.log(`Failed to install browsers\n${e}`);103 process.exit(1);104 }105}).addHelpText('afterAll', `106Examples:107 - $ install108 Install default browsers.109 - $ install chrome firefox110 Install custom browsers, supports ${suggestedBrowsersToInstall()}.`);111_commander.program.command('install-deps [browser...]').description('install dependencies necessary to run browsers (will ask for sudo permissions)').option('--dry-run', 'Do not execute installation commands, only print them').action(async function (args, options) {112 try {113 if (!args.length) await _registry.registry.installDeps(_registry.registry.defaultExecutables(), !!options.dryRun);else await _registry.registry.installDeps(checkBrowsersToInstall(args), !!options.dryRun);114 } catch (e) {115 console.log(`Failed to install browser dependencies\n${e}`);116 process.exit(1);117 }118}).addHelpText('afterAll', `119Examples:120 - $ install-deps121 Install dependencies for default browsers.122 - $ install-deps chrome firefox123 Install dependencies for specific browsers, supports ${suggestedBrowsersToInstall()}.`);124const browsers = [{125 alias: 'cr',126 name: 'Chromium',127 type: 'chromium'128}, {129 alias: 'ff',130 name: 'Firefox',131 type: 'firefox'132}, {133 alias: 'wk',134 name: 'WebKit',135 type: 'webkit'136}];137for (const {138 alias,139 name,140 type141} of browsers) {142 commandWithOpenOptions(`${alias} [url]`, `open page in ${name}`, []).action(function (url, options) {143 open({ ...options,144 browser: type145 }, url, options.target).catch(logErrorAndExit);146 }).addHelpText('afterAll', `147Examples:148 $ ${alias} https://example.com`);149}150commandWithOpenOptions('screenshot <url> <filename>', 'capture a page screenshot', [['--wait-for-selector <selector>', 'wait for selector before taking a screenshot'], ['--wait-for-timeout <timeout>', 'wait for timeout in milliseconds before taking a screenshot'], ['--full-page', 'whether to take a full page screenshot (entire scrollable area)']]).action(function (url, filename, command) {151 screenshot(command, command, url, filename).catch(logErrorAndExit);152}).addHelpText('afterAll', `153Examples:154 $ screenshot -b webkit https://example.com example.png`);155commandWithOpenOptions('pdf <url> <filename>', 'save page as pdf', [['--wait-for-selector <selector>', 'wait for given selector before saving as pdf'], ['--wait-for-timeout <timeout>', 'wait for given timeout in milliseconds before saving as pdf']]).action(function (url, filename, options) {156 pdf(options, options, url, filename).catch(logErrorAndExit);157}).addHelpText('afterAll', `158Examples:159 $ pdf https://example.com example.pdf`);160_commander.program.command('experimental-grid-server', {161 hidden: true162}).option('--port <port>', 'grid port; defaults to 3333').option('--agent-factory <factory>', 'path to grid agent factory or npm package').option('--auth-token <authToken>', 'optional authentication token').action(function (options) {163 launchGridServer(options.agentFactory, options.port || 3333, options.authToken);164});165_commander.program.command('experimental-grid-agent', {166 hidden: true167}).requiredOption('--agent-id <agentId>', 'agent ID').requiredOption('--grid-url <gridURL>', 'grid URL').action(function (options) {168 (0, _gridAgent.launchGridAgent)(options.agentId, options.gridUrl);169});170_commander.program.command('show-trace [trace]').option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium').description('Show trace viewer').action(function (trace, options) {171 if (options.browser === 'cr') options.browser = 'chromium';172 if (options.browser === 'ff') options.browser = 'firefox';173 if (options.browser === 'wk') options.browser = 'webkit';174 (0, _traceViewer.showTraceViewer)(trace, options.browser, false, 9322).catch(logErrorAndExit);175}).addHelpText('afterAll', `176Examples:177 $ show-trace https://example.com/trace.zip`);178if (!process.env.PW_CLI_TARGET_LANG) {179 let playwrightTestPackagePath = null;180 try {181 playwrightTestPackagePath = require.resolve('@playwright/test/lib/cli', {182 paths: [__dirname, process.cwd()]183 });184 } catch {}185 if (playwrightTestPackagePath) {186 require(playwrightTestPackagePath).addTestCommand(_commander.program);187 require(playwrightTestPackagePath).addShowReportCommand(_commander.program);188 } else {189 {190 const command = _commander.program.command('test').allowUnknownOption(true);191 command.description('Run tests with Playwright Test. Available in @playwright/test package.');192 command.action(async () => {193 console.error('Please install @playwright/test package to use Playwright Test.');194 console.error(' npm install -D @playwright/test');195 process.exit(1);196 });197 }198 {199 const command = _commander.program.command('show-report').allowUnknownOption(true);200 command.description('Show Playwright Test HTML report. Available in @playwright/test package.');201 command.action(async () => {202 console.error('Please install @playwright/test package to use Playwright Test.');203 console.error(' npm install -D @playwright/test');204 process.exit(1);205 });206 }207 }208}209if (process.argv[2] === 'run-driver') (0, _driver.runDriver)();else if (process.argv[2] === 'run-server') (0, _driver.runServer)(process.argv[3] ? +process.argv[3] : undefined).catch(logErrorAndExit);else if (process.argv[2] === 'print-api-json') (0, _driver.printApiJson)();else if (process.argv[2] === 'launch-server') (0, _driver.launchBrowserServer)(process.argv[3], process.argv[4]).catch(logErrorAndExit);else _commander.program.parse(process.argv);210async function launchContext(options, headless, executablePath) {211 validateOptions(options);212 const browserType = lookupBrowserType(options);213 const launchOptions = {214 headless,215 executablePath216 };217 if (options.channel) launchOptions.channel = options.channel;218 const contextOptions = // Copy the device descriptor since we have to compare and modify the options.219 options.device ? { ...playwright.devices[options.device]220 } : {}; // In headful mode, use host device scale factor for things to look nice.221 // In headless, keep things the way it works in Playwright by default.222 // Assume high-dpi on MacOS. TODO: this is not perfect.223 if (!headless) contextOptions.deviceScaleFactor = _os.default.platform() === 'darwin' ? 2 : 1; // Work around the WebKit GTK scrolling issue.224 if (browserType.name() === 'webkit' && process.platform === 'linux') {225 delete contextOptions.hasTouch;226 delete contextOptions.isMobile;227 }228 if (contextOptions.isMobile && browserType.name() === 'firefox') contextOptions.isMobile = undefined; // Proxy229 if (options.proxyServer) {230 launchOptions.proxy = {231 server: options.proxyServer232 };233 if (options.proxyBypass) launchOptions.proxy.bypass = options.proxyBypass;234 }235 const browser = await browserType.launch(launchOptions); // Viewport size236 if (options.viewportSize) {237 try {238 const [width, height] = options.viewportSize.split(',').map(n => parseInt(n, 10));239 contextOptions.viewport = {240 width,241 height242 };243 } catch (e) {244 console.log('Invalid window size format: use "width, height", for example --window-size=800,600');245 process.exit(0);246 }247 } // Geolocation248 if (options.geolocation) {249 try {250 const [latitude, longitude] = options.geolocation.split(',').map(n => parseFloat(n.trim()));251 contextOptions.geolocation = {252 latitude,253 longitude254 };255 } catch (e) {256 console.log('Invalid geolocation format: user lat, long, for example --geolocation="37.819722,-122.478611"');257 process.exit(0);258 }259 contextOptions.permissions = ['geolocation'];260 } // User agent261 if (options.userAgent) contextOptions.userAgent = options.userAgent; // Lang262 if (options.lang) contextOptions.locale = options.lang; // Color scheme263 if (options.colorScheme) contextOptions.colorScheme = options.colorScheme; // Timezone264 if (options.timezone) contextOptions.timezoneId = options.timezone; // Storage265 if (options.loadStorage) contextOptions.storageState = options.loadStorage;266 if (options.ignoreHttpsErrors) contextOptions.ignoreHTTPSErrors = true; // Close app when the last window closes.267 const context = await browser.newContext(contextOptions);268 let closingBrowser = false;269 async function closeBrowser() {270 // We can come here multiple times. For example, saving storage creates271 // a temporary page and we call closeBrowser again when that page closes.272 if (closingBrowser) return;273 closingBrowser = true;274 if (options.saveTrace) await context.tracing.stop({275 path: options.saveTrace276 });277 if (options.saveStorage) await context.storageState({278 path: options.saveStorage279 }).catch(e => null);280 await browser.close();281 }282 context.on('page', page => {283 page.on('dialog', () => {}); // Prevent dialogs from being automatically dismissed.284 page.on('close', () => {285 const hasPage = browser.contexts().some(context => context.pages().length > 0);286 if (hasPage) return; // Avoid the error when the last page is closed because the browser has been closed.287 closeBrowser().catch(e => null);288 });289 });290 if (options.timeout) {291 context.setDefaultTimeout(parseInt(options.timeout, 10));292 context.setDefaultNavigationTimeout(parseInt(options.timeout, 10));293 }294 if (options.saveTrace) await context.tracing.start({295 screenshots: true,296 snapshots: true297 }); // Omit options that we add automatically for presentation purpose.298 delete launchOptions.headless;299 delete launchOptions.executablePath;300 delete contextOptions.deviceScaleFactor;301 return {302 browser,303 browserName: browserType.name(),304 context,305 contextOptions,306 launchOptions307 };308}309async function openPage(context, url) {310 const page = await context.newPage();311 if (url) {312 if (_fs.default.existsSync(url)) url = 'file://' + _path.default.resolve(url);else if (!url.startsWith('http') && !url.startsWith('file://') && !url.startsWith('about:') && !url.startsWith('data:')) url = 'http://' + url;313 await page.goto(url);314 }315 return page;316}317async function open(options, url, language) {318 const {319 context,320 launchOptions,321 contextOptions322 } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS, process.env.PWTEST_CLI_EXECUTABLE_PATH);323 await context._enableRecorder({324 language,325 launchOptions,326 contextOptions,327 device: options.device,328 saveStorage: options.saveStorage329 });330 await openPage(context, url);331 if (process.env.PWTEST_CLI_EXIT) await Promise.all(context.pages().map(p => p.close()));332}333async function codegen(options, url, language, outputFile) {334 const {335 context,336 launchOptions,337 contextOptions338 } = await launchContext(options, !!process.env.PWTEST_CLI_HEADLESS, process.env.PWTEST_CLI_EXECUTABLE_PATH);339 await context._enableRecorder({340 language,341 launchOptions,342 contextOptions,343 device: options.device,344 saveStorage: options.saveStorage,345 startRecording: true,346 outputFile: outputFile ? _path.default.resolve(outputFile) : undefined347 });348 await openPage(context, url);349 if (process.env.PWTEST_CLI_EXIT) await Promise.all(context.pages().map(p => p.close()));350}351async function waitForPage(page, captureOptions) {352 if (captureOptions.waitForSelector) {353 console.log(`Waiting for selector ${captureOptions.waitForSelector}...`);354 await page.waitForSelector(captureOptions.waitForSelector);355 }356 if (captureOptions.waitForTimeout) {357 console.log(`Waiting for timeout ${captureOptions.waitForTimeout}...`);358 await page.waitForTimeout(parseInt(captureOptions.waitForTimeout, 10));359 }360}361async function screenshot(options, captureOptions, url, path) {362 const {363 browser,364 context365 } = await launchContext(options, true);366 console.log('Navigating to ' + url);367 const page = await openPage(context, url);368 await waitForPage(page, captureOptions);369 console.log('Capturing screenshot into ' + path);370 await page.screenshot({371 path,372 fullPage: !!captureOptions.fullPage373 });374 await browser.close();375}376async function pdf(options, captureOptions, url, path) {377 if (options.browser !== 'chromium') {378 console.error('PDF creation is only working with Chromium');379 process.exit(1);380 }381 const {382 browser,383 context384 } = await launchContext({ ...options,385 browser: 'chromium'386 }, true);387 console.log('Navigating to ' + url);388 const page = await openPage(context, url);389 await waitForPage(page, captureOptions);390 console.log('Saving as pdf into ' + path);391 await page.pdf({392 path393 });394 await browser.close();395}396function lookupBrowserType(options) {397 let name = options.browser;398 if (options.device) {399 const device = playwright.devices[options.device];400 name = device.defaultBrowserType;401 }402 let browserType;403 switch (name) {404 case 'chromium':405 browserType = playwright.chromium;406 break;407 case 'webkit':408 browserType = playwright.webkit;409 break;410 case 'firefox':411 browserType = playwright.firefox;412 break;413 case 'cr':414 browserType = playwright.chromium;415 break;416 case 'wk':417 browserType = playwright.webkit;418 break;419 case 'ff':420 browserType = playwright.firefox;421 break;422 }423 if (browserType) return browserType;424 _commander.program.help();425}426function validateOptions(options) {427 if (options.device && !(options.device in playwright.devices)) {428 console.log(`Device descriptor not found: '${options.device}', available devices are:`);429 for (const name in playwright.devices) console.log(` "${name}"`);430 process.exit(0);431 }432 if (options.colorScheme && !['light', 'dark'].includes(options.colorScheme)) {433 console.log('Invalid color scheme, should be one of "light", "dark"');434 process.exit(0);435 }436}437function logErrorAndExit(e) {438 console.error(e);439 process.exit(1);440}441function language() {442 return process.env.PW_CLI_TARGET_LANG || 'test';443}444function commandWithOpenOptions(command, description, options) {445 let result = _commander.program.command(command).description(description);446 for (const option of options) result = result.option(option[0], ...option.slice(1));447 return result.option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium').option('--channel <channel>', 'Chromium distribution channel, "chrome", "chrome-beta", "msedge-dev", etc').option('--color-scheme <scheme>', 'emulate preferred color scheme, "light" or "dark"').option('--device <deviceName>', 'emulate device, for example "iPhone 11"').option('--geolocation <coordinates>', 'specify geolocation coordinates, for example "37.819722,-122.478611"').option('--ignore-https-errors', 'ignore https errors').option('--load-storage <filename>', 'load context storage state from the file, previously saved with --save-storage').option('--lang <language>', 'specify language / locale, for example "en-GB"').option('--proxy-server <proxy>', 'specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"').option('--proxy-bypass <bypass>', 'comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"').option('--save-storage <filename>', 'save context storage state at the end, for later use with --load-storage').option('--save-trace <filename>', 'record a trace for the session and save it to a file').option('--timezone <time zone>', 'time zone to emulate, for example "Europe/Rome"').option('--timeout <timeout>', 'timeout for Playwright actions in milliseconds', '10000').option('--user-agent <ua string>', 'specify user agent string').option('--viewport-size <size>', 'specify browser viewport size in pixels, for example "1280, 720"');448}449async function launchGridServer(factoryPathOrPackageName, port, authToken) {450 if (!factoryPathOrPackageName) factoryPathOrPackageName = _path.default.join('..', 'grid', 'simpleGridFactory');451 let factory;452 try {453 factory = require(_path.default.resolve(factoryPathOrPackageName));454 } catch (e) {455 factory = require(factoryPathOrPackageName);456 }457 if (factory && typeof factory === 'object' && 'default' in factory) factory = factory['default'];458 if (!factory || !factory.launch || typeof factory.launch !== 'function') throw new Error('factory does not export `launch` method');459 factory.name = factory.name || factoryPathOrPackageName;460 const gridServer = new _gridServer.GridServer(factory, authToken);461 await gridServer.start(port);462 console.log('Grid server is running at ' + gridServer.urlPrefix());463}464function buildBasePlaywrightCLICommand(cliTargetLang) {465 switch (cliTargetLang) {466 case 'python':467 return `playwright`;468 case 'java':469 return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="...options.."`;470 case 'csharp':471 return `playwright`;472 default:473 return `npx playwright`;474 }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const playwright = require('playwright');2const browserType = 'chromium';3const browser = await playwright[browserType].launch();4const context = await browser.newContext();5const page = await context.newPage();6await page.screenshot({ path: 'example.png' });7await browser.close();8const { buildBasePlaywrightCLICommand } = require('playwright-core/lib/utils/registry');9const baseCommand = buildBasePlaywrightCLICommand();10module.exports = {11 {12 use: {13 },14 },15};16{17 "scripts": {18 },19 "devDependencies": {20 }21}

Full Screen

Using AI Code Generation

copy

Full Screen

1const { buildBasePlaywrightCLICommand } = require('playwright/lib/utils/utils');2const { BrowserType } = require('playwright/lib/server/browserType');3const { BrowserServer } = require('playwright/lib/server/browserServer');4const { Browser } = require('playwright/lib/server/browser');5const { Page } = require('playwright/lib/server/page');6const { BrowserContext } = require('playwright/lib/server/browserContext');7const { ElectronApplication } = require('playwright/lib/server/electron');8const { WebKitBrowser } = require('playwright/lib/server/webkit');9const { WebKitBrowserContext } = require('playwright/lib/server/webkit');10const { WebKitPage } = require('playwright/lib/server/webkit');11const { WebKit } = require('playwright/lib/server/webkit');12const { Android } = require('playwright/lib/server/android');13const { AndroidBrowser } = require('playwright/lib/server/android');14const { AndroidBrowserContext } = require('playwright/lib/server/android');15const { AndroidPage } = require('playwright/lib/server/android');16const { AndroidDevice } = require('playwright/lib/server/android');17const { AndroidDeviceManager } = require('playwright/lib/server/android');18const { BrowserContextDispatcher } = require('playwright/lib/server/browserContextDispatcher');19const { BrowserDispatcher } = require('playwright/lib/server/browserDispatcher');20const { BrowserServerDispatcher } = require('playwright/lib/server/browserServerDispatcher');21const { ElectronApplicationDispatcher } = require('playwright/lib/server/electronDispatcher');22const { PageDispatcher } = require('playwright/lib/server/pageDispatcher');23const { AndroidBrowserContextDispatcher } = require('playwright/lib/server/androidDispatcher');24const { AndroidBrowserDispatcher } = require('playwright/lib/server/androidDispatcher');25const { AndroidDeviceDispatcher } = require('playwright/lib/server/androidDispatcher');26const { AndroidPageDispatcher } = require('playwright/lib/server/androidDispatcher');27const { AndroidDispatcher } = require('playwright/lib/server/androidDispatcher');28const { WebKitBrowserContextDispatcher } = require('playwright/lib/server/webkitDispatcher');29const { WebKitBrowserDispatcher } = require('playwright/lib/server/webkitDispatcher');30const { WebKitPageDispatcher } = require('playwright/lib/server/webkitDispatcher');31const { WebKitDispatcher } = require('playwright/lib/server/webkitDispatcher');32const { AndroidDeviceManagerDispatcher } = require('playwright

Full Screen

Using AI Code Generation

copy

Full Screen

1const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/test');2const { expect } = require('@playwright/test');3const { test } = require('@playwright/test');4const { devices } = require('@playwright/test');5const { chromium } = require('playwright');6const { webkit } = require('playwright');7const { firefox } = require('playwright');8const { devices } = require('playwright');9const { expect } = require('playwright');10const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/test');11const { test } = require('@playwright/test');12const { chromium } = require('playwright');13const { firefox } = require('playwright');14const { webkit } = require('playwright');15const { devices } = require('playwright');16const { expect } = require('playwright');17const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/test');18const { test } = require('@playwright/test');19const { chromium } = require('playwright');20const { firefox } = require('playwright');21const { webkit } = require('playwright');22const { devices } = require('playwright');23const { expect } = require('playwright');24const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/test');25const { test } = require('@playwright/test');26const { chromium } = require('playwright');27const { firefox } = require('playwright');28const { webkit } = require('playwright');29const { devices } = require('playwright');30const { expect } = require('playwright');31const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/test');32const { test } = require('@playwright/test');33const { chromium } = require('playwright');34const { firefox } = require('playwright');35const { webkit } = require('playwright');36const { devices } = require('playwright');37const { expect } = require('playwright');

Full Screen

Using AI Code Generation

copy

Full Screen

1const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/utils/cli');2const { createTestType } = require('@playwright/test/lib/types');3const { PlaywrightTestConfig } = require('@playwright/test/lib/config');4const { PlaywrightTest } = require('@playwright/test/lib/test');5const testType = createTestType('testType');6const config = new PlaywrightTestConfig();7const test = new PlaywrightTest(config, testType);8const basePlaywrightCLICommand = buildBasePlaywrightCLICommand(test);9console.log(basePlaywrightCLICommand);10const { spawnSync } = require('child_process');11spawnSync(basePlaywrightCLICommand, ['test.js'], { stdio: 'inherit' });12testType.use({ workers: 2 });13spawnSync(basePlaywrightCLICommand, ['test.js'], { stdio: 'inherit' });

Full Screen

Using AI Code Generation

copy

Full Screen

1const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/cli/cli');2const { spawn } = require('child_process');3const { join } = require('path');4const pathToPlaywrightConfig = join(__dirname, 'playwright.config.js');5const pathToPlaywrightTest = join(__dirname, 'playwright.config.js');6const pathToTestFile = join(__dirname, 'test.spec.js');7const command = buildBasePlaywrightCLICommand(pathToPlaywrightConfig, pathToPlaywrightTest, pathToTestFile);8const child = spawn(command, { shell: true });9child.stdout.on('data', (data) => {10 console.log(`stdout: ${data}`);11});12child.stderr.on('data', (data) => {13 console.error(`stderr: ${data}`);14});15child.on('close', (code) => {16 console.log(`child process exited with code ${code}`);17});18child.on('error', (err) => {19 console.log(`child process errored with code ${err}`);20});21module.exports = {22 {23 use: {24 viewport: { width: 1280, height: 720 },25 },26 },27};28const { test, expect } = require('@playwright/test');29test('basic test', async ({ page }) => {30 const title = page.locator('text=Playwright');31 await expect(title).toBeVisible();32});

Full Screen

Using AI Code Generation

copy

Full Screen

1const { buildBasePlaywrightCLICommand } = require("playwright/lib/cli/cli");2const { createRequire } = require('module');3const require = createRequire(import.meta.url);4const playwright = require('playwright');5const playwrightConfig = require('./playwright.config.js');6const testConfig = require('./test.config.js');7const run = async () => {8 const { browsers, devices, launchOptions } = playwrightConfig;9 const { testName, testPath } = testConfig;10 const cliCommand = buildBasePlaywrightCLICommand({11 });12 const browser = await playwright.chromium.launch();13 const context = await browser.newContext();14 const page = await context.newPage();15 await page.screenshot({ path: 'example.png' });16 await browser.close();17};18run();19module.exports = {20 launchOptions: {21 }22};23module.exports = {24};

Full Screen

Using AI Code Generation

copy

Full Screen

1const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/utils/cli');2const cliCommand = buildBasePlaywrightCLICommand();3console.log(cliCommand);4const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/utils/cli');5const cliCommand = buildBasePlaywrightCLICommand();6console.log(cliCommand);7const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/utils/cli');8const cliCommand = buildBasePlaywrightCLICommand();9console.log(cliCommand);10const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/utils/cli');11const cliCommand = buildBasePlaywrightCLICommand();12console.log(cliCommand);13const { buildBasePlaywrightCLICommand } = require('@playwright/test/lib/utils/cli');14const cliCommand = buildBasePlaywrightCLICommand();15console.log(cliCommand);

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