Playwright Command Line Interface has moved directly to Playwright.
$ npx playwright --help
Please submit any issues or feature requests to the playwright repository and mention "cli" in the title.
CLI for common Playwright actions. Record and generate Playwright code, inspect selectors and take screenshots.
Home Page: https://playwright.dev
License: Apache License 2.0
Playwright Command Line Interface has moved directly to Playwright.
$ npx playwright --help
Please submit any issues or feature requests to the playwright repository and mention "cli" in the title.
npx playwright-cli -b wk pdf maps.google.com wk.pdf
It just produces a chromium pdf - that surprised my quite a bit. Perhaps we can print a warning/error?
Actual:
// Fill input[name="q"]
await page.fill('input[name="q"]', 'max');
// Press @ with modifiers
await page.press('input[name="q"]', 'Alt+@');
// Fill input[name="q"]
await page.fill('input[name="q"]', 'maxtest.com');
Expected:
// Fill input[name="q"]
await page.fill('input[name="q"]', '[email protected]');
Launch playwright-cli record https://github.com
and then clicking in the search in the top right corner, type "playwright" and hit "enter". Typing is missing.
const assert = require('assert');
const { chromium, firefox, webkit } = require('playwright');
(async() => {
const browser = await chromium.launch();
const page = await browser.newPage();
// Go to https://github.com/
await page.goto('https://github.com/');
// 0× click
await page.click('li[id=jump-to-suggestion-search-global]');
assert.equal(page.url(), 'https://github.com/search?q=playwright');
})();
Launch playwright-cli record https://playwright.dev
, click search and try typing evaluate
there. The generated selector is broken
const assert = require('assert');
const { chromium, firefox, webkit } = require('playwright');
(async() => {
const browser = await chromium.launch();
const page = await browser.newPage();
// Go to https://playwright.dev/
await page.goto('https://playwright.dev/');
// Click <selector>
await page.click('<selector>');
// Fill <selector>
await page.fill('<selector>', 'evaluate');
assert.equal(page.url(), 'https://playwright.dev/#version=v1.2.0&path=docs%2Fapi.md&q=pageevaluatepagefunction-arg');
})();
playwright-cli record https://theverge.com
, try clicking on any article. Generated selector is broken - it's simply img[alt=""]
.const assert = require('assert');
const { chromium, firefox, webkit } = require('playwright');
(async() => {
const browser = await chromium.launch();
const page = await browser.newPage();
// Go to https://www.theverge.com/
await page.goto('https://www.theverge.com/');
// Click img[alt=""]
await Promise.all([
page.waitForNavigation({ url: 'https://www.theverge.com/2020/7/7/21314972/away-employees-ceo-steph-korey-resign-native-american-costume' }),
page.click('img[alt=""]')
]);
})();
Launch playwright-cli record https://bbc.com
, try clicking on any article. The generated selector has wrongly escaped quotes, and doesn't point to the element I clicked.
const assert = require('assert');
const { chromium, firefox, webkit } = require('playwright');
(async() => {
const browser = await chromium.launch();
const page = await browser.newPage();
// Go to https://www.bbc.com/
await page.goto('https://www.bbc.com/');
// Click div[id=page] text=/\s*Brazil's Bolsonaro tests positive for Covid-19\s*/
await page.click('div[id=page] text=/\\s*Brazil\\'s Bolsonaro tests positive for Covid-19\\s*/');
})();
Execution Context is not available in detached frame "https://tpc.googlesyndication.com/sodar/sodar2/217/runner.html" (are you trying to evaluate?)
at Connection.sendMessageToServer (/Users/pfeldman/code/playwright-cli/node_modules/playwright/lib/client/connection.js:69:15)
at Proxy. (/Users/pfeldman/code/playwright-cli/node_modules/playwright/lib/client/channelOwner.js:54:53)
at Frame._extendInjectedScript (/Users/pfeldman/code/playwright-cli/node_modules/playwright/lib/client/frame.js:355:44)
at ScriptController._ensureInstalledInFrame (/Users/pfeldman/code/playwright-cli/lib/scriptController.js:38:30)
at Page. (/Users/pfeldman/code/playwright-cli/lib/scriptController.js:33:49)
Issue: Input element rendered by React which has the value rendered in it.
<input type="text" id="first_name" class="ant-input" value="Hi Mama">
Expected:
await page.click('//input[@id="first_name"]');
await page.fill('//input[@id="first_name"]', 'Admin1');
Actual:
// Click //input[normalize-space(@type)='text' and normalize-space(@value)='Admin']
await page.click('//input[normalize-space(@type)=\'text\' and normalize-space(@value)=\'Admin\']');
// Fill //input[normalize-space(@type)='text' and normalize-space(@value)='Admin']
await page.fill('//input[normalize-space(@type)=\'text\' and normalize-space(@value)=\'Admin\']', 'Admin1');
I would treat ID and name as static attributes which get prioritised in the selector engine.
Chrome has a feature integrated in the DevTools to copy a selector, maybe we can steal some logic from there!
First of all congratulations on the release. I am super excited to start using this software.
Bug report:
__playwright_evaluation_script__763:192 Uncaught TypeError: Cannot read property 'length' of undefined
at Object.parseSelector (__playwright_evaluation_script__763:192)
at InjectedScript.parseSelector (__playwright_evaluation_script__763:688)
at Object.buildSelector (eval at extend ((index):733), <anonymous>:1032:43)
at ConsoleAPI.buildSelector (eval at extend ((index):733), <anonymous>:351:36)
at Object.selector (eval at extend ((index):733), <anonymous>:319:41)
at <anonymous>:1:12
parseSelector @ __playwright_evaluation_script__763:192
parseSelector @ __playwright_evaluation_script__763:688
buildSelector @ VM1432:1032
buildSelector @ VM1432:351
selector @ VM1432:319
(anonymous) @ VM2126:1
Here is the site I was using to find these issues: fanteam.com
<input id="1" placeholder="1" />
<input id="2" placeholder="2" />
Test case:
#1
Expected result:
Page fill with the #2
element
Actual result:
Page fill with the #1
element
Relates #21
With #74, I could start introducing playwright into my workplace. When can we expect the next release to be cut and how can we help?
First of all, thank you for what you've done already! Now to the question: can the tool generate code in Python so that it can be used with Playwright Python (https://github.com/microsoft/playwright-python)?
And if it's not, is it planned to be added?
I'm in an enterprise environment, where I can't download arbitrary binaries. I have Chrome and Edgium installed on my machine, and I've been using them with puppeteer-core, providing path to executables. When I tried installing playwright-cli, I got a dns error for playwright.azureedge.net. I suspect this is due to my network restrictions. One way or another, my company firewalls won't let me download a custom browser.
I managed to install playwright-cli via npm install --ignore-scripts
, but it looks like I can't provide a path to my existing browser executable. I got around this by copying whole chrome folder to the path playwright-cli expected to find it, launched npx playwright-cli codegen wikipedia.org
and it worked, window showed up and actions were recorded in script. But resulting window is in incognito mode, so I can't access any of my intranet sites (all requiring certificate to authenticate).
I think this kind of restrictions will be typical for an enterprise environment, so would it be possible to use codegen with existing browser and without incognito mode?
Testing on online.visualstudio.com
waitForEvent
// Click input[aria-label="Codespace Name"]
await page.click('input[aria-label="Codespace Name"]');
// Fill input[aria-label="Codespace Name"]
await page.fill('input[aria-label="Codespace Name"]', 'asdf');
// Click button[aria-label="Show pricing information..."]
await page.click('button[aria-label="Show pricing information..."]'); <---- This opens a new tab
// Click text=/.*Try for free.*/
await popup1.click('text=/.*Try for free.*/');
// assert.equal(popup1.url(), 'https://azure.microsoft.com/en-us/free/');
First of all, great work with playwright-cli! 🚀
I've tried using playwright-cli for the local HTML file but got an issue, eg.
npx playwright-cli pdf ./my-dir/index.html my-file.pdf
Any chance to fix the above one? Thank you in advance! 🍻
My current output looks something like..
[38;5;205mconst�[0m { chromium } = �[38;5;220mrequire�[0m(�[38;5;130m'playwright'�[0m);
(�[38;5;205masync�[0m () => {
�[38;5;205mconst�[0m browser = �[38;5;205mawait�[0m chromium.launch({
headless: �[38;5;159mfalse�[0m
});
�[38;5;205mconst�[0m context = �[38;5;205mawait�[0m browser.newContext();
})();
�[1A�[2K
�[38;5;23m// Open new page�[0m
�[38;5;205mconst�[0m page = �[38;5;205mawait�[0m context.newPage();
})();
There is a typo in the playwright-cli pdf command example. PR incoming.
- console.log(' $ pdf https://example.com example.png');
+ console.log(' $ pdf https://example.com example.pdf');
Command: node lib/cli.js codegen file://$(pwd)/test.html
test.html:
<a href="https://instagram.com/microsoft" target="_blank" rel="noopener noreferrer">Instagram</a>
Actual result:
// Click text="Instagram"
const [page1] = await Promise.all([
page1.waitForEvent('popup'),
page1.waitForNavigation(/*{ url: 'https://www.instagram.com/microsoft/' }*/),
page1.click('text="Instagram"')
]);
Expected result (I guess):
const [page1] = await Promise.all([
page.waitForEvent('popup'),
page.click('text="Instagram"')
]);
I saw in the master source that the command codegen should support a output option.
If I try that inside the command line I only get a error message.
Master source code
program
.command('codegen [url]')
.description('open page and generate code for user actions')
.option('-o --output <file name>', 'saves the generated script to a file')
.action(function(url, command) {
codegen(command.parent, url, command.output);
}).on('--help', function() {
console.log('');
console.log('Examples:');
console.log('');
console.log(' $ record');
console.log(' $ -b webkit record https://example.com');
});
playwright-cli codegen -o login.js localhost:8090
error: unknown option '-o'
playwright-cli -V
Version 0.5.2
Running npx playwright-cli wk maps.google.com
shows blurry browser. I guess we should default to the host dpi in this case?
npx playwright-cli wk wikipedia.org
Cannot select a select option item.
Try it with:
playwright-cli codegen https://www.w3schools.com/tags/tryit.asp?filename=tryhtml_select
npx playwright-cli --device "JioPhone 2" codegen wikipedia.org
Results in:
(node:95076) UnhandledPromiseRejectionWarning: browser.newContext: options.isMobile is not supported in Firefox
at FirefoxBrowser._wrapApiCall (/Users/max/Development/playwright-cli/node_modules/playwright/lib/client/channelOwner.js:76:15)
at FirefoxBrowser.newContext (/Users/max/Development/playwright-cli/node_modules/playwright/lib/client/browser.js:42:21)
at launchContext (/Users/max/Development/playwright-cli/lib/cli.js:169:35)
at async open (/Users/max/Development/playwright-cli/lib/cli.js:197:69)
(node:95076) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:95076) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Reported by Arjun, needs to be clarified how we should handle that.
I have been using a headful puppetteer for making screen recordings with audio, to turn HTML pages into video.
Is there a path for this to do something similar?
How can I preview traceviewer feature?
When I run cli,I can not find it from dev tools
When clicking "Select your room" on booking.com, I get the following:
await page.click('//div[normalize-space(@aria-label)=\'Search results\' and normalize-space(@role)=\'region\']/div[4]/div[2]/div[3]/div/div[normalize-space(@role)=\'presentation\']/div/div/div[2]/div[3]/div/div/div/a[normalize-space(.)=\'Select your room\']');
await popup1.goto('https://www.booking.com/searchresults.html?long-long-long-long-url-here');
Perhaps, we can use page.waitForEvent('popup')
to introduce popup1
? Also, it is loading the initial url by itself, can probably figure that out as well.
Command: node lib/cli.js codegen file://$(pwd)/test.html
test.html:
<textarea data-testid="foobar"></textarea>
Actual result:
Nothing
Expected result:
await page.fill('textarea[data-testid="foobar"]', 'foobar123');
Python official style guide recommends default indentation of 4 spaces
This is flaky. I managed to enter a state where codegen produces "click" action every second, without me doing anything. Perhaps, previous click was not handled properly?
npx playwright-cli --device="Pixel 2" codegen wikipedia.org
Currently, this is generated as
(async() => {
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36',
viewport: {
width: 411,
height: 731
},
isMobile: true,
hasTouch: true,
defaultBrowserType: 'chromium'
});
It would be great to see this as
(async() => {
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext({
...devices['Pixel 2']
});
When I use "Quit Playwright" menu item, cli terminates with an error:
(node:10230) UnhandledPromiseRejectionWarning: browser.close: Target browser or context has been closed
at WebKitBrowser._wrapApiCall (/Users/dgozman/code/pwuse/node_modules/playwright-cli/node_modules/playwright/lib/client/channelOwner.js:76:15)
at WebKitBrowser.close (/Users/dgozman/code/pwuse/node_modules/playwright-cli/node_modules/playwright/lib/client/browser.js:74:21)
at Page. (/Users/dgozman/code/pwuse/node_modules/playwright-cli/lib/cli.js:160:25)
at Page.emit (events.js:210:5)
at Page._onClose (/Users/dgozman/code/pwuse/node_modules/playwright-cli/node_modules/playwright/lib/client/page.js:138:14)
at Proxy. (/Users/dgozman/code/pwuse/node_modules/playwright-cli/node_modules/playwright/lib/client/page.js:66:46)
at Proxy.emit (events.js:210:5)
at Connection.dispatch (/Users/dgozman/code/pwuse/node_modules/playwright-cli/node_modules/playwright/lib/client/connection.js:99:25)
at Immediate._onImmediate (/Users/dgozman/code/pwuse/node_modules/playwright-cli/node_modules/playwright/lib/inprocess.js:37:85)
at processImmediate (internal/timers.js:439:21)
(node:10230) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:10230) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Run npx playwright-cli@next codegen --target python
, do some actions and close the browser.
# Close page
await page.close()
# Close browser await browser.close()
asyncio.get_event_loop().run_until_complete(main())
We could add line breaks before browser.close
and also before the last line for readability.
Need some help please.
I have a company internal website with Power BI visuals. I am trying to use playwright to develop test cases that would test the reports like a user would manipulate them. I am having trouble finding what is the correct object to use to click on a row in a visual. Clicking this element, would adjust all of the other visuals. I would also need to "get" this element text.
I used a public Power BI report that has the same class names and object names like (pivotTableCellWrap cell-interactive tablixAlignLeft )to use as a test for my question since I can not provide a link to our reports.
I ran the following.
npx playwright-cli codegen https://community.powerbi.com/t5/Data-Stories-Gallery/Customer-Analysis-Dashboard/td-p/630893
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
headless: false
});
const context = await browser.newContext();
// Open new page
const page = await context.newPage();
// Go to https://community.powerbi.com/t5/Data-Stories-Gallery/Customer-Analysis-Dashboard/td-p/630893
await page.goto('https://community.powerbi.com/t5/Data-Stories-Gallery/Customer-Analysis-Dashboard/td-p/630893');
// Click text="Weimei Corp"
await page.frame({
url: 'https://app.powerbi.com/view?r=eyJrIjoiNDIyYWJjM2ItYTgwMi00NjQzLWEzYTItZWMwNzIzOTY2MDUxIiwidCI6IjA0ZWM2MTA5LTRjNzktNGM3My1hZTcxLWE0NzRjMDlhMWY1YSJ9'
}).click('text="Weimei Corp"');
// Close page
await page.close();
The play back actually works, for this site but not mine, because my isn't including the "view" url in the page frame. Maybe because this report was setup specifically to be public and they had to adjust how they did it.
when I do my recording I get the following which doesn't work on playback.
// 0× click
await page.click('//iframe');
// Click text="THERESA"
await page.click('text="THERESA"');
This is what I am doing to get the frame name, not sure where the //iframe came from and it doesn't work either way.
//locate the iframe name visual sandbox
const frame = page.frames().find(frame => frame.name() === 'visual-sandbox');
console.log(frame.name());
I also noticed that during the recording for a different text than I saw a difference reference and that is because that name is in there twice but not as a duplicate just different info for it. I tried that syntax and it didn't work.
//div[3][normalize-space(.)='THERESA WADE' and normalize-space(@title)='THERESA WADE']"
I have attached a few screen shots from my visual. ( I apologize but I had to blur out sensitive PI data). There are some that shows what is displayed when I hover over the different sections when I am using the recording. Which is completely different than what I get from Chrome Dev Tools and do copy selector, js path, or element.
How can I convert my recordings to the correct object and syntax.
Which object and method is the correct one for clicking in pivotTableCellWrap cell-interactive tablixAlignLeft ? then also get that value for sanity check?
Here are the element references:
Copy Element
COPY SELECTOR
#pvExplorationHost > div > div > exploration > div > explore-canvas-modern > div > div.canvasFlexBox > div > div.displayArea.disableAnimations.fitToPage > div.visualContainerHost > visual-container-repeat > visual-container-modern:nth-child(3) > transform > div > div:nth-child(4) > div > visual-modern > div > div > div.tableEx > div.innerContainer > div.bodyCells > div > div > div:nth-child(1) > div:nth-child(1)
COPY JSPATH
document.querySelector("#pvExplorationHost > div > div > exploration > div > explore-canvas-modern > div > div.canvasFlexBox > div > div.displayArea.disableAnimations.fitToPage > div.visualContainerHost > visual-container-repeat > visual-container-modern:nth-child(3) > transform > div > div:nth-child(4) > div > visual-modern > div > div > div.tableEx > div.innerContainer > div.bodyCells > div > div > div:nth-child(1) > div:nth-child(1)")
COPY XPATH
//*[@id="pvExplorationHost"]/div/div/exploration/div/explore-canvas-modern/div/div[2]/div/div[2]/div[2]/visual-container-repeat/visual-container-modern[3]/transform/div/div[3]/div/visual-modern/div/div/div[2]/div[1]/div[4]/div/div/div[1]/div[1]
screenshots from my recording.
This means created scripts are not self-contained and are hanging.
Specific to bing.com
Repro steps:
await page.fill('input[aria-label="Enter your search term"]', 'git');
OS: Windows
Running on plain command prompt works great, but running in the integrated VS Code terminal with cmd prompt does not update the stdout on recorder actions.
Steps to repro:
npx playwright-cli codegen wikipedia.org
await page.fill('input[name="search"]', 'pl');
node lib/cli.js codegen file://$(pwd)/test.html
<input type="date"/>
Ubuntu 20.04
Tried running
npx playwright-cli --device="iPhone 11" open wikipedia.org
As per Readme.
Result:
[err] /home/dan/.cache/ms-playwright/webkit-1343/minibrowser-gtk/bin/MiniBrowser: error while loading shared libraries: libenchant.so.1: cannot open shared object file: No such file or directory
When multiple elements match the proposed selector, we highlight them all. How can I be sure that the action targets a particular one?
Testing on online.visualstudio.com
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
// Click text="Dotfiles (Optional)"
await page.click('text="Dotfiles (Optional)"');
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.