Compare commits

...

1456 commits

Author SHA1 Message Date
Pavel Feldman 31f4a05eb6
chore: make git diff different for CI and local (#34955) 2025-02-27 14:06:13 -08:00
Pavel Feldman 7a61aa25e6
chore: provide blob name for web and html reporter tests (#34940) 2025-02-27 13:22:07 -08:00
Adam Gastineau 67d6f7f603
chore: temporarily disable floating promise warning messages (#34957) 2025-02-27 12:45:30 -08:00
Adam Gastineau b0ceed51a5
docs: Improve toHaveURL doc clarity (#34935) 2025-02-27 11:00:50 -08:00
Dmitry Gozman 08ea36caa2
chore: default reportSlowTests to 5 minutes (#34950) 2025-02-27 16:31:32 +00:00
Dmitry Gozman 70cc2b14e2
chore: apply "injected" eslint rules to "isomorphic" (#34953) 2025-02-27 16:31:05 +00:00
Playwright Service ad64f8d859
feat(chromium): roll to r1161 (#34952)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-27 17:01:07 +01:00
Simon Knott a1146fd4a3
chore: copy as prompt in ui should have codeframe (#34943)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-02-27 15:50:46 +01:00
Dmitry Gozman 3ce9ae6a7d
chore: replace locator.visible with filter({ visible }) (#34947) 2025-02-27 13:44:53 +00:00
Simon Knott 837abfbc15
chore: document indexeddb type as "unknown" (#34944) 2025-02-27 14:29:22 +01:00
Simon Knott 10fc0ef221
chore: make indexeddb opt-in (#34942) 2025-02-27 14:27:54 +01:00
Pavel Feldman 58db3f7e3f
chore: restore pr title in html report (#34937) 2025-02-26 19:22:31 -08:00
Henrik Skupin a803e6053a
chore(bidi): use fractional coordinates for pointerAction (#34929) 2025-02-26 16:28:14 -08:00
Yury Semikhatsky b5fe029c1b
chore: remove failOnStatusCode from Browser.newContext, rename (#34936) 2025-02-26 15:03:21 -08:00
Pavel Feldman cd23a224f6
chore: another iteration on gitCommit/gitDiff props (#34926) 2025-02-26 08:40:30 -08:00
Simon Knott 17c4d8e5ec
chore: change generated filename for toMatchAriaSnapshot from .yml to .snapshot.yml (#34931)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2025-02-26 16:29:56 +01:00
Simon Knott a04a93c1fd
chore: change pageSnapshot extension to .snapshot.yml (#34930) 2025-02-26 14:27:17 +01:00
Dmitry Gozman 439427c14e
chore: remove stages from TestInfoImpl (#34919) 2025-02-26 10:55:02 +00:00
Yury Semikhatsky aaac9923fd
fix: disable global timeout when debugging (#34922) 2025-02-25 11:33:15 -08:00
Pavel Feldman 411f938296
chore: clean up git commit metadata props and UI (#34867) 2025-02-25 09:21:17 -08:00
Dmitry Gozman b148cbad76
fix: remove unicode soft hyphen in normalizeWhitespace (#34920) 2025-02-25 16:54:02 +00:00
Simon Knott a9bbf4b56d
docs: recommend localhost over 127.0.0.1 (#34918) 2025-02-25 15:40:38 +01:00
Simon Knott 9e38473309
fix(runner): hide APIResponse.* calls from results (#34909) 2025-02-25 14:26:54 +01:00
Dmitry Gozman 81855d11e4
chore: add playwright-client to the list of packages (#34916) 2025-02-25 13:23:38 +00:00
Dmitry Gozman ed0bf35435
feat: locator.visible (#34905) 2025-02-25 11:48:15 +00:00
Yury Semikhatsky 9b633ddd2f
docs: touch events guide improvements (#34903) 2025-02-24 14:13:27 -08:00
Vitaliy Potapov c4be54b45c
Docs: improve docs and tests for URL glob pattern (#34899) 2025-02-24 12:22:24 -08:00
Simon Knott 1a8f00c45f
fix: don't wrap button contents in two lines (#34887) 2025-02-24 12:15:21 -08:00
Yury Semikhatsky dbbdabfd1b
chore: pass JSHandles instead of ObjectId to/from context delegate (#34895) 2025-02-24 12:11:17 -08:00
Yury Semikhatsky 954457ba9e
chore: fix firefox tests after switching to context delegate (#34898) 2025-02-22 17:12:39 -08:00
Yury Semikhatsky e091baad79
chore: make execution context delegate public (#34894) 2025-02-21 18:27:24 -08:00
Yury Semikhatsky e38099ef13
chore: getProperties can use context stored in JSHandle (#34893) 2025-02-21 17:55:02 -08:00
Yury Semikhatsky 1af59ee523
chore(bidi): do not leak utility handles (#34892) 2025-02-21 17:44:33 -08:00
Yury Semikhatsky 962a752832
chore: contain remote objects to browser-specific code (#34890) 2025-02-21 16:52:39 -08:00
Yury Semikhatsky 6486ac006e
chore: initialize utility script privately (#34812) 2025-02-21 13:59:55 -08:00
Pavel Feldman 325fe71bb9
chore: minor html report polish (#34864) 2025-02-21 13:49:23 -08:00
Yury Semikhatsky 65910c4ac5
test: unskip "should preserve cookie order from Set-Cookie header" (#34888) 2025-02-21 10:04:01 -08:00
Max Schmitt 132d93151c
test: replace setTimeout with builtinSetTimeout in UI mode test (#34885) 2025-02-21 07:38:24 -08:00
Max Schmitt af61d659cb
chore: fix roll_browser script (#34886) 2025-02-21 07:37:52 -08:00
Playwright Service 0bb5925d0d
feat(chromium): roll to r1160 (#34884)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2025-02-21 15:40:18 +01:00
Max Schmitt 428f196036
test: have typed RunResult.results (#34883) 2025-02-21 14:22:59 +01:00
Simon Knott 48fb536e12
chore(screenshot): warn about visibility of masked elements (#34881) 2025-02-21 13:52:44 +01:00
Sang Nguyen e4ceac8e4c
docs: correct closing tags for option elements in HTML examples (#34874) 2025-02-21 09:38:47 +01:00
Adam Gastineau c64f0ffa1d
chore: manually add exception for esbuild vulnerability (#34875) 2025-02-20 14:47:44 -08:00
Adam Gastineau 33c0a1b0ca
chore: add floating promise warning to hooks (#34861) 2025-02-20 10:46:49 -08:00
Simon Knott bb8e914294
feat(ui): collapse repeating console lines (#34857) 2025-02-20 14:48:20 +01:00
Playwright Service e43d287d8d
feat(webkit): roll to r2140 (#34866)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-20 11:15:46 +01:00
Simon Knott aca3fb275b
fix(runner): validate config.tsconfig (#34849) 2025-02-20 09:11:50 +01:00
Pavel Feldman d5adeb3cf4
chore: build a client bundle (#34847) 2025-02-19 15:27:00 -08:00
Simon Knott 1f1e2acf9b
chore: rename prompt button (#34851) 2025-02-19 14:32:58 -08:00
Adam Gastineau f5b8cca1eb
feat: Warn on floating promises (#34845) 2025-02-19 10:11:04 -08:00
Max Schmitt 3584e72223
chore: remove 'as *' imports because of esModuleInterop: true (#34854) 2025-02-19 15:32:12 +01:00
Simon Knott a3e8788b9c
chore: hide llm chat (#34852) 2025-02-19 14:14:18 +01:00
Max Schmitt 7f7ab96893
chore: fix tsc linting error (#34853) 2025-02-19 12:18:42 +01:00
Playwright Service dcb9ed8d41
feat(webkit): roll to r2139 (#34850)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-19 11:11:40 +01:00
Playwright Service 0baadb513b
feat(chromium-tip-of-tree): roll to r1304 (#34842)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-18 16:24:09 +01:00
Bedřich Schindler 741a7079fe
docs(ct): add brief information about CSS modules into FAQ (#34677) 2025-02-18 06:44:09 -08:00
Max Schmitt 081031f50e
chore: bump vite to v6 (#34663) 2025-02-18 13:29:16 +01:00
Max Schmitt 1af4e367f4
fix(testServer): pass use options to listFiles command (#34832) 2025-02-18 00:33:45 +01:00
Playwright Service 715123afbe
feat(firefox-beta): roll to r1471 (#34796)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-17 10:04:32 +01:00
Playwright Service 060ef5562d
feat(webkit): roll to r2138 (#34814)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-17 09:34:16 +01:00
Max Schmitt 605eb0d657 Revert "devops: migrate away from merge.config.ts (#34802)"
This reverts commit df6e3f043a.
2025-02-17 09:33:20 +01:00
Pavel Feldman f70f92d5cd
chore: do not use process in client (#34816) 2025-02-15 19:49:30 -08:00
Pavel Feldman 3606a434fe
chore: pass validator into validator context (#34810) 2025-02-15 08:28:28 -08:00
Pavel Feldman 024a52821a
chore: init eventEmitter w/ platform (#34809) 2025-02-14 17:06:11 -08:00
Yury Semikhatsky 145b6bf4fe
chore: browser independent setInputFiles implementation (#34808) 2025-02-14 16:44:27 -08:00
Pavel Feldman 8b28e637c8
chrome: remove state from isomorphic utils (#34795) 2025-02-14 15:10:50 -08:00
Yury Semikhatsky be95a08c4d
feat(webkit): roll to r2137, update tests (#34806) 2025-02-14 11:25:35 -08:00
Simon Knott fe0b327770
feat(ui): llm conversation about error (#34750) 2025-02-14 16:59:26 +01:00
Max Schmitt df6e3f043a
devops: migrate away from merge.config.ts (#34802) 2025-02-14 11:58:37 +01:00
Dmitry Gozman e6b405c012
chore: show gha pull request title instead of a merge commit (#34781) 2025-02-14 09:32:06 +00:00
Playwright Service 32c299c89d
feat(chromium): roll to r1159 (#34780)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2025-02-14 09:33:55 +01:00
Playwright Service e276d92dd3
feat(chromium-tip-of-tree): roll to r1303 (#34783)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-14 09:33:27 +01:00
Pavel Feldman 7f742a04b0
chore: make client compile for web (#34792) 2025-02-13 18:33:17 -08:00
Pavel Feldman 4a9b336168
chore: for not use Node's events in client (#34791) 2025-02-13 16:46:24 -08:00
Yury Semikhatsky 6833b664e3
test: update modernizr expectations with actual mobile Safari 18.3 values (#34789) 2025-02-13 16:37:15 -08:00
Pavel Feldman 163aacf4b6
chore: allow client operation w/o local utils (#34790) 2025-02-13 16:15:11 -08:00
Pavel Feldman 90ec838318
chore: move zones into platform (#34786) 2025-02-13 13:06:03 -08:00
Pavel Feldman 9ecf2f69ba
chore: move pipe transport utils to server/ (#34787) 2025-02-13 12:30:53 -08:00
Yury Semikhatsky e03402f7a7
chore(bidi): implement setInputFile(FilePayload) (#34785) 2025-02-13 12:11:05 -08:00
Playwright Service 5028fb6270
chore(driver): roll driver to recent Node.js LTS version (#34776)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-13 12:09:18 +01:00
Playwright Service ea67eca5be
feat(webkit): roll to r2134 (#34754)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-13 10:05:41 +01:00
Pavel Feldman ded909c13f
chrome: restore colors enabled/levels logic (#34767) 2025-02-12 21:13:25 -08:00
Pavel Feldman 3d760b657b
chore: move debug, env and user agent from utils/ (#34766) 2025-02-12 19:27:24 -08:00
Yury Semikhatsky 6951e6ad9d
chore(bidi): move private handle conversion to execution context (#34765) 2025-02-12 18:14:39 -08:00
Yury Semikhatsky bab197b493
test: adjust bidi browser name in browsertype-connect.spec (#34758) 2025-02-12 18:04:42 -08:00
Pavel Feldman e697b1a663
chore: remove stackTrace => path dependency (#34763) 2025-02-12 18:03:23 -08:00
Pavel Feldman c31ce783b7
chore: move event utils to server (#34761) 2025-02-12 15:22:10 -08:00
Pavel Feldman 0eeba380f2
chore: move crypto to server/util/ (#34759) 2025-02-12 14:43:52 -08:00
Yury Semikhatsky c2c336b97d
chore(bidi): implement setInputFiles (#34757) 2025-02-12 12:49:05 -08:00
Yury Semikhatsky 0bd3a99f04
tests: put filechooser and setInputFiles tests into separate files (#34756) 2025-02-12 12:28:19 -08:00
Yury Semikhatsky 148af21540
chore(bidi): implement getOwnerFrame (#34755) 2025-02-12 10:53:03 -08:00
Pavel Feldman f54478a23e
chore: move utils that are user in server to server/utils (3) (#34739) 2025-02-12 09:34:01 -08:00
Yury Semikhatsky 703ca9f851
Revert "chore(bidi): use fractional coordinates for pointerAction (#3… (#34753) 2025-02-12 09:00:01 -08:00
Dmitry Gozman 8eb816b363
fix(trace): do not save trace on failure after success in test+hooks (#34724) 2025-02-12 15:41:16 +00:00
Simon Knott 1ad7aad5fb
fix: prompt should mention contents (#34746) 2025-02-12 15:44:45 +01:00
Adam Gastineau 0501f8c132
chore(html-report): make scrollbar gutter stable (#34732) 2025-02-12 05:55:36 -08:00
Simon Knott b7785e1662
feat(runner): enable gitCommitInfo by default on GH Actions (#34743) 2025-02-12 14:51:00 +01:00
Dmitry Gozman 3e976e9f10
chore(chromium): re-enable PlzDedicatedWorker feature (#34400) 2025-02-12 13:22:35 +00:00
Max Schmitt c052627138
fix: allow empty userDataDir (#34730) 2025-02-12 14:21:57 +01:00
Pavel Feldman bd74fc4964
chore: move utils that are user in server to server/utils (2) (#34736) 2025-02-11 17:19:27 -08:00
Pavel Feldman 25a168fae5
chore: move utils that are user in server to server/utils (1) (#34734) 2025-02-11 15:40:41 -08:00
Yury Semikhatsky 934600b24b
test: reenable 2 screenshot tests on wk mac (#34735) 2025-02-11 15:21:15 -08:00
Yury Semikhatsky 6004865ee5
chore(tests): respect BIDIPATH in browsertype-connect.spec.ts (#34733) 2025-02-11 14:03:16 -08:00
JacksonLei123 5a76b17c87
feat: add failOnStatusCode option to API request context (#34346) 2025-02-11 13:23:11 -08:00
Pavel Feldman 46b048f018
chore: vendor stack utils (#34719) 2025-02-11 12:53:08 -08:00
Yury Semikhatsky 8e51be9069
chore(bidi): use fractional coordinates for pointerAction (#34675) 2025-02-11 12:09:48 -08:00
Simon Knott 8ed2f4319e
chore: add pageSnapshot option (#34669) 2025-02-11 11:04:57 -08:00
Udaiveer Pradhan d2e7e8acdb
fix(ui-mode): Watch mode button doesn't show active when test selected (#34581) 2025-02-11 10:32:39 -08:00
Playwright Service 3ae39166c2
feat(chromium-tip-of-tree): roll to r1302 (#34726)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-11 17:40:52 +01:00
Max Schmitt 416c9b3368
fix: allow relative userDataDir (#34710) 2025-02-11 17:40:00 +01:00
Pavel Feldman 72cd6f06aa
chore: prework for web ws connection (#34718) 2025-02-11 08:28:28 -08:00
Adam Gastineau 91f46bb5d0
chore(html-report): clean up git metadata display (#34713) 2025-02-11 05:16:46 -08:00
dependabot[bot] 6704370c3f
chore(deps-dev): bump esbuild from 0.18.20 to 0.25.0 (#34721)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-11 12:27:59 +01:00
Simon Knott 2eb6cbe357
chore: improve fix test prompt (#34709) 2025-02-11 08:40:46 +01:00
Pavel Feldman 51f944d16a
chore: extract pipe->connection code (#34689) 2025-02-10 15:04:33 -08:00
Pavel Feldman 2718ce7cbf
chore: short-cut localUtils usage in JS client (#34690) 2025-02-10 14:19:58 -08:00
Adam Gastineau ad6444e14c
chore(test): perform action to guarantee URL updates (#34714) 2025-02-10 12:57:25 -08:00
Adam Gastineau aeed1f5909
fix(runner): display no projects error across all test modes (#34676) 2025-02-10 12:52:53 -08:00
Playwright Service 71c7f465a0
feat(webkit): roll to r2132 (#34697) 2025-02-10 11:36:45 -08:00
Pavel Feldman 5d500dde22
chore: introduce platform for client (1) (#34683) 2025-02-10 10:22:32 -08:00
Simon Knott 0672f1ce67
feat(ui): "fix with ai" button (#34708) 2025-02-10 17:47:27 +01:00
Simon Knott 2f8d448dbb
feat(html): "copy prompt" button (#34670) 2025-02-10 15:02:19 +01:00
Max Schmitt 703e077f4b
chore: fix recorder tsconfig linting (#34704) 2025-02-10 13:23:04 +01:00
Priyanshi Saxena 76b7b52c34
docs: source section doc updated (#34627)
Co-authored-by: ankursaxena17 <32309836+ankursaxena17@users.noreply.github.com>
2025-02-10 12:22:53 +00:00
Max Schmitt 967c4f5e3b
chore: fix Locator type issues (#34705) 2025-02-10 13:05:17 +01:00
Playwright Service 4c8af0128f
feat(chromium): roll to r1158 (#34702)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2025-02-10 12:33:37 +01:00
Playwright Service a95186a373
feat(firefox): roll to r1475 (#34695)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-10 09:12:50 +01:00
Playwright Service f11ed1beab
feat(chromium-tip-of-tree): roll to r1301 (#34696)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-10 09:12:07 +01:00
Pavel Feldman 88c01434c6
chore: fix locator type check (#34682) 2025-02-07 14:53:28 -08:00
Pavel Feldman d5d47f2b6e
chore: organize imports in packages (#34681) 2025-02-07 14:44:00 -08:00
Pavel Feldman 4a7f6a6ef0
chore: organize imports in playwright-core (#34680) 2025-02-07 13:54:01 -08:00
Adam Gastineau 4bc8cf0d47
feat(recorder): display primary page URL in recorder title (#34637) 2025-02-07 12:05:04 -08:00
Simon Knott 893e7bbf3b
chore: add _browserTypes helpers to playwright (#34611) 2025-02-07 15:43:08 +01:00
Max Schmitt 9e433060fe
test: keep testing React 18 (#34671) 2025-02-07 12:24:53 +01:00
Simon Knott bc8d6ce344
feat: provide commit diff to HTML reporter (#34653)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2025-02-07 10:39:08 +01:00
Simon Knott fd24521f2e
chore: add page snapshot on test end (#34573)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
2025-02-07 09:02:20 +01:00
Pavel Feldman 7da3be4a1a
chrome: update eslint 9 (#34666) 2025-02-06 19:48:27 -08:00
Henrik Skupin 6fddefde81
chore(bidi): pointerMove action needs to floor fractional values for x and y position (#34191) 2025-02-06 16:17:50 -08:00
Max Schmitt 8accb0ad1b
test: change ct-vite projects to type: module (#34662) 2025-02-06 23:11:06 +01:00
Yury Semikhatsky 34d9d4fc33
chore(html-report): show run duration for each retry (#34647) 2025-02-06 13:30:25 -08:00
Yury Semikhatsky 3d3154de86
chore(tracing): look up snapshot resources only in the same context (#34645) 2025-02-06 12:38:51 -08:00
Max Schmitt 427d7a22ea
Revert "chore: tidy up headless-shell hacks (#33967)" (#34659) 2025-02-06 19:17:20 +01:00
Simon Knott 902e83fe87
fix: allow opt out from IndexedDB in storagestate (#34650) 2025-02-06 16:40:14 +01:00
Dmitry Gozman 8d751cfe50
fix(fetch): filter out undefined params (#34654) 2025-02-06 15:16:45 +00:00
Simon Knott 365f411548
test(storageState): IndexedDB with keyPath (#34648) 2025-02-06 12:39:19 +01:00
Simon Knott 2b5493219b
chore: document typed array limitation (#34649) 2025-02-06 12:39:07 +01:00
Simon Knott 1c7436ec2f
chore: remove dead code (#34651) 2025-02-06 11:39:10 +01:00
Simon Knott 7aac96d780
chore: add encoded versions of IndexedDB key/value (#34630) 2025-02-06 09:48:30 +01:00
Pavel Feldman 11e1b8f30a
chore: fallback to the original code after babel transform (#34635) 2025-02-05 14:03:31 -08:00
Yury Semikhatsky 7f09ba7fa4
feat: step.attach() (#34614) 2025-02-05 12:27:44 -08:00
Pavel Feldman 4b64c47a25
chore: use explicit matcher call context (#34620) 2025-02-05 10:57:33 -08:00
Playwright Service 25ef2f1344
feat(webkit): roll to r2130 (#34631) 2025-02-05 09:05:10 -08:00
Yury Semikhatsky f1a392f844
chore: do not store empty step.attachments[] in trace (#34579) 2025-02-05 08:30:03 -08:00
Adam Gastineau cb208836b5
fix: display error when project is not found (#34577) 2025-02-05 06:58:02 -08:00
Adam Gastineau 50f22f13a4
docs: document config executing multiple times (#34576) 2025-02-05 06:10:32 -08:00
Simon Knott 311625b891
feat: recreate IndexedDB in storagestate (#34591) 2025-02-05 15:01:53 +01:00
Yury Semikhatsky fb3e8ed114
fix: reset APIRequestContext network trace between chunks (#34616) 2025-02-05 08:00:04 +00:00
Playwright Service 11913e6f39
feat(webkit): roll to r2127 (#34599) 2025-02-04 17:03:14 -08:00
Atsushi Kawamura (atzz/a2c) dc14490f13
docs: remove unnecessary hyphens in CircleCI's sharding example (#34609) 2025-02-04 15:38:39 +00:00
Playwright Service 50e1a8b55b
feat(chromium-tip-of-tree): roll to r1300 (#34610)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-04 16:06:35 +01:00
Simon Knott 5d82567346
feat: emulate prefers-contrast (#34494) 2025-02-04 11:15:51 +01:00
Max Schmitt 96d4dc1eda
docs: add backlink from WebSocket to WebSockeRoute (#34600) 2025-02-03 19:42:38 +01:00
Yury Semikhatsky f11f4a8477
docs: breaking changes in java 1.50 (#34601) 2025-02-03 09:39:33 -08:00
Adam Gastineau 5996a0df0a
Revert "Revert "chore(docs): clarify connection method via BrowserType.connect (#34560)" (#34594)" (#34595) 2025-02-03 06:21:00 -08:00
Max Schmitt 340834195b
docs: v1.50 release notes for ports (#34592)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Simon Knott <info@simonknott.de>
2025-02-03 15:17:19 +01:00
Max Schmitt 3d5f85d7e4
Revert "chore(docs): clarify connection method via BrowserType.connect (#34560)" (#34594) 2025-02-03 14:24:33 +01:00
Simon Knott ebf82b0854
test: ensure that attachments are available in onStepEnd (#34590) 2025-02-03 13:54:28 +01:00
Max Schmitt 4e2d82e6c2
test: add test for color input click behavior (#34156) 2025-02-03 13:30:54 +01:00
Playwright Service 36478f250a
feat(firefox): roll to r1474 (#34587)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-03 12:04:12 +01:00
Playwright Service 162182b714
feat(firefox-beta): roll to r1470 (#34589)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-02-03 10:47:37 +01:00
Yury Semikhatsky cd7f3b6e65
devops: validate js code snippets in flint (#34580) 2025-01-31 16:52:55 -08:00
Yury Semikhatsky a1451c75f8
feat: conditional step.skip() (#34578) 2025-01-31 15:45:57 -08:00
Yury Semikhatsky da12af24c2
chore: harden trace file regex (#34563) 2025-01-31 15:34:53 -08:00
Playwright Service 399ba91150
feat(chromium-tip-of-tree): roll to r1299 (#34569)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-31 19:35:12 +01:00
Playwright Service 64f8689a81
feat(chromium): roll to r1157 (#34571)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-31 13:15:40 +01:00
GeneratorX16 4fa1d39c80
fix: Reverse Lumia 550 and Lumia 550 Landscape viewports (#34548) 2025-01-30 13:57:43 -08:00
Adam Gastineau 1936cfa6c3
chore(docs): clarify connection method via BrowserType.connect (#34560) 2025-01-30 12:31:59 -08:00
Debbie O'Brien d288fbcc41
docs: Improve aria snapshots documentation clarity and examples (#34509)
Signed-off-by: Debbie O'Brien <debs-obrien@users.noreply.github.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2025-01-30 20:07:48 +00:00
Dmitry Gozman ab62ef2dbb
fix(toMatchAriaSnapshot): fail test run when updating missing snapshot (#34556) 2025-01-30 19:18:07 +00:00
Adam Gastineau 5afb04b62e
fix(ui): add proper CORS header for loading traces in HMR mode (#34558) 2025-01-30 09:20:43 -08:00
Max Schmitt 833c729eb0
docs: roll follow-ups for .NET and Python (#34550) 2025-01-30 12:06:56 +01:00
Pavel Feldman eff5cd6dbb
fix(aria): disregard text area textContent (#34544) 2025-01-29 16:06:07 -08:00
Pavel Feldman 4b5b326478
chore: do not show steps in line reporter without tty (#34529) 2025-01-29 12:41:09 -08:00
Adam Gastineau f15171bcf0
fix(ui): don't display "Timed Out" when executing action (#34541) 2025-01-29 12:39:05 -08:00
Dmitry Gozman ba650161a8
feat: per-assertion snapshot path template in config (#34537) 2025-01-29 18:47:20 +00:00
Playwright Service b552637ee0
feat(chromium-tip-of-tree): roll to r1298 (#34540)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-29 18:29:23 +01:00
Dmitry Gozman 24f06ec1bf
feat(html report): show metadata (#34517) 2025-01-29 16:22:50 +00:00
Max Schmitt 6c2c90203e
devops(gha): allow workflow_dispatch in roll browser script (#34531)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2025-01-29 17:16:50 +01:00
Dmitry Gozman 7d8265e610
Revert "Reapply "fix(har timing): record connect timing for proxied connections" (#32855) (#33003)" (#34535) 2025-01-29 14:51:31 +00:00
Andrey Lushnikov b419527aab
fix(firefox): disable fetch keep-alive for now before a proper fix (#34530) 2025-01-29 09:50:32 +00:00
Pavel Feldman 931b9f28cd
fix(codegen): attribute navigation to press/fill (#34528) 2025-01-28 17:59:16 -08:00
Pavel Feldman 391e9c4de0
fix(recorder): do not reset inspect highlight on inactivity (#34526) 2025-01-28 16:00:28 -08:00
Pavel Feldman 7060cd1bf7
chore: allow repetative application of rebaselines in the same session (#34524) 2025-01-28 14:37:47 -08:00
Pavel Feldman 7fd0c3e254
fix: follow the pseudo attr value in firefox computed style (#34525) 2025-01-28 14:37:04 -08:00
Danilo Akamine b27945d045
docs: remove duplicate reference (#34513) 2025-01-28 22:33:04 +01:00
Dmitry Gozman 7fc252fffc
test: fetch request through socks proxy over ipv4 (#34522) 2025-01-28 17:05:12 +00:00
Adam Gastineau 63f96efbe0
feat(trace-viewer): display query string in network tab (#34505) 2025-01-28 05:19:30 -08:00
Vitaliy Potapov 61d595ae48
feat: add new config prop populateGitInfo (#34329)
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
2025-01-28 07:54:31 +00:00
Pavel Feldman cea5dad686
chore: remove eslint-plugin-internal-playwright (#34510) 2025-01-27 20:13:27 -08:00
Pavel Feldman ab01dccf9d
chore: clean up tool example (#34512) 2025-01-27 20:13:18 -08:00
Pavel Feldman 2c0576ea76
chore: mark tools package as private (#34511) 2025-01-27 15:32:45 -08:00
Pavel Feldman bd2fdd0f20
chore: land experimental tools (#34503) 2025-01-27 14:49:38 -08:00
ReaZzy eaaef29dbd
fix: add validations to --shard cli parameter (#34463) (#34479) 2025-01-27 14:31:14 -08:00
Henrik Skupin d63907fc5b
chore(bidi): Disable some external services for Firefox (#34492) 2025-01-27 13:17:03 -08:00
Max Schmitt bc1a8c2191
test: add test for fetch with keepalive: true on Firefox (#34498) 2025-01-27 15:39:59 +01:00
Max Schmitt 8d716b28a1
chore(bidi): use full test title in CSV expectations (#34496) 2025-01-27 14:17:47 +01:00
Max Schmitt 52580d640d
Revert "fix(ci): Prevent workflows from automatically running on forks (#34408)" (#34488) 2025-01-27 14:03:19 +01:00
Dmitry Gozman 640e6a8aa7
chore: remove unused headers (#34491) 2025-01-27 09:58:19 +00:00
Pavel Feldman 245f4b5b86
fix: allow changed to be passed in config (#34473) 2025-01-24 15:42:58 -08:00
Playwright Service 3d9a9d2405
feat(firefox): roll to r1472 (#34455) 2025-01-24 15:17:14 -08:00
Playwright Service c815d090bc
feat(firefox-beta): roll to r1468 (#34454) 2025-01-24 15:16:18 -08:00
Alexandra Borovova 2afe287a81
Add canonical screenshots for firefox with webdriver bidi for screenshot element tests (#34289) 2025-01-24 15:15:24 -08:00
Yury Semikhatsky fb145d5ebd
test: do not check deprecated KeyboardEvent.keyCode property (#34472) 2025-01-24 15:09:39 -08:00
Adam Gastineau fccb2b0784
chore: fix codegen SIGINT test (#34468) 2025-01-24 14:21:42 -08:00
Henrik Skupin 9d91d7a1e9
chore(firefox): Don't upgrade HTTP requests to HTTPS (#34465) 2025-01-24 13:36:23 -08:00
Adam Gastineau b39c29d096
docs: remove toMatchAriaSnapshot path feature (#34471) 2025-01-24 21:16:58 +01:00
Yury Semikhatsky dcff914040
chore(bidi): make browserType.connect work (#34461) 2025-01-24 09:09:57 -08:00
Adam Gastineau c44590aa5b
chore: disable popover test on Darwin 13.7 WebKit (#34466) 2025-01-24 08:27:06 -08:00
Playwright Service bbd55587e4
feat(chromium): roll to r1156 (#34464)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-24 15:40:46 +01:00
Adam Gastineau f65dc0cee4
feat: toHaveURL predicate matcher (#34413) 2025-01-24 06:00:17 -08:00
Yury Semikhatsky f11768436a
chore: revert inadvertent test change (#34459) 2025-01-23 12:12:53 -08:00
Pavel Feldman bfb79990da
docs: issue guide (#34457) 2025-01-23 12:12:13 -08:00
Pavel Feldman 039f513744
docs: auto generate evaluate usage docs (#34458) 2025-01-23 12:11:54 -08:00
Playwright Service 04c03b998a
feat(webkit): roll to r2125 (#34453)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-23 18:37:42 +01:00
Playwright Service 2cf6153d9f
feat(chromium-tip-of-tree): roll to r1297 (#34451)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-23 16:40:15 +01:00
Debbie O'Brien 900382540a
docs: add --update-source-method option for snapshot updates in test-cli-js (#34448) 2025-01-23 14:17:23 +00:00
Dmitry Gozman ab3b4b8cd0
fix(test runner): respect updateSourceMethod from the config (#34442) 2025-01-23 12:11:26 +00:00
Playwright Service a9609ed6f2
chore(driver): roll driver to recent Node.js LTS version (#34440) 2025-01-23 11:30:12 +01:00
Henrik Skupin 34cb35859a
chore(bidi): simplify launcher tests for Firefox (#34405) 2025-01-22 13:06:24 -08:00
Adam Gastineau a06600aee9
chore: roll stable-test-runner to: 1.50.0-beta-1737557690000 (#34433) 2025-01-22 12:46:25 -08:00
Adam Gastineau a121f85ce9
chore: update browser patches to 2e93a0b95 (#34426) 2025-01-22 09:56:34 -08:00
Adam Gastineau 256dc47833
docs: switch gracefulShutdown to primarily mention SIGTERM and add Docker comment (#34430) 2025-01-22 09:49:34 -08:00
Max Schmitt 85e41f5b65
docs: update README for flakiness dashboard function update (#34424) 2025-01-22 16:33:19 +01:00
Adam Gastineau b75fc4c547
fix(ci): Prevent workflows from automatically running on forks (#34408) 2025-01-22 07:05:34 -08:00
Adam Gastineau 7e97e01505
docs: release notes for v1.50 js (#34380) 2025-01-22 06:20:24 -08:00
Adam Gastineau 49b3bbb920
docs: release notes for v1.50 js (#34380) 2025-01-22 06:17:54 -08:00
dependabot[bot] a689e534ac
chore(deps): bump vite from 5.4.6 to 5.4.14 (#34420)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-22 14:23:05 +01:00
dependabot[bot] 214b103b46
chore(deps-dev): bump undici from 5.28.4 to 5.28.5 (#34419)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-22 15:52:00 +03:00
Dmitry Gozman cf90c0f122
fix(aria snapshot): make rebase work when options are specified (#34409) 2025-01-22 07:53:53 +00:00
Playwright Service cf3bcd7d4a
feat(chromium-tip-of-tree): roll to r1296 (#34414)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-22 08:21:47 +03:00
Tasawar Hussain 6234c3b15e
docs: update test-fixtures-js.md (#34399) 2025-01-21 13:50:33 -08:00
Dmitry Gozman 888feb06be
fix(list reporter): do not break after output without trailing eol (#34410) 2025-01-21 18:30:09 +00:00
Dmitry Gozman 333e994e7d
fix(step.skip): show a skipped indicator in UI mode (#34407) 2025-01-21 18:28:41 +00:00
Dmitry Gozman e20b6d1617
feat(chromium-tip-of-tree): roll to r1295 (#34372) 2025-01-20 16:28:41 +00:00
Simon Knott 99fb188cb4
chore: move attachment link back to tree item, make it flash yellow (#34353) 2025-01-20 09:06:01 +01:00
Max Schmitt 86768b9ebc
test: add test for consistent hyphen rendering in headless/headed (#34159) 2025-01-18 19:04:56 +03:00
Yury Semikhatsky 372d4196d7
chore: step timeout improvements (#34386) 2025-01-17 21:15:47 -08:00
Pavel Feldman 9970446f51
chore: remove toMatchAriaSnapshot.path (#34379) 2025-01-17 14:35:15 -08:00
Henrik Skupin d082805ea9
chore(bidi): disable thottling of background tabs in Firefox (#34381) 2025-01-17 14:29:26 -08:00
Adam Gastineau 3c160df06a
chore: mark v1.51.0-next (#34382) 2025-01-17 12:34:59 -08:00
Pavel Feldman 1b21ec9cd8
chore: remove --save-trace codegen option (#34362) 2025-01-17 10:17:49 -08:00
Pavel Feldman b339d457e3
chore: dogfood jest-style aria snapshots (#34365) 2025-01-17 10:17:26 -08:00
Dmitry Gozman 07bcbcd1b4
feat(chromium): roll to r1155 (#34371) 2025-01-17 10:45:58 +00:00
Yury Semikhatsky 40b92eaf2a
docs: remove toMatchAriaSnapshot({path}) from language ports (#34363) 2025-01-16 16:56:13 -08:00
Yury Semikhatsky 5438814975
chore: do not fall back to previous LTS release deps for new Ubuntu LTS (#34360) 2025-01-16 15:20:40 -08:00
Yury Semikhatsky 587e778a5a
Revert "feat(aria): extend toHaveAccessibleName() to accept an array … (#34361) 2025-01-16 15:04:56 -08:00
Pavel Feldman 3cf0461a1a
chore: fix the scrollable locator tab (#34358) 2025-01-16 13:20:20 -08:00
Adam Gastineau 84bbc5fd35
feat(trace-viewer): Render context string for most actions (#34292) 2025-01-16 11:48:34 -08:00
Dmitry Gozman be6caed8df
chore: remove expectZone (#34312) 2025-01-16 18:53:32 +00:00
Pavel Feldman 08af3a2f06
chore: do not cache highlight agressively (#34349) 2025-01-16 08:27:48 -08:00
Yury Semikhatsky 00bb17751b
chore: delete recorder in traceviewer experiment (#34347) 2025-01-15 17:37:33 -08:00
Yury Semikhatsky 8d39c44b69
docs: improve toHaveClass paramter description (#34345) 2025-01-15 14:38:34 -08:00
Yury Semikhatsky 07f425434d
chore(bidi): support ControlOrMeta key (#34341) 2025-01-15 13:23:44 -08:00
Yury Semikhatsky 224d7bf847
fix(docker): install gpg on slim images (#34340) 2025-01-15 12:03:19 -08:00
Dmitry Gozman 4d55d3039a
chore: better error message when CSS selector fails to parse (#34331) 2025-01-15 11:34:51 -08:00
Dmitry Gozman aeec0c0e36
fix(test runner): esm loader in old Node versions (#34330) 2025-01-15 14:45:10 +00:00
Yury Semikhatsky 275f334b58
chore(step): remove step.fail and step.fixme, add step.skip (#34326) 2025-01-14 17:43:47 -08:00
Julian Descottes 0869195ba4
chore(bidi): Stop dividing BiDi network event timings by 1000 (#34324) 2025-01-14 15:27:49 -08:00
Yury Semikhatsky 8699d3b9c5
test(bidi): create inspected page before initializing recorder (#34323) 2025-01-14 14:57:42 -08:00
Pavel Feldman b0f0a2951a
docs: improve aria overload docs (#34319) 2025-01-13 18:25:57 -08:00
Pavel Feldman ad365c3bc3
chore: include child nodes when parsing snapshot (#34318) 2025-01-13 18:25:41 -08:00
Pavel Feldman fe96104ce2
docs: clarify updateSourceMethod (#34314) 2025-01-13 18:25:32 -08:00
Rui Figueira 9a9d22af44
feat(codegen): include framePath in jsonl format (#34310) 2025-01-13 17:32:26 -08:00
Playwright Service dfe80bb888
feat(firefox): roll to r1471 (#34309) 2025-01-13 17:26:26 -08:00
Yury Semikhatsky 2b2e84971f
chore(bidi): use original key name when computing bidi value (#34317) 2025-01-13 17:22:00 -08:00
Playwright Service d2e7ad38d5
feat(firefox-beta): roll to r1467 (#34303) 2025-01-13 13:58:34 -08:00
Julian Descottes 454b6f938d
test(bidi): Update browserName used for har file tests when using bidi (#34313) 2025-01-13 13:56:00 -08:00
Playwright Service 6b73ec6092
feat(webkit): roll to r2123 (#34260) 2025-01-13 13:53:18 -08:00
Zachary Blackwood f74a4d55cd
Fix typo "fore" -> "for" (#34315) 2025-01-13 12:30:19 -08:00
Simon Knott a33659f2a8
chore: move attachments link to step body (#34196) 2025-01-13 10:07:54 +01:00
Playwright Service 19c935cde7
feat(firefox): roll to r1470 (#34304) 2025-01-13 09:05:33 +03:00
Pavel Feldman 6179b5b1d7
chore: allow matching aria snapshot in trace viewer (#34302) 2025-01-11 10:14:21 -08:00
Pavel Feldman 0c8a6b80fb
chore: consolidate aria parser in isomorphic bundle (#34298) 2025-01-10 15:32:35 -08:00
Andrey Lushnikov 4bb464197f
test: unflake a few trace-viewer tests (#34299) 2025-01-10 14:57:50 -08:00
Andrey Lushnikov 2cd5003062
test: fix "should capture navigation" flakiness on firefox-headed (#34291) 2025-01-10 13:51:28 -08:00
Yury Semikhatsky 423005a7ab
chore(bidi): create parent dir for report.csv (#34294) 2025-01-10 13:43:43 -08:00
Dmitry Gozman f0a3a15e93
chore: explicitly reset apiZone instead of everything (#34265) 2025-01-10 20:15:05 +00:00
Dmitry Gozman 1f2eb499d2
fix(aria snapshots): normalize whitespace (#34285) 2025-01-10 19:31:47 +00:00
Julian Descottes 4f3a5e2133
chore(bidi): Fix handling of cookie headers in network.continueRequest (#34277) 2025-01-10 11:06:26 -08:00
Julian Descottes ca94291ab7
chore(bidi): Handle headers properly in BiDi network.continueRequest (#34268) 2025-01-10 10:15:38 -08:00
Henrik Skupin 89172175d6
Improve WebDriver BiDi key codes (#34286) 2025-01-10 09:19:28 -08:00
Adam Gastineau a2e2dfd446
feat: Enable snapshots for most remaining public commands (#34072) 2025-01-10 05:04:44 -08:00
Dmitry Gozman b32d546159
test: attempt to unflake vscode highlight tests (#34267) 2025-01-10 09:52:39 +00:00
Simon Knott 75d2661497
docs: fix android launchBrowser.pkg option (#34262) 2025-01-10 10:51:29 +01:00
Pavel Feldman 13bdd3c92f
feat(toBeChecked): allow indeterminate expectation (#34269) 2025-01-09 18:18:15 -08:00
Yury Semikhatsky 37c2569eb2
fix(inspector): do not start recording by default (#34276) 2025-01-09 14:58:41 -08:00
Yury Semikhatsky cd9d02faf9
chore: remove setAutoCloseAllowed (#34273) 2025-01-09 14:16:01 -08:00
Yury Semikhatsky 201fc48cf0
chore(bidi): write custom expectations only for timing out tests (#34270) 2025-01-09 11:10:14 -08:00
Alexandra Borovova c465e21161
chore(bidi): add missing canonical screenshots for tests running with Firefox and WebDriver BiDi (#34257) 2025-01-09 10:36:59 -08:00
Adam Gastineau 01ba528904
fix: Prepare CI to properly run Electron on ubuntu-latest (24.04) (#34238) 2025-01-09 06:34:59 -08:00
Playwright Service 9b58e4a93a
chore(driver): roll driver to recent Node.js LTS version (#34261) 2025-01-09 13:53:41 +03:00
Ben Hovinga 9f32c858e0
Fix typo (#34225) 2025-01-08 11:22:41 -08:00
Yury Semikhatsky edfbab2a79
fix: dispatch touch events in webkit (#34250) 2025-01-08 11:06:30 -08:00
Dmitry Gozman 7ee7e018fa
chore: update chrome extensions doc and tests (#34236) 2025-01-08 17:24:29 +00:00
JustasM d6d5944797
fix(ui): fix washed out dropdown colors in dark mode (#34186) 2025-01-08 06:14:22 -08:00
Adam Gastineau ada68cd6f0
feat(trace-viewer): Add setting for display canvas content in snapshots (#34010) 2025-01-08 05:08:00 -08:00
Yury Semikhatsky ff9242104b
docs: touch events emulation guide (#34201) 2025-01-07 16:47:00 -08:00
Yury Semikhatsky 6fb6282a9d
chore(bidi): propertly dispatch ControlRight key event (#34246) 2025-01-07 16:46:44 -08:00
Yury Semikhatsky 809225503c
docs: remove note about DataTrander limited availability (#34243) 2025-01-07 15:42:10 -08:00
Pavel Feldman 0d34369fc0
chore: include actual value in the elementState (#34245) 2025-01-07 15:31:18 -08:00
Yury Semikhatsky 0008816ee3
test: reenable "return empty content there is no iframe src" in cr and ff (#34241) 2025-01-07 11:49:14 -08:00
Pavel Feldman 7923d35e32
fix(retarget): do not unconditionally retarget to enclosing label (#34229) 2025-01-07 11:15:00 -08:00
Pavel Feldman 9514f0fb9d
fix(aria): escape leading dash in property values (#34227) 2025-01-07 11:14:45 -08:00
Playwright Service d2af88c1fe
feat(chromium-tip-of-tree): roll to r1293 (#34234)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-07 21:43:05 +03:00
Dmitry Gozman 63329a3471
chore: remove dependency from library on expectZone, straighten csi handling (#34211) 2025-01-07 13:30:04 +00:00
Simon Knott 527505e67b
docs: be more precise in what versions of Node.js are supported (#34231)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2025-01-07 14:23:27 +01:00
Yury Semikhatsky ec79f28ffe
chore(bidi): keep custom expectations only for timing out tests (#34228) 2025-01-06 17:36:49 -08:00
Yury Semikhatsky a9e6b51108
chore(bidi): implement query selector all ($$) method (#34226) 2025-01-06 16:37:11 -08:00
Pavel Feldman 4e8c83055f
chore: split output clients by capabilities and base dir (#34135) 2025-01-06 11:03:35 -08:00
Dmitry Gozman eeca68ba97
test: unflake some cookie tests in msedge (#34217) 2025-01-05 18:19:28 +00:00
Yury Semikhatsky 5a22475ea8
chore(bidi): fix signals tests (#34209) 2025-01-03 12:37:28 -08:00
Yury Semikhatsky 8b45ea6f2f
chore: properly initialize Touch arguments in TouchEvent (#34200) 2025-01-03 12:16:01 -08:00
Yury Semikhatsky dca95ba609
fix(bidi): set initial frame url from creation event (#34198) 2025-01-03 10:39:32 -08:00
Simon Knott 6bdd2694ee
feat(webserver): customize shutdown with new gracefulShutdown option (#34130)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2025-01-03 11:34:34 +01:00
Simon Knott 04a3574f80
feat(reporter): report TestStep#attachments (#34037) 2025-01-02 17:48:59 +01:00
Max Schmitt 175f05cafc
test: increase page-event-crash timeout (#34178) 2025-01-02 16:04:51 +01:00
David Gahnassia acdd666d95
docs(test-fixtures): removed redundancy (#34185) 2025-01-02 06:17:22 +01:00
Playwright Service 546b7b702c
feat(webkit): roll to r2122 (#34180)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-02 06:16:46 +01:00
Playwright Service da52befea0
feat(chromium-tip-of-tree): roll to r1291 (#34182)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2025-01-02 06:16:04 +01:00
Yury Semikhatsky 7769010e6e
chore(bidi): mark test expected to timeout as fixme (#34176) 2024-12-31 13:18:25 -08:00
Max Schmitt b2cbe7f2ec
chore(roll): roll WebKit to r2121 (#34179) 2024-12-31 11:22:10 +01:00
Henrik Skupin 940230d43a
Use csvReporter as well when running BiDi tests locally (#34167) 2024-12-30 14:48:22 -08:00
Dmitry Gozman cd32d1b08c
fix(test runner): apply --last-failed after sharding (#34166) 2024-12-30 18:45:49 +00:00
Henrik Skupin cab2bc4e2a
Combine file name and test name to a single identifier for CSV export of BiDi results (#34172) 2024-12-30 10:06:00 -08:00
Dmitry Gozman 9dbe63636d
fix(routeWebSocket): should work after context reuse (#34165) 2024-12-30 10:00:10 -08:00
Max Schmitt 4819747c85
chore: keep linting generated files (#34150) 2024-12-27 10:00:59 +00:00
Pengoose 7f141b2c42
feat: expect(locator).toHaveAccessibleErrorMessage (#33904) 2024-12-27 09:54:16 +00:00
Playwright Service 3ec8ee7a9b
feat(chromium): roll to r1153 (#34118)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-27 08:51:06 +01:00
Playwright Service 08644003d2
feat(chromium-tip-of-tree): roll to r1290 (#34144)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-26 22:27:56 +01:00
Gautier Ben Aïm 1c8e6f0921
docs: fixed typo (#34129) 2024-12-21 18:59:50 +01:00
Yury Semikhatsky 03cf7429a4
chore(bidi): upload report.csv to azure (#34122) 2024-12-20 18:04:21 -08:00
Yury Semikhatsky cce8e8e0e5
chore(html): use api prefix to qualify public types (#34121) 2024-12-20 14:03:38 -08:00
Evan Cahill c89e213eff
docs: Use locator.first() in locator.or examples (#34106) 2024-12-20 13:23:01 -08:00
Yury Semikhatsky a74c488b25
docs: document --no-shell option (#34120) 2024-12-20 10:24:10 -08:00
Adam Gastineau 875436855e
chore(lint): Ensure EOL newlines (#34117) 2024-12-20 09:17:09 -08:00
Yury Semikhatsky 3bc72eb841
chore(bidi): disambiguate report.csv artifact name (#34110) 2024-12-20 08:58:15 -08:00
Adam Gastineau a8dfdc8ac5
chore(ui): Dialog UI for upcoming settings menu (#34058) 2024-12-20 08:43:12 -08:00
Adam Gastineau 05472f5ef6
feat: Add time information to Call and Network tabs in Trace Viewer (#33935) 2024-12-20 05:01:16 -08:00
Yury Semikhatsky cc98166aaa
chore(bidi): add csv report (#34107) 2024-12-19 22:59:24 -08:00
Pavel Feldman a94952b87f
chore: make ts happy with zip import (#34108) 2024-12-19 22:59:05 -08:00
Pavel Feldman 04e670c909
fix(locator): do not explode locators (#34104) 2024-12-19 15:34:54 -08:00
Max Schmitt b7a1cfd786
chore: move winldd to CDN (#34078) 2024-12-19 23:29:21 +01:00
Yury Semikhatsky d7a52347e5
chore(bidi): skip tooling tests (#34105) 2024-12-19 14:04:05 -08:00
Max Schmitt 61ce37cd53
test: use checkInstalledSoftwareOnDisk for itest (#34103) 2024-12-19 22:09:49 +01:00
Pavel Feldman 6505a3e34c
fix(yaml): escape to disambiguate yaml arrays (#34096) 2024-12-19 12:46:54 -08:00
Pavel Feldman ec1d3313c3
Revert "feat(fetch/network): add generic to json method" (#34098) 2024-12-19 12:46:39 -08:00
Henrik Skupin edd789780a
WebDriver BiDi: "browsingContext.captureScreenshot" accepts quality from 0 to 1 (#34097) 2024-12-19 12:26:01 -08:00
Adam Gastineau 7d3a188530
chore(ui): Clean up settings component for shared uses (#34090) 2024-12-19 12:14:58 -08:00
Max Schmitt 613f6c5f95
devops: run bidi tests for bidi changes (#34099) 2024-12-19 21:03:33 +01:00
Yury Semikhatsky 8e721fac85
chore(bidi): no retries on CI (#34080) 2024-12-19 11:55:10 -08:00
Volodymyr Momot 94ffbcb9c5
feat(fetch/network): add generic to json method (#34091) 2024-12-19 10:36:02 -08:00
Playwright Service 9c14cccc24
feat(chromium-tip-of-tree): roll to r1288 (#34092) 2024-12-19 17:17:29 +01:00
Playwright Service a239ab3048
feat(ffmpeg): roll to r1011 (#34079)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-19 10:17:42 +01:00
Max Schmitt 4c9a116aff
chore: move protocol to d.ts types only files (#34077) 2024-12-19 00:23:35 +01:00
Playwright Service bddbf8950e
feat(webkit): roll to r2120 (#34069) 2024-12-19 00:08:27 +01:00
Rui Figueira c2d057ba23
chore: add url option to routeFromHAR call if codegen launched with --save-har-glob (#34048) 2024-12-18 13:34:06 -08:00
Dmitry Gozman d9e5ca06bf
fix(remote server): allow local paths in extension mode (#34051) 2024-12-18 13:32:16 -08:00
Max Schmitt f7c99ee6e3
chore: update CDN endpoints (#34061) 2024-12-18 22:26:01 +01:00
Andrew Goldis c57155e30c
docs: explain globalSetup caveats for reporters (#34063) 2024-12-18 13:16:03 -08:00
Simon Knott 67bc484d8b
chore(ui): test that UI works behind proxy, take 2 (#33771) 2024-12-18 12:39:08 +01:00
Simon Knott 443b2a2bbc
fix: don't rely on requestAnimationFrame (#34065) 2024-12-18 11:41:48 +01:00
Playwright Service c9ae644e5f
feat(chromium-tip-of-tree): roll to r1287 (#34057) 2024-12-17 22:31:01 +01:00
Max Schmitt 52b2548612
chore: no @web imports from @web package (#34055) 2024-12-17 20:27:21 +01:00
Max Schmitt 43e46d63dd
chore: use recorder/html types for exported shared types (#34056) 2024-12-17 20:26:56 +01:00
Yury Semikhatsky 7ed60ccf7f
feat(test): step.fail and step.fixme modifiers (#34042) 2024-12-17 11:17:22 -08:00
Adam Gastineau aabbcbf41d
fix(trace-viewer): Fix network log flicker #33929 (#34036) 2024-12-17 05:24:22 -08:00
Yury Semikhatsky 7ce1a540bc
chore(bidi): skip only timeouts on CI (#34041) 2024-12-16 15:28:21 -08:00
Pavel Feldman 94d0fc780d
chore: make visible=false work (#34040) 2024-12-16 14:14:51 -08:00
Yury Semikhatsky b58a4762f4
docs: improve note on browser.close() behavior (#34039) 2024-12-16 13:52:17 -08:00
Yury Semikhatsky 76bb01d77c
chore: rephrase suggestion for slow test files (#34012) 2024-12-16 13:35:19 -08:00
Dmitry Gozman d4b2c966cf
fix(codegen): fallback to iframe[name/src] when failed to generate selector (#34030) 2024-12-16 17:37:53 +00:00
Simon Knott 512cb36c9b
feat(html): link from attachment step to attachment (#33267) 2024-12-16 15:25:32 +01:00
Adam Gastineau 6270918f67
docs: Moved Trace Viewer running instructions to the top of the page (#33956) 2024-12-16 05:18:54 -08:00
Dmitry Gozman aa1fe61cc9
fix(list reporter): do not print step location instead of test location (#34022) 2024-12-16 10:15:52 +00:00
Dmitry Gozman f713d3adaf
chore: simplify page initialization logic across browser types (#34002) 2024-12-14 20:15:58 +00:00
Pavel Feldman 1e4239f48d
chore: allow selecting update source type via test server (#34014) 2024-12-14 10:58:16 -08:00
Pavel Feldman 3a10c32d8a
chore: report highlight parse error to debug controller (#33984) 2024-12-13 16:10:59 -08:00
Pavel Feldman cbc809edc7
chore: recorder toolbar polish (#33983) 2024-12-13 16:10:45 -08:00
Yury Semikhatsky 369f4b76b3
fix: throw an error when object reference chain is to long to serialize (#34008) 2024-12-13 13:38:26 -08:00
Max Schmitt 91d4b82dfb
fix(pwt): custom fixture titles in UI Mode / HTML Reporter (#34009) 2024-12-13 12:31:38 -08:00
Max Schmitt e995ecd9b8
chore: add docs for experimental 'watch mode' (#33988) 2024-12-13 10:38:27 -08:00
Dmitry Gozman 258881bea1
test: fix should not transform external for newer Node versions (#34006) 2024-12-13 17:17:49 +00:00
Rui Figueira c700a8405c
feat(trace-viewer): render iframe canvas in trace viewer (#33809) 2024-12-13 16:28:06 +01:00
Max Schmitt 65688d623e
chore: update TypeScript to v5.7 (#33994) 2024-12-13 04:52:04 -08:00
Simon Knott dd36de7809
fix(html): encode all stdio attachments (#33950) 2024-12-13 12:01:20 +01:00
Playwright Service b0cec5b351
feat(chromium-tip-of-tree): roll to r1286 (#33991)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-12 19:22:48 -08:00
Playwright Service dd41930e72
feat(webkit): roll to r2119 (#33992)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-12 19:22:27 -08:00
Yury Semikhatsky 0034c6b984
fix: parse locator with empty options (#33990) 2024-12-12 17:49:48 -08:00
Yury Semikhatsky 76d46d478f
fix: text-is() should ignore comments (#33980) 2024-12-12 17:49:31 -08:00
Max Schmitt e4413f2089
docs: add docs for 'run-server' (#33989) 2024-12-12 16:23:13 -08:00
Max Schmitt 21c456b2c1
chore: remove vite default scripts in package.json's (#33986) 2024-12-12 15:37:53 -08:00
Max Schmitt 16a1552e74
chore: remove 'npx playwright debug' (#33987) 2024-12-12 15:25:13 -08:00
Max Schmitt 38758c0596
chore: tidy up headless-shell hacks (#33967) 2024-12-12 12:23:03 -08:00
Jozef Izso a4add6ebaf
Fix typo in AndroidServerLauncherImpl class when on device was found (#33973) 2024-12-12 11:12:58 -08:00
Max Schmitt aca00a4ab0
chore: update README/device descriptors after roll (#33982) 2024-12-12 11:06:14 -08:00
Playwright Service fc9f5a6f28
feat(chromium): roll to r1152 (#33977) 2024-12-12 09:04:17 -08:00
Pavel Feldman 29fd2df124
chore: send aria snapshot to the debug controller (#33969) 2024-12-12 08:21:53 -08:00
Pavel Feldman 0e2b984287
chore: prioritize role over label and placeholder (#33970) 2024-12-12 08:21:00 -08:00
Max Schmitt e3629dc1df
fix: validate ffmpeg on context creation (#33903) 2024-12-11 23:07:03 -08:00
Max Schmitt 081f455ee9
fix: headless-shell follow-up (#33968) 2024-12-11 19:28:39 -08:00
Max Schmitt 8d57b7543e
chore: introduce chromium-tip-of-tree-headless-shell (#33964) 2024-12-11 18:11:33 -08:00
Max Schmitt 217a0e9003
chore: bump https/socks proxy-agent (#33965) 2024-12-11 17:52:52 -08:00
Max Schmitt b12ede48fc
test: fix html-reporter tests after #33754 (#33966) 2024-12-11 17:49:16 -08:00
Bill Collins e4e562cac5
fix(types): Global JSX namespace is deprecated (#33949) 2024-12-11 17:09:19 -08:00
Yury Semikhatsky 22e58aa084
docs: clarify --only-shell option (#33961) 2024-12-11 13:06:48 -08:00
Yury Semikhatsky 9e683d798f
docs: clarify setDefaultTimeout with 0 value (#33959) 2024-12-11 13:06:37 -08:00
Yury Semikhatsky 856704a176
chore: run server with headless shell for connect tests (#33957) 2024-12-11 10:35:14 -08:00
Playwright Service 5a1bae0f19
feat(chromium-tip-of-tree): roll to r1285 (#33945)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-11 10:30:17 -08:00
Simon Knott 6d424875e3
fix(html): remove filter clear button (#33754) 2024-12-11 15:16:21 +01:00
Simon Knott ed2be67e47
chore(trace viewer): support HMR (#33609) 2024-12-11 13:25:52 +01:00
Adam Gastineau a14d9750b3
docs: #33837 Clarify that clock.install must precede clock operations (#33901) 2024-12-10 16:18:41 -08:00
Pavel Feldman 4bcf505e19
chore: prefer generating role with text to css with text (#33942) 2024-12-10 16:03:33 -08:00
Playwright Service 4745f64bc0
feat(webkit): roll to r2118 (#33938) 2024-12-10 14:29:30 -08:00
Pavel Feldman acf1107220
chore: ignore checkbox/radio value in aria (#33941) 2024-12-10 14:04:18 -08:00
Yury Semikhatsky 599b09c1c0
docs: sharding per file with multiple projects (#33939) 2024-12-10 14:02:13 -08:00
Yury Semikhatsky 54c595c7ed
docs: add examples for clock.install() followed by pauseAt() (#33937) 2024-12-10 11:50:51 -08:00
Pavel Feldman a25bda6950
chore: allow storing aria snapshots in files (#33919) 2024-12-10 11:45:16 -08:00
Max Schmitt 200e868b63
chore: bump nanoid to 3.3.8 (#33936) 2024-12-10 11:19:36 -08:00
jinohkang-theori 27060a0f65
fix(connect): disable context takeover in websocket transport (#33811) 2024-12-09 18:07:00 -08:00
yangsisi d029b03d9f
fix(defineConfig): fix type issue passing custom property in the seco… (#33774)
Signed-off-by: yangsisi <13655750+yangsisi0422@users.noreply.github.com>
2024-12-09 09:20:47 -08:00
Dmitry Gozman 0937d2f7b9
fix(types): update types for test.extend (#33784) 2024-12-09 08:59:01 -08:00
Playwright Service dfa24462db
feat(webkit): roll to r2117 (#33902) 2024-12-06 16:43:25 -08:00
Playwright Service 2a1a9c9452
feat(webkit): roll to r2116 (#33897)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-06 15:38:51 -08:00
Simon Knott 4914f34a83
fix(recorder): allow clearing when recording is disabled (#33821) 2024-12-06 10:17:06 -08:00
Adam Gastineau a56a5cabbd
docs: clarify use of comments in contributions (#33896) 2024-12-06 10:09:35 -08:00
Yury Semikhatsky 733f9a2926
chore: pdf generation now works in headed mode too (#33879) 2024-12-05 17:53:31 -08:00
Simon Knott 993546c1bc
chore: r1284 fixup (#33883) 2024-12-05 16:22:52 -08:00
Simon Knott f6f6a6225c
docs: locale defaults to en-us (#33840) 2024-12-05 15:44:41 -08:00
Playwright Service ee8208beda
feat(chromium-tip-of-tree): roll to r1284 (#33876)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-05 09:34:30 -08:00
Playwright Service b86725bb98
feat(chromium): roll to r1151 (#33873)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-05 09:34:16 -08:00
Playwright Service b941359fce
chore(driver): roll driver to recent Node.js LTS version (#33870) 2024-12-05 06:08:44 -08:00
Dmitry Gozman be78e9e11f
fix: do not stall waiting for pending navigations after beforeunload dismiss (#33834) 2024-12-03 15:55:45 -08:00
Playwright Service abf6916909
feat(webkit): roll to r2113 (#33807) 2024-12-03 10:05:51 -08:00
Dmitry Gozman a7f2868594
fix(codegen): do not reset current tool upon clearing highlight (#33822) 2024-12-03 09:25:14 -08:00
Playwright Service e4211ee3ac
feat(chromium-tip-of-tree): roll to r1283 (#33845)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-12-03 07:14:05 -08:00
Max Schmitt 9b5f7f77b2
docs(network): add proxy back-ref to api docs (#33839) 2024-12-02 16:20:44 -08:00
Dmitry Gozman 4e33ade287
docs: fix codegen --viewport option examples (#33816) 2024-11-29 06:13:53 -08:00
Tasawar Hussain b456ac5f8c
docs: update ci.md (#33815)
Signed-off-by: Tasawar Hussain <31658686+tasawar-hussain@users.noreply.github.com>
2024-11-29 03:36:50 -08:00
Dmitry Gozman b5bd543cc6
test: skip 'should not auto play audio' with frozen time (#33799) 2024-11-28 06:36:49 -08:00
Playwright Service fd25f3ab85
feat(chromium-tip-of-tree): roll to r1282 (#33798)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-28 14:43:45 +01:00
Simon Knott 4fb6c4ed4c
fix(trace): in indexTree check isVisible before adding to result (#33797) 2024-11-28 14:04:34 +01:00
Dmitry Gozman a84488edaa
fix(aria): escape even more yaml (#33793) 2024-11-28 03:21:52 -08:00
Playwright Service ff6c283af5
feat(webkit): roll to r2112 (#33778)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-27 16:53:22 +01:00
Segev Finer f3ae940684
fix(ct-vue): Upgrade plugin-vue to be compatible with Vite 5 (#33758) 2024-11-26 17:42:36 +01:00
Max Schmitt 84df6e3297
docs(python): add note about async fixtures (#33760) 2024-11-26 16:23:19 +01:00
Playwright Service b9c923f87c
feat(chromium-tip-of-tree): roll to r1281 (#33769)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-26 14:26:35 +01:00
Playwright Service 3fd5174b9f
feat(webkit): roll to r2111 (#33759)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-25 22:35:34 +01:00
Dmitry Gozman 39285c4667
docs: update extensions doc for new headless (#33753) 2024-11-25 01:13:20 -08:00
Max Schmitt 9d92b0d3ec
docs(dotnet): add docs for xUnit (#33742) 2024-11-25 10:09:35 +01:00
Max Schmitt e0e4da8ead
docs(cli): fix docs rendering (#33751) 2024-11-24 14:50:12 +01:00
Pavel Feldman 0d9bcd45d5
chore: pin typescript while vue-tsc is broken (#33746) 2024-11-23 11:48:34 -08:00
Pavel Feldman 35dd3dd104
chore: use diff for snapshot delta (#33739) 2024-11-23 11:39:04 -08:00
Pavel Feldman 971b5da741
chore: introduce update-source-method (#33738) 2024-11-22 18:30:35 -08:00
Pavel Feldman 66d9f3acbe
chore: introduce update-snapshots=changed (#33735) 2024-11-22 17:41:31 -08:00
Yury Semikhatsky 66f709663e
fix(webkit): do not auto play audio without user gesture (#33734) 2024-11-22 14:53:29 -08:00
Dmitry Gozman 4696dd8682
fix(chromium): race between oopif attach and context clear (#33729) 2024-11-22 09:35:35 -08:00
Dmitry Gozman 7e09aa07de
feat(trace): preserve the open state of popovers (#33728) 2024-11-22 09:35:19 -08:00
Pavel Feldman 5f85a4a419
chore: add config markers / overwrite mode (#33723) 2024-11-22 09:12:58 -08:00
Dmitry Gozman f123f7ac69
fix: isEditable/toBeEditable throw for elements that cannot be editable/readonly (#33713) 2024-11-22 03:40:43 -08:00
Max Schmitt b7e47dc0bd
docs(test-runners): restructure .NET test-runners doc (#33727) 2024-11-22 12:35:14 +01:00
Playwright Service b32fdade16
feat(chromium): roll to r1150 (#33718)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-22 12:05:16 +01:00
Pavel Feldman e0f0996bbd
chore: climb file tree to git root for patches (#33722) 2024-11-21 17:32:07 -08:00
Pavel Feldman 605df0be8f
chore: add more info about snapshot testing (#33721) 2024-11-21 16:11:01 -08:00
Max Schmitt 5da0b94357
feat(webkit): roll to r2108 (#33710)
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
2024-11-21 14:42:21 -08:00
Playwright Service c2a8375ef2
feat(chromium-tip-of-tree): roll to r1280 (#33719)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-21 22:36:39 +01:00
Max Schmitt 92436518ff
docs(python): add LocatorAssertions.NotToMatchAriaSnapshot (#33712) 2024-11-21 15:53:37 +01:00
Max Schmitt 77d82b8b07
chore: remove dead code in urlMatches (#33714) 2024-11-21 15:53:28 +01:00
Dmitry Gozman d3ffdefd50
docs: release notes for languages v1.49 (#33706) 2024-11-21 05:45:00 -08:00
Max Schmitt f43b86fea4
devops: delete .devcontainer/devcontainer.json (#33709)
Signed-off-by: Max Schmitt <max@schmitt.mx>
2024-11-21 12:22:45 +01:00
Simon Knott fc19e6e7b4
fix(test): export TestDetailsAnnotation (#33698) 2024-11-20 17:28:56 +01:00
Max Schmitt 6a32589330
test: update 'should work for canvas' test expectation (#33685) 2024-11-20 17:13:07 +01:00
Simon Knott 89f4d4ce4f
chore(html): hmr report should survive reload (#33696) 2024-11-20 16:35:39 +01:00
Simon Knott 81e28a8854
docs(aria): add demo video (#33668) 2024-11-20 15:36:51 +01:00
Simon Knott bfd64ac11b
docs: add video for 1.49 (#33693) 2024-11-20 15:36:38 +01:00
Dmitry Gozman 94776ad18a
docs: note that permissions list may change (#33690) 2024-11-20 06:08:34 -08:00
Josh Kelley 1afb56ee1b
docs: add docs for 1.49.0's new "chromium" option (#33680) 2024-11-20 01:19:39 -08:00
Simon Knott 1d3605d1fc
feat(trace viewer): add "Copy as Playwright Request" button (#33298) 2024-11-20 10:16:43 +01:00
Simon Knott f1ddd379f3
fix(html): don't conflate file names (#33600) 2024-11-20 10:16:33 +01:00
Dmitry Gozman 50c8fbf750
fix(ui mode): do not render anonymous describe (#33675) 2024-11-20 00:51:31 -08:00
Simon Knott ae10d56836
docs(fixtures): add rules of thumb for fixture usage (#33472) 2024-11-20 09:06:54 +01:00
Max Schmitt 402bb4ccf8
devops: update GitHub Actions via dependabot (#33683) 2024-11-20 08:13:35 +01:00
Pavel Feldman b40889d1a8
chore: escape more yaml values (#33686) 2024-11-19 17:09:49 -08:00
Max Schmitt 7f7b440c72
devops: deduplicate redudant information in client side changes issue (#33666) 2024-11-19 19:06:20 +01:00
Playwright Service aa0ac04d06
feat(webkit): roll to r2105 (#33679)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-19 17:56:50 +01:00
Playwright Service 4d4fa69a0a
feat(chromium-tip-of-tree): roll to r1279 (#33676)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-19 16:49:59 +01:00
Simon Knott 4979ce2b5d
chore(html): Reveal elements with Anchor abstraction (#33537) 2024-11-19 16:40:02 +01:00
Simon Knott 8c1002a98b
fix(sw): fix UI mode on codespaces by not passing server (#33664) 2024-11-19 16:39:47 +01:00
Dmitry Gozman 6e19bc341f
fix(role): ignore invalid aria-labelledby attributes (#33667) 2024-11-19 03:56:16 -08:00
Max Schmitt ecf6f27159
fix: dark-mode in UI Mode (#33662) 2024-11-19 10:29:05 +01:00
Simon Knott e047f6bc07
chore(build): typo in trace-viewer output dir (#33661) 2024-11-19 10:02:41 +01:00
Yury Semikhatsky dc91bab6cc
chore: fix npm audit (#33659) 2024-11-18 16:24:54 -08:00
Yury Semikhatsky 6d71805f4a
fix: do not send favicon request to network when interception is on (#33639) 2024-11-18 11:01:39 -08:00
Max Schmitt 150092438f
chore(recorder): support HMR (#33637) 2024-11-18 18:23:29 +01:00
Simon Knott acd862c6c9
chore(trace): remove embedded trace viewer (#33651) 2024-11-18 16:57:53 +01:00
Max Schmitt 0b312248cd
test: add test for crash on label with input file (#33654) 2024-11-18 16:56:59 +01:00
Max Schmitt 72c532846f
chore(roll): roll Firefox Beta to r1466 (#33653) 2024-11-18 16:56:49 +01:00
aairiian 7f054ef8c6
feat(aria): extend toHaveAccessibleName() to accept an array of expected accessible names (#33277) 2024-11-18 07:46:47 -08:00
Simon Knott 3fa33ca81f
chore(build): fix bug where sw changes aren't copied in watch mode (#33579) 2024-11-18 16:04:12 +01:00
Simon Knott 5e8b469c1c
fix(test): hide response.* calls from reports (#33620) 2024-11-18 13:59:40 +01:00
Max Schmitt d7d8ab62a2
chore: roll stable-test-runner to 1.49.0-beta-1731772650000 (#33648) 2024-11-18 10:21:48 +01:00
Max Schmitt 6fce5620e0
fix(ui-mode): use onChange instead of onClick for <input type='checkbox' (#33636) 2024-11-18 10:21:28 +01:00
Rui Figueira 82c77a5e9e
fix(ui-mode): prevent websocket connection leaks on reload (#33643) 2024-11-18 01:03:21 -08:00
Pavel Feldman 46321e5bf2
chore: clear highlight when performing action (#33638) 2024-11-16 07:56:33 -08:00
Pavel Feldman a98021499f
chore: add cm placeholder text (#33635) 2024-11-15 16:19:35 -08:00
Jean-François Greffier 508021362d
fix minor typos in "Getting Started" (#33613) 2024-11-15 14:45:54 -08:00
Max Schmitt 37ce53945e
fix(ui-mode): fix issue when updating state while rendering (#33634) 2024-11-15 23:45:25 +01:00
Rui Figueira c36b5a6059
fix: ensure toMatchAriaSnapshot is properly commented in javascript c… (#33593) 2024-11-15 14:44:27 -08:00
Pavel Feldman d127255881
chore: add AriaSnapshot internal type (#33631) 2024-11-15 13:48:43 -08:00
Pavel Feldman 44cd1d03cc
chore: highlight edited locator while recording (#33632) 2024-11-15 13:43:00 -08:00
Max Schmitt b91f609b14
chore: fix react attribute casing in TestErrorView (#33633) 2024-11-15 22:25:26 +01:00
Yury Semikhatsky e24780f825
chore: unshift shortest whitespace prefix only (#33618) 2024-11-15 12:47:25 -08:00
Dmitry Gozman 77dee44984
fix(rebase): do not apply multiple rebaselines to the same assertion (#33629) 2024-11-15 09:08:31 -08:00
Max Schmitt c81504c5d6
fix(codegen): document.documentElement is null on early navigation (#33627) 2024-11-15 17:14:49 +01:00
Amaechi Hope e61cea597a
docs(dotnet): fix assertion snippets (#33622) 2024-11-15 15:02:40 +01:00
Dmitry Gozman 2aa9e11a7f
fix(aria): normalize whitespace in toMatchAccessible{Name,Description} (#33619) 2024-11-15 02:49:03 -08:00
Dmitry Gozman eaf3536014
fix(trace): afterAll hook should not break tracing with reused context (#33616) 2024-11-14 13:24:02 -08:00
Yury Semikhatsky f5477d9051
docs: add ariaSnapshot.timeout for language ports (#33614) 2024-11-14 12:23:42 -08:00
Max Schmitt b3e5daff2b
cherry-pick(#33606): feat(chromium): roll to r1149 (#33612) 2024-11-14 19:40:46 +01:00
Playwright Service b61b3a5a13
feat(chromium): roll to r1149 (#33606) 2024-11-14 16:39:24 +01:00
Playwright Service 5e579cc29c
feat(chromium-tip-of-tree): roll to r1278 (#33608)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-14 16:38:56 +01:00
Max Schmitt 358fad45cd
chore: add ESRP CDN for browser downloads (#33585) 2024-11-14 16:19:42 +01:00
Max Schmitt b8f824ca6b
chore: throw if protocol can't get generated when rolling (#33607) 2024-11-14 16:12:07 +01:00
Simon Knott 445ff73c6e
chore(trace viewer): decouple test server from web server (#33542) 2024-11-14 15:27:33 +01:00
Simon Knott 25c039401d
fix(canvas snapshots): position mismatch in headless mode (#33575) 2024-11-14 15:27:09 +01:00
Dmitry Gozman 80ce205d81
docs: update docs about headless shell (#33604) 2024-11-14 05:38:16 -08:00
Dmitry Gozman 31a2b7bbdc
chore: update headless shell treatment (#33603) 2024-11-14 04:20:44 -08:00
Dmitry Gozman 9f59dbdc57
fix(merge): update error.cause location (#33583) 2024-11-14 01:15:21 -08:00
Simon Knott dc93c8a05b
chore(release): alternative headless mode release notes (#33578)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
2024-11-14 08:40:51 +01:00
Pavel Feldman 4817483ff2
chore: allow highlighting aria template from extension (#33594) 2024-11-13 21:33:38 -08:00
Yury Semikhatsky a8af7cc435
chore: remove macOS <=12 checks (#33591) 2024-11-13 17:21:21 -08:00
Yury Semikhatsky 5203c780ae
feat: step timeout option (#33560) 2024-11-13 11:17:54 -08:00
Max Schmitt eab6447ad9
test: add 'should show errors with causes in the error tab' (#33577) 2024-11-13 17:32:32 +01:00
Simon Knott da7639b737
chore(build): empty out dir (#33576) 2024-11-13 13:08:50 +01:00
Max Schmitt cd41404b05
chore: mark v1.50.0-next (#33572) 2024-11-13 12:51:54 +01:00
Max Schmitt d1ae5f6ac4
chore: update browser patches to bb81b1c60 (#33573) 2024-11-13 12:34:49 +01:00
Max Schmitt 382d98760c
chore: update WebKit version to 18.2 (#33570) 2024-11-13 12:33:45 +01:00
Max Schmitt e535b3aa5f
docs(best-practises): add note about saving browser downloads (#33568) 2024-11-13 12:11:12 +01:00
Dmitry Gozman 099dd80806
fix(recorder): align apiName with the real one (#33567) 2024-11-13 03:06:34 -08:00
Dmitry Gozman 88082b417a
chore: release notes for v1.49 js (#33565) 2024-11-13 03:04:43 -08:00
Dmitry Gozman f54d3f44c2
chore: download and launch chromium-headless-shell for headless chromium (#33454) 2024-11-13 02:52:28 -08:00
Pavel Feldman d685763c49
chore: use diff instead of diffmatchpatch (#33550) 2024-11-12 14:46:29 -08:00
Max Schmitt 0aa8da8035
test: fix csharp har tests on Windows (#33556) 2024-11-12 14:42:07 +01:00
Playwright Service 55b81a83e8
feat(chromium-tip-of-tree): roll to r1277 (#33555)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-12 13:55:12 +01:00
Dmitry Gozman 33f9c8279c
chore: more aria snapshot fixes (#33534) 2024-11-12 02:26:54 -08:00
Simon Knott 114884335d
chore(html): support HMR for local dev (#33511) 2024-11-12 11:11:50 +01:00
Pavel Feldman 1b65f26f02
chore: apply rebaselines in a task (#33549) 2024-11-11 21:15:05 -08:00
Pengoose a501232bf0
fix(expect): adjust normalization for regex values in toHaveText matcher (#33533) 2024-11-11 17:19:04 -08:00
Pavel Feldman e534fba60f
chore: render recorder placeholders (#33548) 2024-11-11 16:38:02 -08:00
Max Schmitt d8a98a2bf5
test: fix flaky page.pause() tests end up stalling (#33544) 2024-11-11 22:19:58 +01:00
Yury Semikhatsky e691ca7fbf
fix(codegen): generate routeFromHAR for --save-har option (#33480) 2024-11-11 11:59:20 -08:00
Yury Semikhatsky e3ed9fa7c3
chore: drop support for solid component testing (#33523) 2024-11-11 10:26:50 -08:00
Pavel Feldman 649e0e0235
chore: nicer cm widgets for aria (#33524) 2024-11-11 09:40:50 -08:00
Max Schmitt 5a8b49910a
fix(ct): msw interception after msw v2.6.4 release (#33536) 2024-11-11 11:37:29 +01:00
Max Schmitt d5ebe285c1
fix(transform): allow import attributes always (#33527) 2024-11-11 10:26:13 +01:00
Pavel Feldman 503f74da90
chore: allow editing aria template in recorder (tests) (#33522) 2024-11-08 17:18:51 -08:00
Dmitry Gozman c29f573243
fix(aria snapshot): assorted fixes (#33512) 2024-11-08 10:25:05 -08:00
Yury Semikhatsky 9c6c58f8ce
docs: note about screenshot environment (#33501) 2024-11-08 08:33:04 -08:00
Pavel Feldman b021b58379
chore: allow editing aria template in recorder (#33482) 2024-11-08 07:43:01 -08:00
Dmitry Gozman d561ba7b86
fix(chromium-headless-shell): fallback to chromium when running headed (#33490) 2024-11-08 07:04:41 -08:00
Simon Knott f7a388dcb4
chore: HMR for Trace Viewer build script changes (#33291) 2024-11-08 15:08:58 +01:00
Playwright Service 93b7b6e279
feat(webkit): roll to r2104 (#33500)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-08 13:23:20 +01:00
Playwright Service 7073f80879
feat(chromium-tip-of-tree): roll to r1276 (#33494)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-07 16:43:58 +01:00
Playwright Service 910ecdf556
feat(chromium): roll to r1148 (#33491)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-07 14:51:33 +01:00
Dmitry Gozman 67e8defbe9
docs: update tracing.group docs (#33487) 2024-11-07 03:57:18 -08:00
Dmitry Gozman 43e4ba9f2f
fix(click): better compensate for integer click coordinates in firefox (#33467) 2024-11-07 00:01:00 -08:00
Yury Semikhatsky 50775698ae
fix: parent step for API calls inside waitForEvent callback (#33409) 2024-11-06 17:35:16 -08:00
Yury Semikhatsky 523e50088a
test: do not rely on http://localhost2 dns resolution failure (#33479) 2024-11-06 14:20:38 -08:00
Pavel Feldman 3f8bd36a3a
fix(html): align prev/next with the group title (#33462) 2024-11-06 08:31:55 -08:00
Pavel Feldman 2f8a14c6e2
test: cover more aria escaping edge cases (#33463) 2024-11-06 08:31:32 -08:00
Simon Knott 8c4738ab1a
Revert "chore(trace viewer): always format trace location as URL, not file path" (#33476) 2024-11-06 17:17:59 +01:00
Simon Knott 0d92737a07
chore(web): replace static ID with React.useId (#33474) 2024-11-06 14:42:48 +01:00
Simon Knott f554f42b82
feat(trace viewer): link from attach action to attachment tab (#33265) 2024-11-06 10:22:15 +01:00
Pavel Feldman d4ad520a9b
chore: fix more aria escaping edge cases (#33460) 2024-11-05 16:22:02 -08:00
Pavel Feldman 9d94ad152e
chore: dedupe tags in base reporter title (#33461) 2024-11-05 16:18:10 -08:00
Pavel Feldman a655b0bfb3
chrome: aria api review (#33458) 2024-11-05 15:23:38 -08:00
Dmitry Gozman 697d7a40b1
fix(routeWebSocket): make it work with http(s) baseURL (#33457) 2024-11-05 11:46:05 -08:00
Max Schmitt 1003f3429c
chore: roll chromium-headless-shell to r1147 (#33455) 2024-11-05 15:19:39 +01:00
Max Schmitt c96245dde7
docs(aria-snapshot): fix markdown rendering / langs (#33453) 2024-11-05 15:04:26 +01:00
Dmitry Gozman 9b2ca93a50
chore: followup to tracing.group (#33450) 2024-11-05 04:45:54 -08:00
Playwright Service 96a7f49b72
feat(chromium-tip-of-tree): roll to r1275 (#33451)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-05 13:30:24 +01:00
René fa10bcd5a3
feat(tracing) Adding groups to trace via pw-api (#33081)
Signed-off-by: René <snooz@posteo.de>
Signed-off-by: René <41592183+Snooz82@users.noreply.github.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-11-05 03:45:37 -08:00
Playwright Service da4614ea7c
feat(firefox): roll to r1466 (#33448)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-05 11:56:03 +01:00
Max Schmitt 9a668aeab3
fix(websocket): pass through underlying WebSocket protocol (#33446) 2024-11-05 11:13:33 +01:00
Simon Knott 8e140a4873
fix(global setup): simplify ordering (#33444) 2024-11-05 10:36:29 +01:00
Max Schmitt ba6386e0ae
fix(download): fix second browser download of channels (#33429) 2024-11-05 10:34:00 +01:00
Simon Knott 26a7dd4dd4
chore(reporter): add another surrogate pair test case (#33428) 2024-11-05 07:55:17 +01:00
Pavel Feldman 58b1f322ab
docs: iterate over aria docs (2) (#33440) 2024-11-04 19:24:54 -08:00
Pavel Feldman ec8161cb0a
docs: iterate over aria docs (#33439) 2024-11-04 17:52:53 -08:00
Yury Semikhatsky 513c57536a
chore: relax checks when installing channels on unsupported platforms (#33436) 2024-11-04 16:53:13 -08:00
Pavel Feldman f138c30915
chore: improve aria template error reporting (#33438) 2024-11-04 15:33:09 -08:00
Yury Semikhatsky 36a975c30b
chore: override host platform with env variable (#33434) 2024-11-04 14:14:24 -08:00
Playwright Service ab22f81922
feat(chromium): roll to r1147 (#33430)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-04 21:38:43 +01:00
Pavel Feldman 8b49d568de
docs: start adding the aria snapshot documentation (#33407) 2024-11-04 10:53:46 -08:00
Playwright Service cf137845df
feat(webkit): roll to r2103 (#33431)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-04 19:39:18 +01:00
Simon Knott cb0171e571
chore(expect): clarify message() for custom matchers (#33321) 2024-11-04 16:58:20 +01:00
Simon Knott edf1eb154d
chore(trace viewer): always format trace location as URL, not file path (#33344) 2024-11-04 16:25:44 +01:00
Max Schmitt 4560686427
test: re-add headless-new fixme's (#33426) 2024-11-04 16:18:36 +01:00
Simon Knott b148ce1ad1
fix(debug controller): highlight selectors in iframe (#33273) 2024-11-04 14:41:06 +01:00
Max Schmitt 96a29b69eb
feat(chromium-tip-of-tree): roll to r1274 (#33423) 2024-11-04 14:23:17 +01:00
Dmitry Gozman 82f6c15e6a
feat(chromium): switch to headless=new by default (#33262)
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-11-04 12:56:00 +01:00
Max Schmitt 76ffc2374c
devops: increase heap size to 8 GB for merge report workflow (#33422)
Signed-off-by: Max Schmitt <max@schmitt.mx>
2024-11-04 11:42:50 +01:00
Playwright Service abcd1ff201
feat(webkit): roll to r2102 (#33408)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-02 01:10:15 +01:00
Pavel Feldman 1d4650cea2
chore(snapshot): support aria-owns (#33404) 2024-11-01 15:25:38 -07:00
Playwright Service 3cd753f6bb
feat(webkit): roll to r2101 (#33401)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-01 21:43:33 +01:00
Pavel Feldman 80bd246543
chore: use React.useId for a11y (#33402) 2024-11-01 13:38:16 -07:00
Pavel Feldman c76f004ec3
chore: move compress call log to server (#33399) 2024-11-01 13:38:01 -07:00
Pavel Feldman fc0ce7046b
chore: perform e2e rebase test (#33390) 2024-11-01 12:25:05 -07:00
Max Schmitt 3b4b8f9e49
docs(python): add snippet for new_context fixture (#33392) 2024-11-01 17:50:34 +01:00
Playwright Service 18453f3889
feat(webkit): roll to r2100 (#33395) 2024-11-01 17:45:58 +01:00
Max Schmitt 33593c5f06
docs(browsers): add note for Python about channels in launch() (#33396) 2024-11-01 17:45:07 +01:00
Yury Semikhatsky c95feccce4
chore: support reverse in ansi2html, drop ansi-to-html (#33389) 2024-10-31 21:42:06 -07:00
Pavel Feldman 26c2049d5a
chore: treat input value as text in templates (#33388) 2024-10-31 20:41:52 -07:00
Pavel Feldman 135ed28740
chore: more yaml escaping tests (#33387) 2024-10-31 17:14:11 -07:00
Playwright Service dcf85edcb7
feat(chromium): roll to r1146 (#33380)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-11-01 00:50:09 +01:00
Pavel Feldman c462e29e73
chore(aria): generate single patch for all baselines (#33384) 2024-10-31 15:34:17 -07:00
Playwright Service 69404561f9
feat(webkit): roll to r2099 (#33385)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-31 21:34:01 +01:00
Pavel Feldman a2e901e080
chore: generate aria name regex when possible (#33373) 2024-10-31 11:25:38 -07:00
Pavel Feldman 676f014b5f
chore: use objects for string aria template notes (#33371) 2024-10-30 17:25:51 -07:00
Pavel Feldman a43b99368e
chore: support aria snapshots in tsx (#33369) 2024-10-30 17:25:30 -07:00
Playwright Service 81e7d9fa25
feat(webkit): roll to r2098 (#33366) 2024-10-30 21:55:44 +01:00
Max Schmitt 1342e7f6b6
Revert "chore: add Devuan OS fallback to Debian (#32990)" (#33365) 2024-10-30 21:28:16 +01:00
Max Schmitt 512645463e
test: rebase headless-shell/--headless=new/Edge tests (#33350) 2024-10-30 15:12:05 +01:00
Simon Knott 64802fc284
fix(line reporter): wrap chinese characters correctly (#33322) 2024-10-30 13:29:31 +01:00
Pavel Feldman 6f5c7b4358
feat(html): render prev/next test buttons (#33356) 2024-10-29 18:29:07 -07:00
Pavel Feldman 9ce401d44a
chore: suggest aria snapshots w/ regex (#33334) 2024-10-29 16:19:08 -07:00
Max Schmitt 3b1883444d
chore: bump Docker Node.js to 22 (#33348) 2024-10-29 21:04:13 +01:00
Denis LE 7a1739792f
docs(best-practices): improve wording (#33342) 2024-10-29 16:27:14 +01:00
Playwright Service 53ff35cbc4
chore(driver): roll driver to recent Node.js LTS version (#33349)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-29 16:14:22 +01:00
Simon Knott 0221f15f4f
chore(control-or-meta): mention in docs (#33338) 2024-10-29 10:07:59 +01:00
Playwright Service 0df801d632
feat(webkit): roll to r2097 (#33336)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-29 06:59:12 +01:00
Max Schmitt 9eb4fe5546
feat(pwt): serialize and expose Error.cause from Worker process (#32833) 2024-10-29 00:01:59 +01:00
Max Schmitt 5c0fdfed50
chore: throw when using headless-shell with headed mode (#33292) 2024-10-28 22:33:21 +01:00
Max Schmitt 19e863191c
test: use 'chrome' for UI mode tests (#33329) 2024-10-28 21:56:46 +01:00
Max Schmitt c9a93486a1
test: update macOS-15 WebKit cookie tests expectations (#33332) 2024-10-28 20:34:08 +01:00
Pavel Feldman 4b7c8d8a20
chore: use stable library along with the test runner in ttest (#33312) 2024-10-25 23:15:10 -07:00
Yury Semikhatsky 88c42f7887
chore: delete unused source-map-support code (#33306) 2024-10-25 16:20:33 -07:00
Yury Semikhatsky 0ace47e7cf
chore: revert exposed expect error details on TestError (#33310) 2024-10-25 16:20:18 -07:00
Pavel Feldman 74e5e5560f
chore: update missing snapshots by default (#33311) 2024-10-25 16:13:38 -07:00
Yury Semikhatsky c66af9c525
chore: make expect timeout field required in the protocol (#33309) 2024-10-25 15:26:41 -07:00
Yury Semikhatsky 4facda8685
chore: fix source-map type import error (#33308) 2024-10-25 13:51:08 -07:00
Yury Semikhatsky 87b896e597
chore: remove playwright-ct-vue2 (#33302) 2024-10-25 13:31:55 -07:00
Yury Semikhatsky 1e8884621a
chore: unify toHaveScreenshot error formatting (#33300) 2024-10-25 12:36:39 -07:00
Yury Semikhatsky f98531baee
chore: remove check for node < 16 (#33301) 2024-10-25 10:33:43 -07:00
DetachHead 7e00112fec
docs(python): improve the typing example with the pytest plugin (#33296) 2024-10-25 15:27:14 +02:00
Pavel Feldman 9707e97867
chore: revert #33228 - it needs a proper review (#33284) 2024-10-25 09:36:03 +02:00
Pavel Feldman ff5f1628dc
chore: allow aria snapshot rebaselines (#33256) 2024-10-24 16:49:10 -07:00
Max Schmitt a2dec8da63
fix(codegen): SIGINT handling was leading to zombie processes (#33269) 2024-10-24 19:23:19 +02:00
Playwright Service 0509eca9b6
feat(chromium): roll to r1145 (#33274)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-24 17:47:34 +02:00
Max Schmitt adc38cfd8b
test: rebaseline test expectations (#33270) 2024-10-24 16:49:35 +02:00
Dmitry Gozman 67471cb3c5
test: make a few tests headed/headless agnostic (#33268) 2024-10-24 06:03:36 -07:00
Simon Knott 3641e5984f
chore: HMR for Trace Viewer (#33228) 2024-10-24 14:34:59 +02:00
Dmitry Gozman 2e01154bb5
feat: screenshot:on-first-failure (#33266) 2024-10-24 04:41:35 -07:00
Dmitry Gozman 1950bbdc6e
test: unflake "should not leak recorders" (#33264) 2024-10-24 02:47:34 -07:00
Max Schmitt 487134fbaf
devops: add chromium-headless-shell bots (#33242) 2024-10-24 11:34:41 +02:00
Simon Knott 69f56b9f63
fix(locator generator): handle frameLocator() and locator().contentFrame() (#33208) 2024-10-24 10:52:54 +02:00
Pavel Feldman 6ae6b4865c
chore: always use TestInfoErrorImpl (impl) in @playwright/test (#33255) 2024-10-23 17:36:05 -07:00
Pavel Feldman 9a0a6cec10
chore: remove the leaf node notion (#33249) 2024-10-23 17:34:21 -07:00
Pavel Feldman 24cafbc8cb
chore: use diff_match_patch with types (#33254) 2024-10-23 16:04:37 -07:00
Pavel Feldman 8da065a2ea
Revert "chore: remove unused @babel/parser (#32654)" (#33252) 2024-10-23 12:57:15 -07:00
Dmitry Gozman 9a6e1b71a4
fix(trace viewer): make LRUCache per-trace (#33245) 2024-10-23 10:25:16 -07:00
Dmitry Gozman ec9c11f1cd
fix(trace viewer): limit the number of contexts loaded in sw (#33244) 2024-10-23 10:25:04 -07:00
Dmitry Gozman 993a6b2a2a
fix(recorder): do not leak when instantiated in snapshots (#33240) 2024-10-23 10:24:53 -07:00
Max Schmitt f1f2a7b33a
chore: warn when browser with revision override is getting installed (#33226) 2024-10-23 18:14:55 +02:00
Max Schmitt 0d12fbe002
fix: have more friendly playwright-report error when opening TV via file:// (#33239) 2024-10-23 12:19:29 +02:00
Simon Knott 3322a7f3bb
chore(trace): remove screenshot instead of snapshot code (#33225) 2024-10-23 12:17:02 +02:00
Pavel Feldman 6bfdad068c
chore: introduce accessibility tab in recorder (#33235) 2024-10-22 16:36:03 -07:00
Max Schmitt 6800fd45a2
feat(webkit): roll to r2095 (#33229) 2024-10-22 22:30:54 +02:00
Yury Semikhatsky 8ec981c394
chore: move github reporter formatting out of base (#33213) 2024-10-22 11:45:12 -07:00
Max Schmitt 29ca54eb38
chore: add headless shell builds (#33222) 2024-10-22 15:47:50 +02:00
Playwright Service c8431ca122
feat(chromium-tip-of-tree): roll to r1271 (#33224)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-22 15:47:17 +02:00
Max Schmitt 131f8b39c3
docs(vscode): outline more that global teardown needs to be executed manually (#33221) 2024-10-22 14:25:23 +02:00
Simon Knott ef84051c91
feat(tracing): clip canvas contents from screenshots (#33119) 2024-10-22 14:12:25 +02:00
Rui Figueira b194d6a1e9
fix(recorder): fix recorder injected icons (#33198) 2024-10-22 12:44:18 +02:00
Max Schmitt b275c19612
chore: update eslintignore to lint files in utils/ folders (#33218) 2024-10-22 11:52:20 +02:00
Pavel Feldman 2a3d67195d
chore: use aria snapshots in some ui mode tests (#33212) 2024-10-21 21:54:06 -07:00
Max Schmitt 0351fd9401
docs: use WebSocketFrame abstraction for Java & .NET (#33211) 2024-10-21 21:21:30 +02:00
Yury Semikhatsky aebceb345e
chore: expose expect error details on TestError (#33183) 2024-10-21 11:15:55 -07:00
Max Schmitt 36d3a6764e
docs: set minimal Ubuntu version to 22 and Debian to 12 (#33207) 2024-10-21 18:41:27 +02:00
Max Schmitt e866e3306e
devops: stop publishing Ubuntu 20.04 (#33203) 2024-10-21 17:00:10 +02:00
Playwright Service 014577d345
feat(webkit): roll to r2094 (#33188) 2024-10-21 11:33:16 +02:00
Simon Knott 40d5a1cb4a
fix(ff): resource type for image sets should be image (#33195) 2024-10-21 11:14:48 +02:00
Meir Blachman 4b187107ee
devops: fix 'client side changes bot' PR links in PRs (#33189) 2024-10-20 18:44:48 +02:00
Pavel Feldman 97d26e8166
chore: add aria attribute tests (#33184) 2024-10-19 14:23:08 -07:00
Pavel Feldman 64bf1bc107
chore: support basic aria attributes (#33182) 2024-10-18 20:18:18 -07:00
Max Schmitt b1fb4f16a7
chore: hide 'markdown' reporter (#33140) 2024-10-18 23:00:05 +02:00
Pavel Feldman 2e8e7a66cd
chore: implement tree w/o list (#33169) 2024-10-18 13:50:43 -07:00
Max Schmitt 6ea17a5d82
chore: move non-test utility workflows to ubuntu-24.04 (#33176) 2024-10-18 16:38:55 +02:00
Playwright Service 02f8acce02
feat(chromium): roll to r1143 (#33163)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-18 11:34:39 +02:00
Playwright Service 58ef9e2e5f
feat(firefox-beta): roll to r1465 (#33170)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-18 11:34:28 +02:00
Simon Knott 0d63df4875
feat(test runner): allow multiple global setups (#32955)
Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-10-18 11:03:00 +02:00
Pavel Feldman 29c84a33c3
chore: compute aria text consistently with the role accumulated text (#33157) 2024-10-17 17:06:18 -07:00
Pavel Feldman 623a8916f9
chore: implement tree w/o list (#33167) 2024-10-17 16:57:45 -07:00
Dmitry Gozman aa952c1b03
fix(html report): generate test snippets when test dir is non-root (#33162) 2024-10-17 08:33:15 -07:00
Dmitry Gozman a2a5b102ab
chore: update CONTRIBUTING.md (#33138) 2024-10-17 06:13:17 -07:00
LeoTM edb041f9e3
chore(docs): fix documentation url (#33161)
Signed-off-by: LeoTM <1881059+leotm@users.noreply.github.com>
2024-10-17 06:12:19 -07:00
LeoTM 65983b4bf8
chore(docs): remove dead link to install config (#33160)
Signed-off-by: LeoTM <1881059+leotm@users.noreply.github.com>
2024-10-17 06:08:14 -07:00
Dmitry Gozman 2d150eec25
fix: correct types for things like test.describe.only (#33142) 2024-10-17 03:34:05 -07:00
Amaechi Hope 7af9e93304
docs(api): fix code snippets for locator ele (#33153) 2024-10-17 09:11:53 +02:00
Debbie O'Brien 9848ebec5a
docs: add video to release notes (#33147) 2024-10-16 18:36:46 +02:00
Pengoose d10a5e5693
feat(testType): add support for test.fail.only method (#33001) 2024-10-16 06:47:23 -07:00
Lars Hanisch 183720b56a
fix(docker): correct Ubuntu Noble name in name template (#33133) 2024-10-16 10:15:40 +02:00
Pavel Feldman 94321fef1c
chore: implement locator.ariaSnapshot (#33125) 2024-10-15 18:47:26 -07:00
Pavel Feldman b92b855638
test: unflake ff debugger test (#33124) 2024-10-15 16:21:55 -07:00
Pavel Feldman b421bd8b0d
chore: add a basic snapshot generator test (#33123) 2024-10-15 15:21:45 -07:00
Pavel Feldman 4b1fbde2ad
chore: generate match snapshot (#33105) 2024-10-15 13:38:55 -07:00
Pavel Feldman 23b1012c70
chore: fix ff test for codegen (#33122) 2024-10-15 13:34:08 -07:00
Anand M Cherian d40425ea58
docs: update to "Matching one of the two alternative locators" section (#33079)
Signed-off-by: Anand M Cherian <63868951+Anand-M-Cherian@users.noreply.github.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-10-15 12:45:03 -07:00
Playwright Service 615f1dbd63
feat(chromium-tip-of-tree): roll to r1269 (#33117)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-15 17:51:57 +02:00
Dmitry Gozman 59a50cf596
fix(chromium): disable PlzDedicatedWorker again (#33110) 2024-10-15 02:13:19 -07:00
Dmitry Gozman 17837e564d
fix(routeWebSocket): make sure ws url without trailing slash is supported (#33095) 2024-10-15 02:08:27 -07:00
Dmitry Gozman 8a275e5a5b
docs: improve docs for WebSocketRoute (#33097) 2024-10-15 02:07:03 -07:00
Pavel Feldman 2c05d294a8
chore: fix webkit visibility check in aria matcher (#33102) 2024-10-14 15:55:21 -07:00
Pavel Feldman a38ff6e0d8
chore: experimental toMatchAriaSnapshot (#33014) 2024-10-14 14:07:19 -07:00
Pavel Feldman 6cfcbe0d6d
chore: fix codegen selector while debugging (#33099)
Fixes #33052
2024-10-14 14:04:24 -07:00
Dmitry Gozman ecd147ce43
fix(test runner): when sharding with beforeAll, use shards total instead of workers (#33083)
Otherwise, we might split the `beforeAll`-grouped test group into
`workers` parts instead of `shard.total` parts as the user would expect.

Fixes #33077.
2024-10-14 13:46:06 -07:00
Yury Semikhatsky f8806d253d
chore(bidi): remove assertion from response dispatch (#33100)
After the context has been disposed we can't route any callbacks to it
because
it is not in the map, so the assertion doesn't make sense as it always
ends up in
the top level session.

Fixes the following error:
```
  pw:browser <closing ws> Closing websocket due to failed onmessage callback. eventData={"type":"success","id":32,"result":{}} e=Assertion error Error: Assertion error
  pw:browser     at assert (/home/yurys/playwright/packages/playwright-core/src/utils/debug.ts:21:11)
  pw:browser     at BidiSession.dispatchMessage (/home/yurys/playwright/packages/playwright-core/src/server/bidi/bidiConnection.ts:229:13)
  pw:browser     at BidiConnection.call [as _dispatchMessage] (/home/yurys/playwright/packages/playwright-core/src/server/bidi/bidiConnection.ts:93:25)
```
2024-10-14 13:25:30 -07:00
Playwright Service c7fbeddaf4
feat(webkit): roll to r2092 (#33078) 2024-10-14 22:21:49 +02:00
Simon Knott a8df750a48
fix(har): account for reused sockets (#33087)
Closes https://github.com/microsoft/playwright/issues/32960

If the socket is reused, the connect and DNS timings are set to -1,
because that timing doesn't apply to the current request. The time
between request start and the socket being free is counted as `blocked`.
2024-10-14 17:22:29 +02:00
Max Schmitt 9fcf60464d
chore: various v1.48.0 roll fixes for .NET (#33096) 2024-10-14 16:32:11 +02:00
Remigiusz Dudek 4c2d62a881
feat(html-reporter): recognize video attachment by the contentType (#33074)
Closes https://github.com/microsoft/playwright/issues/33073.

---------

Signed-off-by: Remigiusz Dudek <remigiusz_dudek@tlen.pl>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-10-14 05:16:19 -07:00
Fumiaki MATSUSHIMA 0a63427c77
fix(codegen): fix unselect issue (#33076) 2024-10-13 13:16:01 +02:00
Playwright Service 699f51b227
feat(webkit): roll to r2091 (#33070) 2024-10-11 17:18:06 -07:00
Playwright Service e4b0d5e6dd
feat(chromium): roll to r1142 (#33062)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-11 16:33:59 +02:00
Max Schmitt 87624c5434
Revert "fix(codegen): fix unselect issue (#32127)" (#33065)
This reverts commit 5121b19ac6.

The tree is red and fixing seems non-trivial.

Closes https://github.com/microsoft/playwright/issues/33064
Closes https://github.com/microsoft/playwright/pull/33060
2024-10-11 16:33:17 +02:00
Yury Semikhatsky b9cce598dd
fix(screenshot): show image diff inline in errors list (#32997)
The diff is now shown inline in the errors list.

There are 2 possible failures of toHaveScreenshot
* Previous and actual snapshot mismatch. In this case html report will
show diff between Actual/Previous and have Expected as a separate
screenshot.
* Actual/Previous are equal but they differ from the expected. In this
case html report only contains Actual/Expected images and the diff.

Reference: https://github.com/microsoft/playwright/issues/32341

<img width="1039" alt="image"
src="https://github.com/user-attachments/assets/b458f986-cc25-4721-862c-0cc2c1b01a42">
2024-10-10 16:49:17 -07:00
Playwright Service 10a9e1c730
feat(webkit): roll to r2090 (#33050) 2024-10-11 00:08:03 +02:00
Yury Semikhatsky 82fe882004
fix(webkit): scroll mobile page with background-attachment: fixed (#33048)
Fixes #31551
Fixes #23573
2024-10-10 14:32:27 -07:00
Playwright Service 7de084b6dc
feat(chromium-tip-of-tree): roll to r1268 (#33042)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-10 16:32:00 +02:00
Playwright Service 217b57df4c
feat(webkit): roll to r2089 (#33039)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-10 13:10:54 +02:00
Dmitry Gozman 25dd9b5cd4
feat: config.build.tsconfig (#33026)
Allows to specify `tsconfig` in the configuration file, which applies to
test files but not the config file itself.

Fixes #32808.
2024-10-10 01:37:46 -07:00
Pavel Feldman 8f3353865d
fix(ui): bring back the headed param (#33030)
Fixes https://github.com/microsoft/playwright/issues/33023
2024-10-09 17:46:54 -07:00
Playwright Service bc30cc795e
feat(chromium): roll to r1141 (#33027)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-09 14:55:37 +02:00
Dmitry Gozman c2cbf26497
docs: refresh timeouts doc (#33025)
After changes a few releases ago, specify that `afterEach` hooks are
included in a separate timeout.

Fixes #32851.
2024-10-09 05:10:10 -07:00
Max Schmitt 6210fef681
test: fix android tests (#33021) 2024-10-09 11:22:27 +02:00
Yury Semikhatsky bcf4ff1e47
chore(bidi): update setContent expectations for ff (#32992) 2024-10-08 11:58:01 -07:00
Simon Knott 892d67ffef
feat(test runner): allow stopping testrun with escape (#32584)
Closes https://github.com/microsoft/playwright/issues/32579
2024-10-08 11:39:54 -07:00
Fumiaki MATSUSHIMA 5121b19ac6
fix(codegen): fix unselect issue (#32127)
Fixes https://github.com/microsoft/playwright/issues/31290
2024-10-08 11:38:52 -07:00
Pavel Feldman dbe881cfdc
docs: add a section on balancing shards (#33011)
Closes https://github.com/microsoft/playwright/issues/32922
2024-10-08 08:35:02 -07:00
Pavel Feldman 6c9823eeaf
chore: allow minimal height for trace attachments (#32996) 2024-10-08 08:33:45 -07:00
Max Schmitt d0f2170e21
Revert "fix(test): do not allow mixing tests from different types (#29284)" (#33002)
This reverts commit 4784139bb0.

Closes https://github.com/microsoft/playwright/issues/29734
2024-10-08 16:00:40 +02:00
Simon Knott 042161e1ce
Reapply "fix(har timing): record connect timing for proxied connections" (#32855) (#33003)
This reapplies what we reverted in
https://github.com/microsoft/playwright/pull/32989.

Max and me debugged this, and found that the test failures come from
SOCKS proxy now preferring IPv6 over IPv4. We've updated the tests and
made sure that this doesn't mask any breaking change.

I'm enabling CQ1 to make sure we don't oversee any other CI failures.
2024-10-08 14:17:50 +02:00
Playwright Service 992994f036
feat(chromium-tip-of-tree): roll to r1267 (#33007)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-08 14:13:45 +02:00
Max Schmitt 47a889ac48
chore: roll stable-test-runner to 1.48.0-beta-1728384960000 (#33008) 2024-10-08 14:01:45 +02:00
Dmitry Gozman 814f7eb556
test: fix/fixme/update a few tests (#33006) 2024-10-08 03:59:35 -07:00
Playwright Service 5b29ead6f0
chore(driver): roll driver to recent Node.js LTS version (#33005)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-08 12:53:38 +02:00
Dmitry Gozman 0f2cbdedac
fix(routeWebSocket): do not show in the trace (#32991) 2024-10-08 02:47:24 -07:00
Simon Knott 1b589c4bd3
Revert "fix(har timing): record connect timing for proxied connections" (#32989)
Reverts microsoft/playwright#32855. This broke two tests on main, and we
don't yet know how to fix it other than downgrading.
2024-10-08 10:13:21 +02:00
Mark 04bf425268
feat(base-reporter): Add tags to test output (#32930) 2024-10-07 17:14:46 -07:00
Pavel Feldman 7047c3a6c6
fix(codegen): do not codegen non-existing fixtures (#32993)
Closes https://github.com/microsoft/playwright/issues/32981
2024-10-07 17:12:36 -07:00
Yury Semikhatsky 6ba5ee3a83
chore(ui-mode): expand all button (#32994)
<img width="230" alt="image"
src="https://github.com/user-attachments/assets/dd7fa3a1-39ec-4b88-9279-d664c9c4e5cd">


Reference https://github.com/microsoft/playwright/issues/32825
2024-10-07 15:42:12 -07:00
Aaron Sherwood 4d13677ebd
chore: add Devuan OS fallback to Debian (#32990) 2024-10-07 23:24:18 +02:00
Yury Semikhatsky 4ab857ce8e
test: fetch header propagation on redirect (#32970)
Documenting current behavior with and without interception.

Reference https://github.com/microsoft/playwright/issues/32939
2024-10-07 14:06:28 -07:00
Yury Semikhatsky 4fe33db392
docs(route): header override propagation (#32971)
Fix https://github.com/microsoft/playwright/issues/32939
2024-10-07 13:52:55 -07:00
Simon Knott 9a6f03eb87
fix(fetch): listener leaks on Socket (#32956)
Closes https://github.com/microsoft/playwright/issues/32951

`node:http` reuses TCP Sockets under the hood. We weren't cleaning up
our listeners, leading to the `MaxListenersExceededWarning`.

This PR adds cleanup logic. It also raises the warning threshhold, so
that it doesn't trigger until there's 100 concurrent requests over the
same socket.
2024-10-07 18:43:25 +02:00
Simon Knott d3fbf1aaeb
fix(clock): amend setSystemTime docs (#32901)
As discussed yesterday over
https://github.com/microsoft/playwright/issues/32807. Adds some words to
differentiate `setSystemTime` from `setFixedTime`.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-10-07 12:12:12 +02:00
Dmitry Gozman e6afb650be
test: mark a few tests as fixme (#32985) 2024-10-07 02:58:03 -07:00
Max Schmitt 001ba37706
test: update webview2 skipme's (#32984)
This leaves only reasonable skipmes for WebView2 in the code base.
2024-10-07 11:08:07 +02:00
Bruno 317ddd4117
docs(best practices): tabs with yarn and pnpm commands added (#32980) 2024-10-07 10:48:30 +02:00
Simon Knott de4a4d1ce1
fix(har timing): record connect timing for proxied connections (#32855)
Fixes a bug discovered in
https://github.com/microsoft/playwright/pull/32647. When using http
proxy, the `connect` event isn't emitted so we don't populate
`tcpConnectionAt`. The updated version of `https-proxy-agent` emits a
`proxyConnect` as a replacement, so this PR updates and listens to that
event.
For socks proxies, the `on("socket")` event is emitted once the SOCKS
connection is established, which is the equivalent of having a TCP
connection available.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-10-07 09:59:13 +02:00
Max Schmitt ddeabdf770
devops: speculative fix for flakiness dashboard data loss (#32963) 2024-10-04 18:47:35 +02:00
Dmitry Gozman b284df984b
test: enable test after chromium roll to 1140 (#32965)
Fixes #32355. Fixed after the last roll #32949.
2024-10-04 09:23:11 -07:00
Dmitry Gozman 9f842da8b3
fix: throw when element handle is detached while waiting for selector (#32961) 2024-10-04 08:23:25 -07:00
Dmitry Gozman eaeaa0b158
test: remove tests that we are not going to ever fix (#32962) 2024-10-04 08:22:36 -07:00
Dmitry Gozman 34ad67659f
test: remove some fixmes (#32953) 2024-10-04 08:22:27 -07:00
Simon Knott 40670e6ffd
fix(emulate media): document "no-preference" as deprecated (#32881)
Closes https://github.com/microsoft/playwright/issues/32862.

`prefers-color-scheme: no-preference` was removed from browsers. This PR
marks it as deprecated in our docs and removes all mentions.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-10-04 16:49:32 +02:00
Simon Knott 80ff7c396a
chore(docs): fix code highlighting (#32927)
Closes https://github.com/microsoft/playwright/issues/32921

This is the diff when rolling to `playwright.dev` locally:
<img width="1262" alt="Screenshot 2024-10-02 at 14 54 42"
src="https://github.com/user-attachments/assets/aade7ad4-420c-48c4-a2c9-03fe815a3959">

---------

Signed-off-by: Simon Knott <info@simonknott.de>
2024-10-04 16:38:13 +02:00
Simon Knott 6be97f34dd
docs(test-reporters): replace reporter showcase with list of interesting OSS implementations (#32896)
As discussed yesterday, this PR replaces the "reporter showcase" with a
list of interesting implementations for folks who are writing their own
custom reporters.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
2024-10-04 16:29:13 +02:00
Dmitry Gozman 84b4fd4e40
feat: wait for pending navigation to resolve before many actions (#32899)
This includes all actions that perform locator handler check.
    
Note this makes it impossible to interact with the page while a main
frame navigation is ongoing. This was already the case for Chromium, but
now WebKit and Firefox align with it.

Setting `PLAYWRIGHT_SKIP_NAVIGATION_CHECK` environment variable disables
this behavior.
2024-10-04 07:25:18 -07:00
Simon Knott 1b457b1ff8
fix(html reporter): render annotation newlines (#32948)
Closes https://github.com/microsoft/playwright/issues/32925. Before this
change, newlines in annotation descriptions weren't respected. This
change makes them shown. Here's how it looks for this annotation:

```ts
test.info().annotations.push({
  type: 'user story',
  description: '\n- user goes to the page\n- user clicks the button\n- user sees the result',
});
```

Before:

<img width="1071" alt="Screenshot 2024-10-04 at 09 55 15"
src="https://github.com/user-attachments/assets/89e74ff5-ea83-48da-a33b-833423916d95">

After:

<img width="1031" alt="Screenshot 2024-10-04 at 09 51 08"
src="https://github.com/user-attachments/assets/0f2914e8-bd88-4970-aa68-6a5a9828295c">
2024-10-04 14:18:38 +02:00
Simon Knott ff0c498904
fix(ct-vue): update default slot should work (#32952)
Closes https://github.com/microsoft/playwright/issues/32809

We were writing onto the wrong object.
2024-10-04 14:18:21 +02:00
Dmitry Gozman 10d6812058
chore: clear pendingDocument() for the same-document navigation (#32954)
WebKit notifies about a pending same-document navigation through
`Page.frameScheduledNavigation`, and committing it should clear the
`pendingDocument()`.

Extracted from #32899.
2024-10-04 04:54:56 -07:00
Max Schmitt 895be9f8de
chore: lint java docs snippets (#32945) 2024-10-04 11:34:04 +02:00
Playwright Service 0a45549533
feat(chromium): roll to r1140 (#32949)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-04 11:14:08 +02:00
Max Schmitt dfa4ab8726
test: speed up only-changed CT test (#32947) 2024-10-04 10:06:56 +02:00
Yury Semikhatsky d7020cba63
test: scroll mobile page with background-attachment: fixed (#31992)
Reference: https://github.com/microsoft/playwright/issues/31551
Reference: https://github.com/microsoft/playwright/issues/23573
2024-10-03 18:16:49 -07:00
Dmitry Gozman 6b1d0361cd
fix(chromium): reset mouse position upon page reuse (#32944)
Similarly to Firefox, move the mouse to (-1, -1) upon page reuse. This
fixes the corresponding test on all platforms.
2024-10-03 08:09:00 -07:00
Dmitry Gozman d98fa5da2f
test: update some expectations for headed chromium, unskip tests (#32943) 2024-10-03 07:59:48 -07:00
Playwright Service 076a6e84a1
feat(chromium-tip-of-tree): roll to r1266 (#32942)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-03 16:03:30 +02:00
Dmitry Gozman 0ffac886e8
test: fix android tests (#32932)
One test is removed, since it's impossible to fix. Hopefully, the rest
will pass.
2024-10-03 03:37:43 -07:00
Dmitry Gozman 3c5967d4f5
fix(trace viewer): clear old highlighted elements upon change (#32917)
When the list of highlighted elements changes over time, we should
update the elements marked as `__playwright_target__` in the snapshot.

A good example is an `expect(locator).toHaveText([...])` where the list
of elements changes from 4 items to 3 after clicking a "Delete" button.
2024-10-02 23:48:26 -07:00
Playwright Service 616425a0fb
feat(firefox): roll to r1465 (#32938) 2024-10-03 08:25:44 +02:00
Max Schmitt 8715652a0d
devops: don't run codegen tests in trace-events mode (#32810) 2024-10-02 23:22:00 +02:00
Yury Semikhatsky d7651b8f56
chore(bidi): disable firefox tracing on CI (#32935)
Disabling as it produces [too much
output](https://github.com/microsoft/playwright/pull/32908#issuecomment-2387914821).
2024-10-02 11:16:56 -07:00
Simon Knott 29ffcdfc4e
test(html reporter): filtering by type works (#32931)
The folks who opened
https://github.com/microsoft/playwright/issues/32925 would benefit from
filtering by annotation existence. Turns out we already have it! This PR
adds a test to ensure it stays that way.
2024-10-02 16:29:27 +02:00
Dmitry Gozman face24dc66
test: unflake/skip a few tests (#32929) 2024-10-02 06:58:21 -07:00
Max Schmitt 31a4a74598
chore: do not create a GitHub Status Check for merge results (#32928) 2024-10-02 15:23:42 +02:00
Simon Knott 3a5bf1cc1d
fix(trace viewer): reveal stack for highlighted action (#32919)
Closes https://github.com/microsoft/playwright/issues/32915.

In the `Call` and `Logs` tabs, we update the contents based on the
hovered action. We document that this is also the case for the `Source`
tab:


78054a7652/docs/src/test-ui-mode-js.md?plain=1#L61-L65

But it isn't. Not sure if it's a regression or not, but this PR fixes
it.
2024-10-02 13:30:44 +02:00
Max Schmitt 6373fe703d
docs: fix Java/.NET types for docs rolling (#32924) 2024-10-02 13:27:56 +02:00
Max Schmitt 67c37cf813
docs(ci): recommend noble instead of jammy (#32923) 2024-10-02 13:12:11 +02:00
Viet Nguyen Duc dbf7976dd8
docs(selenium): update docker image tag in feat Playwright connect Selenium Grid (#32777) 2024-10-02 11:34:05 +02:00
Simon Knott 6ccaad3a1b
chore: call out that that the vscode extension is for Node.js (#32882)
In https://github.com/microsoft/playwright/issues/32861, an interested
.NET user wanted to try Playwright and found the VS Code Getting Started
guide. It didn't work for them because the VS Code Extension is for
usage with Node.js, and they don't have NPM installed. We can reduce
confusion by mentioning that VS Code Getting started is for Node.js.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
2024-10-02 11:19:51 +02:00
Simon Knott 208a54529d
fix(ct-react): support shorthand fragment notation (#32900)
Closes https://github.com/microsoft/playwright/issues/32853

Vite turns the shorthand fragment notation `<></>` into `import {
Fragment } from "react"; <Fragment></Fragment>`. On the Node.js side of
things, this `react` import resolves to our mock version of React, which
currently mocks `Fragment` as `{}`. Currently, we pass that straight to
`React.createElement`, which throws an error.

The fix is to make our `Fragment` mock detectable with a tag, and when
we render it replace it with the real `__pwReact.Fragment`.
2024-10-02 11:19:09 +02:00
Playwright Service 0fd9452127
feat(webkit): roll to r2084 (#32912)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-02 09:02:32 +02:00
Dmitry Gozman 773202867d
feat(trace): highlight strict mode violation elements in the snapshot (#32893)
This is fixing a case where the test failed with strict mode violation,
but all the matched elements are not highlighted in the trace.

For example, all the buttons will be highlighted when the following line
fails due to strict mode violation:
```ts
await page.locator('button').click();
```

To achieve this, we mark elements during `querySelector` phase instead
of inside `onBeforeInputAction`. This allows us to only mark from inside
the `InjectedScript` and remove the other way of marking from inside the
`Snapshotter`.
2024-10-02 00:00:45 -07:00
Max Schmitt daac0ddd24
fix(fetch): fallback to given URL if baseURL is invalid (#32911) 2024-10-01 22:43:32 +02:00
Max Schmitt c84305ed73
test: retry installation tests up to 3 times (#32910)
Installation tests can fail due to e.g. network issues. Lets align with
library tests and retry up to 3 times.
2024-10-01 13:12:38 -07:00
Yury Semikhatsky 228eb141db
chore(bidi): enable logs in Firefox on CI (#32908) 2024-10-01 11:15:27 -07:00
Max Schmitt 78054a7652
chore: remove 'screenshot instead of snapshot' usages (#32905)
Fixes https://github.com/microsoft/playwright/issues/32904
2024-10-01 18:38:10 +02:00
Playwright Service 00e1a99d65
feat(chromium): roll to r1139 (#32906)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-01 18:18:45 +02:00
Playwright Service 8688af0580
feat(chromium-tip-of-tree): roll to r1265 (#32894)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-01 16:02:21 +02:00
Playwright Service 60db16bad3
feat(chromium): roll to r1138 (#32898)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-01 15:15:00 +02:00
Simon Knott 4bcfa56a13
chore(test runner): mention different timeout (#32883)
In https://github.com/microsoft/playwright/issues/32872, a user notes
that we document `.focus()` to not timeout by default, but in practice
when used without the test runner, it defaults to a 30s timeout.

I've discussed this with Dima, and he noted that our JS documentation
focuses on usage with the Playwright test runner, not with the library.
The test runner disables timeouts for operations in favour of timeouts
for test cases. In the library, we default to a 30s timeouts. This PR
adds this to the "key differences" table.
2024-10-01 11:46:42 +02:00
Max Schmitt 6f16b6cc08
chore: unflake 'should record' (#32880) 2024-09-30 20:32:04 +02:00
Dmitry Gozman 6f99d48a12
test: unflake two tests (#32879)
- the test that closes a context must not be a "page test";
- account for stray browser requests in the proxy test.
2024-09-30 07:49:18 -07:00
Simon Knott c67a7335ab
chore(ui): ensure that --ignore-snapshots is respected (#32875)
Closes https://github.com/microsoft/playwright/issues/32868.

The actual fix was already delivered in
https://github.com/microsoft/playwright/pull/32798/files#diff-98ff2ff92b08ca7e8b274abb3ba6b2eec9bab332e340d062cc18ad1dfe505bf2R299,
this PR adds a test to ensure we don't regress.
2024-09-30 15:12:37 +02:00
Max Schmitt b78103ba50
devops: simplify 'headed' testing matrix (#32878) 2024-09-30 14:40:56 +02:00
Max Schmitt dde8090916
devops: unite channel tests into single GHA matrix workflows (#32876) 2024-09-30 14:24:05 +02:00
Dmitry Gozman 011034050b
chore: update browser patches to 09195c9 (#32877) 2024-09-30 05:14:45 -07:00
Dmitry Gozman 541ce9f0bb
chore: mark 1.49.0-next (#32873) 2024-09-30 04:24:57 -07:00
Max Schmitt d3e38c32af
devops: align macOS versions in workflows (#32871) 2024-09-30 12:42:47 +02:00
Simon Knott aa3146785f
fix(ui): turn "copy as fetch" into text button (#32858)
Turns the "copy as fetch" text with a copy button into a text button, as
discussed in the meeting.


https://github.com/user-attachments/assets/01f72f0b-e3f2-440e-a75d-33385aabeec4
2024-09-30 03:01:56 -07:00
Max Schmitt 412073253f
test: unflake microphone/video tests on macOS 15 (#32870) 2024-09-30 10:31:15 +02:00
Max Schmitt df16f6efb4
test: skip avif test on linux/webkit (#32869) 2024-09-30 10:30:45 +02:00
Adam Patridge 2f7b06736f
chore(contributing.md): markdown list item adjustments (#32859) 2024-09-30 09:48:01 +02:00
Pavel Feldman 11014145ce
chore: update trace event on action merge (#32860) 2024-09-27 21:18:30 -07:00
Pavel Feldman 908b0de5d4
chore: style action list in tv mode (#32845) 2024-09-27 17:52:03 -07:00
Max Schmitt 6721cc1746
chore: disable LensOverlay in Chromium (#32790) 2024-09-27 20:06:27 +02:00
Dmitry Gozman 6bc5c9ca84
docs: release notes for 1.48 (#32857) 2024-09-27 11:06:11 -07:00
Max Schmitt ded567d8f8
test: add test for avif image format (#32815)
Fixes https://github.com/microsoft/playwright/issues/32673
2024-09-27 10:02:54 -07:00
Dmitry Gozman 5947c21dc7
test: brush up fixtures, unflake some tests (#32854) 2024-09-27 07:06:37 -07:00
Dmitry Gozman a395fb22c4
feat(routeWebSocket): address api review feedback (#32850) 2024-09-27 04:01:31 -07:00
Playwright Service d6f584c2d4
feat(chromium-tip-of-tree): roll to r1264 (#32840)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-27 10:06:45 +02:00
Pavel Feldman bcb6860ef5
chore: fix cross browser leak tests (#32843) 2024-09-26 19:33:07 -07:00
Yury Semikhatsky 728b4814b4
test: fix recently added junit tests (#32844) 2024-09-26 19:32:54 -07:00
Pavel Feldman 1a3d3f699b
chore: render recorded action list in tv mode (#32841) 2024-09-26 16:46:27 -07:00
Yury Semikhatsky 5b85c71722
fix(junit): env variable should take precedence over config (#32842)
Fixes https://github.com/microsoft/playwright/issues/32826
2024-09-26 15:29:09 -07:00
Pavel Feldman c105de4436
chore: move actions types to recorder (#32839) 2024-09-26 14:50:09 -07:00
Max Schmitt 0d79291604
chore: hide screenshot instead of snapshot Trace Viewer feature (#32832) 2024-09-26 22:30:41 +02:00
Playwright Service 463bd55cf0
feat(webkit): roll to r2083 (#32813) 2024-09-26 21:49:02 +02:00
Pavel Feldman 9bff4d7eab
chore: move sw files into the sw/ folder (#32837) 2024-09-26 11:22:20 -07:00
Yury Semikhatsky e8d08e8d1e
docs: more prominent note on tags being read-only (#32836)
Reference https://github.com/microsoft/playwright/issues/32828
2024-09-26 09:41:38 -07:00
Dmitry Gozman d07f6cfc5c
docs: check that description has an empty line before it (#32830) 2024-09-26 06:31:42 -07:00
Dmitry Gozman 6465f0b1bd
test: make sure custom asymmetric matchers work (#32829)
This adds a test for a regression introduced by #32366 and fixed by
#32795.
2024-09-26 06:27:37 -07:00
Max Schmitt 3b86a9c0e4
docs(markdown): parse :::note's text as children (#32510) 2024-09-26 15:16:26 +02:00
Dmitry Gozman a2bdb2fd79
docs: linkify params and options (#32823)
References https://github.com/microsoft/playwright/issues/32590.
2024-09-26 05:13:00 -07:00
Dmitry Gozman a9d5c39d40
chore: address api review for page.forceGarbageCollection (#32824)
- Renamed to `page.requestGC`.
- Added a useful snippet to the docs.

References #32278.

---------

Signed-off-by: Dmitry Gozman <dgozman@gmail.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-09-26 05:08:33 -07:00
Playwright Service 6c20318e5c
feat(chromium): roll to r1137 (#32827)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-26 13:58:55 +02:00
Dmitry Gozman ff954b58eb
fix(test runner): cleanup DEBUG_COLORS usage (#32764)
`DEBUG_COLORS` we default to `1`, but we should not do that when it is
already defined to some value supplied by the user.

Closes #32543.
2024-09-26 03:15:46 -07:00
Dmitry Gozman e5433d0576
chore(docs): validate params/options links (#32820)
Also supports fully-qualified links like this:
```
[`option: BrowserType.launch.headless`]
```

References https://github.com/microsoft/playwright/issues/32590.
2024-09-26 01:08:16 -07:00
Yury Semikhatsky 597642d269
chore: pass cli config overrides straight to test server (#32818) 2024-09-25 19:45:59 -07:00
Pavel Feldman 61801aa1ee
chore: more codegen fixes (#32816) 2024-09-25 18:18:36 -07:00
Yury Semikhatsky 0480bd0cac
chore(bidi): launch firefox with user prefs tailored for testing (#32817)
Various settings that make Firefox behave when testing over Bidi. The
settings are copied from
ea36b7b1f0/packages/browsers/src/browser-data/firefox.ts (L190-L402).

Unlike Playwright bundled version, we write the settings into `user.js`
in the profile folder before launching the browser.
2024-09-25 18:17:07 -07:00
Yury Semikhatsky b6783bb18b
fix(ui-mode): respect --tsconfig option (#32798)
Fixes https://github.com/microsoft/playwright/issues/32797
2024-09-24 19:59:15 -07:00
Pavel Feldman 35158feec0
chore: fix codegen flakiness (#32799) 2024-09-24 19:56:31 -07:00
Pavel Feldman 755edfba5b
chore: fallback expect.extend to legacy (#32795) 2024-09-24 14:00:13 -07:00
Playwright Service a4cea0c208
feat(webkit): roll to r2082 (#32793) 2024-09-24 19:46:12 +02:00
Max Schmitt dd91afa736
test: retry page-leak object count checks (#32794) 2024-09-24 18:48:54 +02:00
Playwright Service 0b69b1370a
feat(chromium-tip-of-tree): roll to r1263 (#32791)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-24 14:44:27 +02:00
Max Schmitt 5e7d7f356b
test: skip codegen tracing tests in PWTEST_TRACE mode (#32788) 2024-09-24 12:35:05 +02:00
Max Schmitt 137f192d55
test: add different expectation for macOS/headed 'should work for canvas' (#32774) 2024-09-24 12:27:36 +02:00
Max Schmitt b01dd55697
docs: use node-version: lts/* in GHA examples (#32789) 2024-09-24 12:23:47 +02:00
Max Schmitt 057a3187fc
devops: add logging for report name when uploading to flakiness dashboard (#32786) 2024-09-24 12:20:39 +02:00
Max Schmitt 76c3077a69
test: retry oopif boundingBox assertions (#32787) 2024-09-24 12:02:40 +02:00
Max Schmitt 995c73e9d9
test: skip WebKit WebGL tests on Intel macOS (#32784) 2024-09-24 11:55:17 +02:00
Dmitry Gozman 59700aa9f1
chore: brush up documentation scripts (#32782)
References #32590.
2024-09-24 02:51:09 -07:00
Pavel Feldman 22c76aacad
chore: roll rollup to fix audit (#32778) 2024-09-23 20:01:08 -07:00
Pavel Feldman 8649b13f25
chore: start putting tv-recorder ui together (#32776) 2024-09-23 19:13:45 -07:00
Playwright Service 7c3dd70bf6
feat(webkit): roll to r2081 (#32738) 2024-09-23 19:08:01 -07:00
Yury Semikhatsky eda0e01167
chore(bidi): bring to front, pdf (#32698) 2024-09-23 19:05:55 -07:00
Yury Semikhatsky fbeba6619a
devops(bidi): increase global timeout to 60m (#32775)
Firefox tests are running out of time on CI.
2024-09-23 17:55:30 -07:00
Max Schmitt 8557b98aee
test: fix CR/LF warning on only-changed tests (#32772) 2024-09-24 01:32:36 +02:00
Pavel Feldman c7a5278fb3
fix: do not start tracing in default recorder (#32770) 2024-09-23 15:51:27 -07:00
Pavel Feldman 0c8b2a7c32
chore: take snapshot tab apart (#32756) 2024-09-23 15:51:15 -07:00
Yury Semikhatsky 11320d34c6
Revert chore: ignore third-party execution contexts (#32437) (#32771)
Partially revert #32437 and add a test that console.log() messages from
content scripts are properly reported

Fixes https://github.com/microsoft/playwright/issues/32762
2024-09-23 15:48:11 -07:00
Max Schmitt 0ee9a82926
test: skip 'should work with error after successful open' on WebKit Windows (#32769) 2024-09-23 23:31:04 +02:00
Yury Semikhatsky c9a26e60f5
fix(webkit): 204 response is not a failure (#32768)
The login being changed was added in
https://github.com/microsoft/playwright/pull/1260 and is supposed to
only work for navigation requests.

Reference: https://github.com/microsoft/playwright/issues/32752
2024-09-23 14:30:40 -07:00
Max Schmitt 26dc8955d3
docs: explain glob patterns (#32728) 2024-09-23 22:22:57 +02:00
Mathias Leppich 281eff1209
docs(trial): note that modifier keys are pressed regardless of trial option (#32734) 2024-09-23 22:17:47 +02:00
Pavel Feldman 0cdc7ee1a3
chore: extract polling recorder (#32749)
We are reusing recorder in a snapshot tab, no need for the polling
harness to be there.
2024-09-23 08:42:18 -07:00
Playwright Service 99895005e2
feat(chromium-tip-of-tree): roll to r1262 (#32760)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-23 14:47:44 +02:00
Max Schmitt 12ecd476dd
fix(watch): cancel waitForCommand when files change (#32761)
Fixes https://github.com/microsoft/playwright/issues/32758
2024-09-23 14:43:28 +02:00
Dmitry Gozman b3a82bef46
feat: do not record route calls in the trace (#32723)
These are represented in the network pane instead.
2024-09-21 10:17:59 -07:00
Pavel Feldman 17ed944a84
chore: iterate towards recording into trace (4) (#32743) 2024-09-20 16:56:05 -07:00
Pavel Feldman 418d1c0c55
chore: allow starting recorder in traceviewer (#32741) 2024-09-20 15:25:49 -07:00
Pavel Feldman dfb3fdf217
chore: iterate towards recording into trace (3) (#32718) 2024-09-20 13:08:33 -07:00
Yury Semikhatsky bef1e990ac
chore(bidi): run firefox tests against nightly build (#32737) 2024-09-20 12:57:10 -07:00
Yury Semikhatsky 5c20f0c534
test: pressing tab should trigger blur event (#32719)
Reference: https://github.com/microsoft/playwright/issues/32339
2024-09-20 12:03:25 -07:00
Max Schmitt 7cd69beed2
test: unflake 'should properly synchronize local and remote time' test (#32733) 2024-09-20 20:21:57 +02:00
Playwright Service 33890eb6c5
feat(webkit): roll to r2080 (#32721)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-09-20 08:28:46 -07:00
Dmitry Gozman cdcaa7fab6
feat: routeWebSocket (#32675)
This introduces `WebSocketRoute` class and
`page/context.routeWebSocket()` methods.
2024-09-20 03:20:06 -07:00
Dmitry Gozman ace8cb2427
fix(test runner): page.pause() should enable debug mode (#32714)
Fixes #32706.
2024-09-20 00:41:16 -07:00
Playwright Service 935aa6b020
feat(webkit): roll to r2079 (#32720)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-20 09:34:31 +02:00
Pavel Feldman 01b44ba077
chore: remove PWTEST_RECORDER_PORT as it was ignored (#32717) 2024-09-19 13:35:52 -07:00
Pavel Feldman a00e1c9c4b
chore: make recorder tests match order of codegen calls (#32716) 2024-09-19 10:31:44 -07:00
Max Schmitt 2b2a57abad
chore: enable @babel/plugin-syntax-import-attributes all the time (#32713) 2024-09-19 16:51:35 +02:00
Dmitry Gozman cc302fa515
fix(chromium): allow PlzDedicatedWorker (#32711)
With the recent Chromium fixes in v129, it is now safe to enable this
feature.

Fixes #31747.
2024-09-19 06:38:58 -07:00
Playwright Service ea284f2986
feat(chromium-tip-of-tree): roll to r1261 (#32709)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-19 14:47:03 +02:00
Playwright Service e8e72deac2
feat(chromium): roll to r1136 (#32707)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-19 14:35:48 +02:00
Dmitry Gozman 5089d9f293
fix(chromium): disable ThirdPartyStoragePartitioning (#32701)
See
https://developers.google.com/privacy-sandbox/cookies/storage-partitioning
for more details.

References #32230.
2024-09-19 03:12:21 -07:00
Max Schmitt 61cbca6695
test: fix client-certificate tests (#32691) 2024-09-19 12:03:05 +02:00
Max Schmitt 48030a4eff
test: fix test expecations after Node.js 22.9.0 (#32695) 2024-09-19 10:52:29 +02:00
Pavel Feldman 2f4acbb001
chore: use contentFrame() as a canonical locator representation (#32697) 2024-09-18 20:15:01 -07:00
Pavel Feldman 790dbfd78f
fix(codegen): use content_frame property in python (#32699) 2024-09-18 19:11:14 -07:00
Yury Semikhatsky 3d306da767
chore: roll chromium-bidi (#32696)
It implements network.setCacheBehavior which should unblock some
interception tests
2024-09-18 17:23:26 -07:00
Yury Semikhatsky 48d3d5554d
chore(bidi): suppress crash reporter in firefox (#32694)
Same settings as geckodriver uses upstream:
https://searchfox.org/mozilla-central/rev/c414b4538dd3c7e1dc674f7b66176e7c309afa95/testing/geckodriver/src/browser.rs#130-132
2024-09-18 16:02:10 -07:00
Pavel Feldman 427eca6f7e
chore: iterate towards recording into trace (2) (#32693) 2024-09-18 14:39:07 -07:00
Dmitry Gozman f9d9ad25de
feat(locator handler): perform checkpoit during locator.waitFor (#32683)
Fixes #32255.
2024-09-18 09:34:06 -07:00
Max Schmitt d4eecafa8a
test: listen always on 127.0.0.1 for client certificate tests (#32677) 2024-09-18 17:09:08 +02:00
Max Schmitt 523ec83cad
chore: move Location type from testReporter.d.ts to test.d.ts (#32687) 2024-09-18 16:57:11 +02:00
Playwright Service ddd43d0f20
feat(webkit): roll to r2078 (#32685)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-18 15:50:43 +02:00
Max Schmitt ec3db20743
test: fix toolbar hydration test under frozen suite (#32684) 2024-09-18 15:35:33 +02:00
Simon Knott 825df6c074
feat(har): record serverIPAddress for API requests (#32660)
Discovered working on
https://github.com/microsoft/playwright/pull/32658. We're recording the
remote server address for browser requests, but not for API requests.
This PR adds that for API requests.
2024-09-18 14:51:42 +02:00
Playwright Service 7d4aa0aa8e
feat(chromium-tip-of-tree): roll to r1260 (#32651)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-18 14:37:19 +02:00
Max Schmitt 4c31a8289f
feat(trace-viewer): add network requests 'copy as cURL' button (#32627) 2024-09-18 14:35:11 +02:00
Max Schmitt 9fc195bff5
test: update cookie expectations for macOS 15 (#32674) 2024-09-18 11:08:17 +02:00
Simon Knott 4460c98710
fix(har tracing): record response.bodySize for API requests (#32656)
A small drive-by that came out of working on
https://github.com/microsoft/playwright/issues/32653.
2024-09-18 08:21:10 +02:00
Simon Knott 8a97050822
feat(har): record securityDetails for API Requests (#32664)
While working on https://github.com/microsoft/playwright/pull/32658 I
discovered that we're recording `securityDetails` for browser requests,
but not for API requests. This PR fixes that.
2024-09-18 08:18:47 +02:00
Simon Knott 443f72dcbe
feat(watch): hide show-report prompt (#32666)
Closes https://github.com/microsoft/playwright/issues/32665
2024-09-18 08:17:13 +02:00
Pavel Feldman 355c88f48f
chore: iterate towards recording into trace (#32646) 2024-09-17 18:26:44 -07:00
Yury Semikhatsky 623b2e6bc8
chore: bump vite dependency 5.0.13->5.4.6 (#32672)
Fixes the following:

```
npm audit report

vite  5.0.0 - 5.2.13
Severity: moderate
Vite DOM Clobbering gadget found in vite bundled scripts that leads to XSS - https://github.com/advisories/GHSA-64vr-g452-qvp3
```
2024-09-17 17:01:38 -07:00
Yury Semikhatsky 4c4d74ca5b
chore: page.screenshot() in bidi (#32671)
The results are copied from the existing chromium expectations.
2024-09-17 16:51:56 -07:00
Yury Semikhatsky 8b84b20dd0
chore: back-forward in bidi (#32670) 2024-09-17 16:02:13 -07:00
Yury Semikhatsky 375a1c4982
chore: exposeBinding/exposeFunction in bidi (#32669) 2024-09-17 15:37:42 -07:00
Yury Semikhatsky ad70e7a783
fix(trace-viewer): time delta between local and remote actions (#32661) 2024-09-17 11:14:15 -07:00
Simon Knott f1390cc269
chore(har recorder): ensure we respect minimal mode (#32658)
Closes https://github.com/microsoft/playwright/issues/32653.

Adds some test coverage to ensure we respect minimal mode for API
Requests in HAR tracing.

| omit setting | result |
| - | - |
| `omitCookies` |  added test for it |
| `omitTiming` | already covered |
| `omitSecurityDetails` | not recorded yet |
| `omitServerIP` | we don't record it yet, so no action here. gonna open
a separate issue |
| `omitPages` | not relevant to API requests |
| `omitSizes` | added test for it |
| `omitScripts` | not relevant to API requests |
2024-09-17 19:59:44 +02:00
오소현 8761dafc73
feat(test runner): allow to pass arbitrary location to test.step (#32504)
Fixes https://github.com/microsoft/playwright/issues/30160

### Description:
This pull request introduces the ability to specify custom locations for
test steps in Playwright. By enabling the provision of arbitrary
locations to the test.step method, it resolves the limitation where
helper methods obfuscate the original call site, providing more accurate
and meaningful location data in test reports.

### Motivation:
To enhance the utility and clarity of test reports in Playwright.
Specifically, it addresses the need to trace test steps back to their
precise location in the code, which is especially important when steps
are abstracted in helper functions. This feature is crucial for
maintaining accurate documentation and facilitating debugging processes.

### Changes:
Added functionality to pass a custom location object to test.step.

### Expected Outcome:
This PR is expected to significantly improve the precision and
usefulness of diagnostic data in test reports by allowing specific
locations within helper functions to be accurately documented. It
facilitates better tracking of test executions and simplifies the
debugging process, making it easier for developers to understand and
address issues within complex tests.

### References:
Closes https://github.com/microsoft/playwright/issues/30160 -
"[Feature]: allow to pass arbitrary location to test.step"

**Code Check**
I conducted tests on this new feature by integrating it into some
existing test codes, and it worked well. I will attach the code used for
testing and a screenshot showing the successful outcome.

<details>
<summary>toggle dropdown</summary>
<div markdown="1">

```
import type { Location } from '../../../packages/playwright/types/testReporter'
...
test('should respect the back button', async ({ page }) => {
    await page.locator('.todo-list li .toggle').nth(1).check();
    await checkNumberOfCompletedTodosInLocalStorage(page, 1);
...
    await test.step('Showing active items', async () => {
      await page.getByRole('link', { name: 'Active' }).click();
    }, {location});
```

<img width="1109" alt="image"
src="https://github.com/user-attachments/assets/359feafa-0949-4c71-9426-46debef21bdd">
</div>
</details>
2024-09-17 08:11:21 -07:00
Max Schmitt 507e515cb2
chore: remove unused @babel/parser (#32654) 2024-09-17 16:14:24 +02:00
Simon Knott 751b939d3a
feat(fetch): record timings (#32613)
Related to https://github.com/microsoft/playwright/issues/19621

Adds some instrumentation to collect timings for `APIRequestContext`
requests and adds them to the HAR trace. Doesn't yet expose them via an
API, but makes our `Duration` field in the trace viewer show a nice
duration:

<img width="1392" alt="Screenshot 2024-09-14 at 11 46 04"
src="https://github.com/user-attachments/assets/8020382d-9494-4634-9cfd-22b6f4a1d770">


I'm gonna add it to our API in a separate PR.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-09-17 16:11:21 +02:00
Max Schmitt c216c25a1d
feat(html-reporter): add file name copy button (#32652) 2024-09-17 15:54:22 +02:00
Simon Knott f6219e6e79
Revert "feat(tracing): add .pwtrace to trace file extension" (#32648)
Reverts microsoft/playwright#32581
Relates
https://github.com/microsoft/playwright/issues/32226#issuecomment-2351164727
2024-09-17 15:32:30 +02:00
Ana Margarida Silva b23edf5137
fix(docs): remove todo in ci intro docs (#32643) 2024-09-17 10:36:43 +02:00
Simon Knott ec2ae1ed2d
feat(watch mode): buffer mode (#32631)
Closes https://github.com/microsoft/playwright/issues/32578.

Adds a buffer mode that can be toggled by pressing <kbd>b</kbd>. When
engaged, changed test files are collected and shown on screen. The test
run is then kicked off by pressing <kbd>Enter</kbd>.

This changes the signal to start a test run from <kbd>Cmd+s</kbd> to a
<kbd>Enter</kbd> press in the test terminal. It should help users with
auto-save and make it easier to run on long-running tests. It feels very
similar to running `npx playwright test`, but without having to write a
filter.



https://github.com/user-attachments/assets/71e16139-9427-4e90-b523-8d218f09ed9d
2024-09-17 08:45:44 +02:00
Simon Knott b0f15b320f
fix(recorder): reattach toolbar if it was unmounted by framework hydration (#32637)
Closes https://github.com/microsoft/playwright/issues/32632. A side
effect of Remix's hydration implementation is that it throws away the
entire DOM. This is broadly discussed in
https://github.com/remix-run/remix/issues/4822 - there might be a fix in
coming React versions, but who knows.
Besides breaking browser extensions, this also deletes our toolbar!
This PR fixes it by periodically checking in on `x-pw-glass`, and
remounting it if it was unmounted. Hacky but effective!
2024-09-17 08:37:49 +02:00
Pavel Feldman 47713e8a66
chore: make recorder tests pass in frozen mode (#32645) 2024-09-16 22:47:54 -07:00
Pavel Feldman 3bff7b6ab1
chore: preserve selected trace action in live trace (#32630) 2024-09-16 17:33:52 -07:00
Yury Semikhatsky 2a347b5494
chore: support launchPersistentContext with bidi (#32641) 2024-09-16 17:31:26 -07:00
Pavel Feldman 6dbde62a6b
chore: simplify signal handling while recording (#32624) 2024-09-16 14:39:36 -07:00
Pavel Feldman 92c6408b94
fix(recorder): address the react race condition (#32628) 2024-09-16 13:47:13 -07:00
Dmitry Gozman ce06a81aa6
feat: make npx playwright clear-cache public (#32638) 2024-09-16 12:54:20 -07:00
Max Schmitt 21d162c945
feat(client-certificates): add support for proxies (#32611)
Fixes https://github.com/microsoft/playwright/issues/32370
2024-09-16 17:57:33 +02:00
Max Schmitt b335b00a86
docs: add reference to locator strictness if or resolves to multiple elements (#32633) 2024-09-16 17:30:14 +02:00
Playwright Service feac957475
feat(webkit): roll to r2077 (#32636)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-16 17:18:01 +02:00
Anthony Roberts 71c43693ac
feat(reporter): add copy button for annotations (#31790)
Adds a copy-to-clipboard button for each annotation so that text can be
copied easily.
This re-uses the existing `CopyToClipboard` component and adds a `small`
variant that can be used inline. The icon size and colour have been
chosen to avoid being overwhelming when used inline.

Related to #30141 
I opted not to introduce the hover behaviour from #30749 as it's less
discoverable, but can understand why that might be favourable. Certainly
open to suggestions 😄

<img width="379" alt="Screenshot 2024-07-22 at 3 23 53 PM"
src="https://github.com/user-attachments/assets/3b9998cf-2e8d-40c9-9c8a-64eab3a9ed2e">
2024-09-16 07:57:11 -07:00
Max Schmitt 762e954599
devops: update GitHub Actions (#32634)
Fixes: 
<img width="2205" alt="image"
src="https://github.com/user-attachments/assets/0cd09784-6f0b-4331-9e08-315cf8614031">

For future reference: `pip install github-actions-cli &&
github-actions-cli update-actions --update`
2024-09-16 15:43:42 +02:00
Dmitry Gozman 268357238a
fix(expect): respect custom message in expect.poll (#32603)
Fixes #32582.
2024-09-16 00:10:06 -07:00
Max Schmitt c24ad36f86
docs(docker): fix Docker container permissions (#32621) 2024-09-16 07:39:36 +02:00
Simon Knott aeb4d182f7
feat(tracing): add .pwtrace to trace file extension (#32581)
Closes https://github.com/microsoft/playwright/issues/32226

I've updated every mention of `.trace.zip` except for the release notes.
2024-09-14 10:17:07 +02:00
Yury Semikhatsky 34876e9291
chore: cookies in intercepted bidi requests (#32623) 2024-09-13 18:29:35 -07:00
Matthew Jee f2a974b045
feat(api): add method to force garbage collection (#32383) 2024-09-13 23:09:36 +02:00
Playwright Service 5b28d2a84c
feat(firefox): roll to r1464 (#32614)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-13 18:12:43 +02:00
Playwright Service b82100adf5
feat(firefox-beta): roll to r1464 (#32615)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-13 18:12:35 +02:00
Max Schmitt 79cba7d704
chore: introduce option overrides on context/browser (#32606) 2024-09-13 17:34:34 +02:00
Simon Knott 9bb1c86f93
feat(test runner): don't run tests on --watch start (#32583)
Closes https://github.com/microsoft/playwright/issues/32580.
2024-09-13 17:24:38 +02:00
Max Schmitt 9e99c86f00
chore: unhide merge-reports command (#32605) 2024-09-13 16:13:23 +02:00
Playwright Service e3370c9eb0
feat(webkit): roll to r2075 (#32610)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-13 15:13:11 +02:00
Simon Knott 48c7fb6b06
feat(library): accept FormData in fetch (#32602)
Closes https://github.com/microsoft/playwright/issues/26520 by accepting
`FormData`, which became stable in Node.js in v21.
2024-09-13 13:21:02 +02:00
Pavel Feldman cd4dabef8b
chore: remove stray codegen signal handling (#32599) 2024-09-12 14:38:23 -07:00
Pavel Feldman 7e3348eb0e
chore: recorder is trace viewer experiment (#32598) 2024-09-12 13:39:44 -07:00
Pavel Feldman de08e729ae
chore: move recorder trace to action collector (#32597) 2024-09-12 12:42:28 -07:00
Pavel Feldman d051495c7a
chore: perform double click while recording (#32576) 2024-09-12 11:40:44 -07:00
Max Schmitt 5e086be36b
chore: freeze ffmpeg on macOS-12 (#32596) 2024-09-12 20:32:34 +02:00
Max Schmitt 8e82f53ceb
test: unskip various proxy tests (#32595)
Unskipping of various tests and revert the rest of
https://github.com/microsoft/playwright/pull/6350 since the upstream bug
has been fixed.
2024-09-12 20:31:22 +02:00
Simon Knott ef4be6afff
feat(test runner): make expect.extend immutable (#32366)
Changes `expect.extend` behaviour so that it doesn't mutate the global
instance and behaves closer to what users expect. This is formally a
breaking change, and I had to remove a test that asserts the breaking
behaviour.

TODO:
- [x] decide wether this is a separate method or a flag for
`expect.extend`
- [x] figure out if we need to change docs
2024-09-12 19:56:38 +02:00
Simon Knott c9f3eb158e
feat(ui): highlight output toggle button if terminal contains error (#32392)
Closes https://github.com/microsoft/playwright/issues/32368

<img width="412" alt="Screenshot 2024-08-30 at 13 22 39"
src="https://github.com/user-attachments/assets/76cadcd9-e92a-44d9-80fc-b4e04702e71e">
2024-09-12 19:40:40 +02:00
Playwright Service 470b1b4922
feat(chromium-tip-of-tree): roll to r1259 (#32588)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-12 13:46:33 +02:00
Playwright Service b1b33efebb
feat(chromium): roll to r1135 (#32591)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-12 13:46:15 +02:00
Max Schmitt 491678ada6
docs: release note fixes for 1.47 (#32589) 2024-09-12 12:51:30 +02:00
Teng Yang 6a0009f9ed
fix(trace-viewer): fix ui issue on network request details (#32553) 2024-09-12 12:26:51 +02:00
Max Schmitt dc5bbbf295
devops: remove macos-12 bots (#32587)
We stopped supporting macos-12 in 1.45, see the release notes and
https://github.com/microsoft/playwright/pull/31283.
2024-09-12 11:27:47 +02:00
Max Schmitt a838e74c61
devops: move macos runners to public infra (#32586) 2024-09-12 10:50:05 +02:00
Yury Semikhatsky d1926e2f9b
chore: do not store project name in expectations (#32575) 2024-09-11 15:15:10 -07:00
Yury Semikhatsky 678c454fea
test: update bidi expectations from recent run (#32574) 2024-09-11 14:59:28 -07:00
Yury Semikhatsky fd1f32556b
chore: run all tests with bidi by default (#32572)
Only use expectation files on CI to save resources
2024-09-11 14:24:32 -07:00
Dmitry Gozman 1981989aef
docs: mention variability of media codecs between platforms (#32569)
References #32558.
2024-09-11 13:35:17 -07:00
Yury Semikhatsky a8103abee6
chore: incremental bidi expectation update, ff expectations (#32570)
* Do not override expectations for the tests that didn't run or already
had expectations
* Sort expectations alphabetically
* Add firefox expectations
2024-09-11 13:33:25 -07:00
Dmitry Gozman 29a0f49e9b
chore(test runner): simplify code around running tasks (#32557)
This avoids complex boilerplate around `onConfigure`/`onEnd`/`onExit`
and managing the resulting status.
2024-09-11 13:09:00 -07:00
Playwright Service 6f52834f74
feat(webkit): roll to r2073 (#32563)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-11 20:39:01 +02:00
Max Schmitt 7458c3292c
fix(test-runner): do not consider retries for maxFailures (#32533)
Fixes https://github.com/microsoft/playwright/issues/26350
2024-09-11 20:35:26 +02:00
Yury Semikhatsky 1f0514536e
chore: add bidi test expectations in separate file (#32549)
Based on the expectations the tests that are expected to timeout or fail
will be skipped to save resources. The expectations can be manually
updated when corresponding feature is fixed.
2024-09-11 08:28:29 -07:00
Playwright Service aaac57b948
feat(webkit): roll to r2072 (#32550)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-11 13:02:03 +02:00
Dmitry Gozman 7335fa602c
fix(trace viewer): do not show multiple action points in iframes (#32537)
When action has an input target, we assume there is a target element in
one of the frames and show action point in its center.

Fixes #32453.
2024-09-11 03:04:03 -07:00
Yury Semikhatsky a4bd551597
docs: TestInfo.titlePath does not include project (#32548) 2024-09-10 16:52:12 -07:00
Dmitry Gozman 356517cddb
chore(test runner): extract LastRunReporter (#32540) 2024-09-10 12:14:44 -07:00
Dmitry Gozman b5d968fa0e
chore: make ReporterV2 a partial interface (#32532)
This makes it easier to write reporters by avoding empty methods.
2024-09-10 06:08:54 -07:00
Simon Knott ec40890fd8
fix(tracing): use page swap timestamp to find closest screenshot (#32512)
Follow-up to https://github.com/microsoft/playwright/pull/32248. When we
have it, we should use the page swap timestamp we get from Chromium to
find the closest screenshot.
2024-09-10 14:32:33 +02:00
Rui Figueira f8562e4ca7
chore: improve error message when Array.toJSON misbehaves (#32508)
Fixes: #32507
2024-09-10 04:14:24 -07:00
Max Schmitt 9fa06be49e
fix(ct): throw error if inline component is getting mounted (#32531)
What was happening?
- When we use CT, we go over the test files, look at the imports using
`tsxTransform.ts` and store them inside a map, these we feed into the
import registry which we build using Vite and have access inside the
browser
- In case of an inline component in the same file as where the test file
is, this is not happening.
- jsx-runtime via babel kicks in, transforms every JSX component in
something like that:

```
{
  __pw_type: 'jsx',
  type: [Function: MyInlineComponent],
  props: { value: 'Max' },
  key: undefined
}
```

this then gets passed into `wrapObject` which maps any function from the
Node.js side into expose function calls so they work inside the browser.
The assumption for `wrapObject` was to do it mostly for callbacks. So it
does for `type` - which is actually our component. We then pass this to
the React render function, which calls back the exposed function but we
never return anything, so it mounts `undefined`.

---

While there have been experiments from certain vendors to get the
'client only' code inside a server side file, we should throw for now to
not confuse users. We might revisit this in the future since Babel / TSX
doesn't support it outside of the box.

Fixes https://github.com/microsoft/playwright/issues/32167
2024-09-10 11:15:20 +02:00
Playwright Service 8995ace825
feat(firefox-beta): roll to r1463 (#32529) 2024-09-10 08:57:40 +02:00
Yury Semikhatsky c8a72d63ad
chore: run bidi firefox tests on ci (#32527) 2024-09-09 17:22:19 -07:00
Pavel Feldman 6d5889a52c
chore: revert the matcherResult in API (#32524) 2024-09-09 16:44:32 -07:00
Dmitry Gozman ae118674b8
fix(test runner): allow directory imports with path mapping (#32491)
We now hopefully align with `moduleResolution: bundler` tsconfig option,
allowing directory imports in every scenario, and allowing proper module
imports when not going through the type mapping.

This regressed in #32078. Fixes #32480, fixes #31811.
2024-09-09 14:01:20 -07:00
Dmitry Gozman 6bb005db85
fix(test runner): improve error message when not able to parse tsconfig (#32526) 2024-09-09 14:01:02 -07:00
Dmitry Gozman e6c5b6054d
test: fix project filter test (#32525)
It was erroneously passing projects separate by comma, which never
worked.
2024-09-09 14:00:51 -07:00
Max Schmitt e5d6ee5bd8
chore: merge fetch params on server side (#32518)
https://github.com/microsoft/playwright-python/pull/2546#discussion_r1750090592
2024-09-09 22:28:08 +02:00
Pavel Feldman 9a313eecc9
chore: roll expect and move it to third party (#32458) 2024-09-09 13:12:20 -07:00
Max Schmitt 4b5422a3c7
fix(ui-mode): use server side path separator (#32523)
Fixes https://github.com/microsoft/playwright/issues/32323
2024-09-09 22:07:28 +02:00
Playwright Service 363e79ee87
feat(webkit): roll to r2071 (#32521)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-09 20:07:37 +02:00
Yury Semikhatsky d030965688
chore: addInitScript and auth (unsuccessful) in bidi (#32500) 2024-09-09 10:13:26 -07:00
Max Schmitt 728083b435
chore: allow query as string in Python/.NET (#32516)
https://github.com/microsoft/playwright-python/issues/2497
2024-09-09 15:49:59 +02:00
Sander 4a53973fd0
docs(ct): vue + jsx and general improvements (#32212)
partial fix for:
https://github.com/microsoft/playwright/issues/31927#issuecomment-2267065378

---------

Signed-off-by: Sander <info@mesander.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-09-09 05:09:18 -07:00
Simon Knott cc9c4cdd9a
chore: fix flaky screenshot test (#32517)
In this test, the trace recording goes super fast. Sometimes, this means
that the recording is finished before the screen recorder got a chance
to take a screenshot. If that happens, the tests fail because we never
show a screenshot.
This PR fixes the flakiness by delaying the trace recording so that
there's always a screenshot taken.
2024-09-09 14:00:38 +02:00
Simon Knott 31e269ad06
feat(trace-viewer): show screenshot pointer (#32514)
Follow-up to https://github.com/microsoft/playwright/pull/32248. Adds a
glowing red circle that shows the click position. I made it glowing to
show that its position is inaccurate.
<img width="964" alt="Screenshot 2024-09-09 at 11 33 45"
src="https://github.com/user-attachments/assets/1903071d-6dc0-46c7-9951-844e49a51f35">
2024-09-09 14:00:22 +02:00
Max Schmitt ae02331d00
test: fix stress tests bots (#32513) 2024-09-09 12:52:40 +02:00
Max Schmitt 718bd9b35f
devops: run BiDi tests (#32493) 2024-09-07 09:16:42 +02:00
Yury Semikhatsky f3ada9c654
chore: wheel input in bidi (#32499) 2024-09-06 17:10:14 -07:00
Yury Semikhatsky 37bc485827
chore: remove browser-specific bidi hacks (#32498)
Those were just workarounds for browser-specific bugs, they should be
fixed upstream.
* individual mouse down/up/down/up events don't trigger dblclick event
in Firefox
* setContent throws when document.open/write is called in the utility
context in Firefox
2024-09-06 16:40:24 -07:00
Yury Semikhatsky a113553f14
test: allow running oopif test without newBrowserCDPSession (#32496) 2024-09-06 13:49:37 -07:00
Yury Semikhatsky df2bc2d0dc
test: worker interception for existing workers (#32494)
Failing test for https://github.com/microsoft/playwright/issues/32355
2024-09-06 13:17:49 -07:00
Yury Semikhatsky 11441c0fe1
fix: add missing await in adoptIfNeeded (#32497)
Otherwise it throws in Bidi.
2024-09-06 13:17:32 -07:00
Yury Semikhatsky d85527e9f6
test: some tests for expected API behavior (#32495)
Adding some tests discussed in
https://github.com/microsoft/playwright/pull/32434
2024-09-06 13:13:44 -07:00
Dmitry Gozman 1402dee9e6
Revert "fix(test runner): align with typescript behaviour for resolving index.js and package.json through path mapping (#32078)" (#32492)
This reverts commit effb1ae234.

This broke path mapping into directories in ESM mode. References #32480.
2024-09-06 12:08:10 -07:00
Simon Knott 3fe1263643
feat(trace viewer): show Screenshot instead of Snapshot (#32248)
Closes https://github.com/microsoft/playwright/issues/23964.

Trace snapshots are a best-effort snapshots of the browser DOM, but we
can't guarantee them to be exactly what the browser showed. One example
of this is `canvas` elements, where you just can't see their contents.
That makes snapshots useful, but not perfect.

For those cases where the snapshot doesn't show everything, this PR
introduces a new setting to show a screenshot instead. You won't be able
to scroll or inspect the DOM or select a locator anymore. But if the
snapshot was missing something, or displaying something wrong, you can
now check the screenshot instead.
2024-09-06 16:24:33 +02:00
Max Schmitt ed303208b3
test: update to android-35 SDK (Android 15) (#32430) 2024-09-06 14:27:56 +02:00
Simon Knott 0e3f4736cc
fix(test runner): always show all projects in selection (#32450)
Follow-up to
https://github.com/microsoft/playwright/pull/32156#discussion_r1741628770,
alternative solution to
https://github.com/microsoft/playwright/pull/32425.

Ensures we always show all projects in the watch mode project selector
by performing the initial `listTests` without any filters, and using its
result for the project selector.
2024-09-06 11:35:20 +02:00
Max Schmitt a8f67a42b8
docs(dotnet): fix wrong snippets (#32484)
Fixes https://github.com/microsoft/playwright-dotnet/issues/2994
2024-09-06 11:27:35 +02:00
Simon Knott 5d4a65b318
docs: update release notes for 1.47 to our changes from yesterday (#32482)
I'll also cherry-pick this into the release branch and update
playwright.dev.
2024-09-06 10:28:17 +02:00
Pavel Feldman a52eb0c9a0
chore: expose matcherResult on TestError (#32455) 2024-09-05 21:36:51 -07:00
Pavel Feldman 16cef9901d
chrome: cache tsconfig for folder (#32477)
Fixes https://github.com/microsoft/playwright/issues/32459
2024-09-05 21:36:13 -07:00
Yury Semikhatsky f0e13164d7
chore: split firefox and chromium bidi implementations (#32478) 2024-09-05 18:31:56 -07:00
Yury Semikhatsky 752b171a13
chore: support bidi connection to chromium (#32474) 2024-09-05 14:56:07 -07:00
Yury Semikhatsky 1989589edd
docs: update browsers version in release notes (#32475) 2024-09-05 13:59:54 -07:00
Dmitry Gozman 1ba3db6864
chore: implement clear-cache through plugins (#32471)
Also switches it to task runner.
2024-09-05 13:50:16 -07:00
Dmitry Gozman d4c77ce260
chore: make find-related-test-files work through plugins (#32465)
Also switches it to the task runner.
2024-09-05 06:52:11 -07:00
Playwright Service 5127efdc2a
feat(chromium): roll to r1134 (#32470)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-05 14:57:20 +02:00
Simon Knott 895d017fb8
chore: update browser patches as of July, 25th, 2024 (#32468) 2024-09-05 13:44:58 +02:00
Simon Knott 29f1541b14
chore: roll stable test runner to 1.47 beta (#32469) 2024-09-05 13:44:22 +02:00
Simon Knott 0f636116e2
chore: mark 1.48.0-next (#32466) 2024-09-05 12:57:16 +02:00
Simon Knott 0a49c05e2d
chore(test runner): document that --only-changed on CI needs history (#32461)
Closes https://github.com/microsoft/playwright/issues/32452

`--only-changed=$GITHUB_BASE_REF` needs the base ref available locally
to work properly. `fetch-depth: 0` does that, see
https://github.com/actions/checkout?tab=readme-ov-file#fetch-all-history-for-all-tags-and-branches.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-09-05 12:13:09 +02:00
Simon Knott a8139b5d77
docs: add release notes for 1.47 (#32463) 2024-09-05 11:57:14 +02:00
Dmitry Gozman 91012833c6
chore: move 'dev-server' extensibility point to plugin (#32448)
Instead of plumbing it through a custom unspecified config field, make
it a part of plugin interface.

Additionally, use task runner for starting/stopping dev server.
2024-09-05 02:22:27 -07:00
Playwright Service 255143e201
feat(webkit): roll to r2070 (#32451)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-04 20:41:06 +02:00
Yury Semikhatsky 9a2c60a77c
chore: identify largest gaps in Bidi API (#32434)
This pull request introduces initial support for the WebDriver BiDi
protocol in Playwright. The primary goal of this PR is not to fully
implement BiDi but to experiment with the current state of the
specification and its implementation. We aim to identify the biggest
gaps and challenges that need to be addressed before considering BiDi as
the main protocol for Playwright.
2024-09-04 11:36:52 -07:00
Pavel Feldman a87426ee0d
Update bug.yml
Signed-off-by: Pavel Feldman <pavel.feldman@gmail.com>
2024-09-04 09:17:43 -07:00
Kuba Janik ee91bdc585
feat(ui-mode): display list of query params in request tab (#32443) 2024-09-04 07:54:44 -07:00
dependabot[bot] b43915f4cc
chore(deps): bump actions/download-artifact from 3 to 4.1.7 in /.github/workflows (#32436) 2024-09-04 13:05:51 +02:00
Dmitry Gozman 60631409d6
chore: make dev server only use public config (#32441)
In preparation to make it a part of a plugin.
2024-09-04 01:29:55 -07:00
Dmitry Gozman d7393f998e
chore: simplify settings management in UI mode (#32440) 2024-09-04 01:05:07 -07:00
Simon Knott b3d767fa14
fix(trace viewer): fix memory leak (#32379)
In the `visit` method, we currently cache the rendered HTML for every
walked node. This re-use works well for traces that consist mostly of
references to earlier snapshots.
But for traces that don't share much, this is a large memory overhead
and leads to the memory crash documented in
https://github.com/microsoft/playwright/issues/32336. For the algocracks
amongst you, the current memory usage for an html tree $h$ is
$\mathcal{O}(|h| * \text{height}(h))$.

This PR removes that cache from the nodes and replaces it with a
snapshot-level cache, fixing the memory crash.
Traces *without* reference should not see a performance impact from
this.
Traces *with* references will have slower initial rendering, but
re-rendering maintains speed because of the snapshot-level cache.

Closes https://github.com/microsoft/playwright/issues/32336

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-09-04 09:57:15 +02:00
Playwright Service 2fabd15fef
feat(firefox): roll to r1463 (#32439)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-04 08:49:10 +02:00
Yury Semikhatsky d7b9cf21db
chore: ignore third-party execution contexts (#32437)
* Only track main and utility world contexts
* Properly update click metadata
2024-09-03 23:00:59 -07:00
Dmitry Gozman cfae7f755c
chore(test runner): always go through internal reporter (#32426)
This way we guarantee the API contract and do not miss errors because we
forgot to call `onBegin()`.
2024-09-03 22:38:02 -07:00
Pavel Feldman 446ed72878
docs: revert typo (#32433) 2024-09-03 10:18:40 -07:00
Yury Semikhatsky b75483bbb4
Revert "docs: deprecate: Request.serviceWorker() (#32136)" (#32432)
This reverts commit b7ed4d7b9e.
2024-09-03 10:18:20 -07:00
Yury Semikhatsky 565aed6c39
Revert "chore: enforce tags format via typescript types (#32384)" (#32431)
After API review we decided to revert it:
* VSCode extension and UI mode users already get the (runtime) error if
the tag is not prefixed
* The typescript error message is not very nice
* The type change would break those clients that generate tests with
tags passed as string

This reverts commit 90e7b9ebac.
2024-09-03 10:07:08 -07:00
Playwright Service 9f466a1ead
feat(chromium-tip-of-tree): roll to r1256 (#32423)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-03 17:12:54 +02:00
Simon Knott 201bad75d3
chore(test runner): rebase watch mode onto TestServerConnection (#32156)
Closes https://github.com/microsoft/playwright/issues/32076.

This PR rewrites `watchMode.ts` to use `TestServer` under the hood. It's
essentially a complete rewrite, so don't pay too much attention on the
old implementation. Note that there's no changes to tests, so all
behaviour we have specced out there still works.

To make this work without a superfluous WebSocket connection, I had to
refactor `TestServerConnection` a little. Originally, I pulled this into
a [separate PR](https://github.com/microsoft/playwright/pull/32132), but
then realised how small the refactoring is. So it's in this PR now. Let
me know if you'd like to land it separately.
2024-09-03 15:15:44 +02:00
dependabot[bot] 53bf9534ec
chore(deps): bump micromatch from 4.0.5 to 4.0.8 in /packages/playwright/bundles/expect (#32399) 2024-09-03 14:52:52 +02:00
Playwright Service 847d29dd86
feat(webkit): roll to r2069 (#32422)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-03 13:28:15 +02:00
Playwright Service 221b77309c
feat(webkit): roll to r2068 (#32417)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-03 09:54:14 +02:00
Przemyslaw Malolepszy b8c4a477ff
chore(docs): fix APIResponse.headersArray() desc (#32375) 2024-09-03 09:01:01 +02:00
Kevin Jagodic 787da9b5a5
docs(mock): fix routeFromHAR() arguments for Java (#32409) 2024-09-03 08:57:57 +02:00
Playwright Service d145c4c91c
feat(webkit): roll to r2067 (#32415) 2024-09-03 06:59:54 +02:00
dependabot[bot] 7318293355
chore(deps-dev): bump svelte from 4.2.9 to 4.2.19 (#32398) 2024-09-02 15:16:46 +02:00
Simon Knott f62f85ba51
fix(test runner): fix types to allow calling custom matchers on expect.poll (#32407)
The `'should support custom matchers'` test asserts that the
functionality works, but it was a type error. This PR updates the types
so that it's allowed.

Closes https://github.com/microsoft/playwright/issues/32408

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-09-02 13:42:15 +02:00
Playwright Service 5c2e9962b4
feat(chromium-tip-of-tree): roll to r1255 (#32376)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-02 09:54:58 +02:00
Playwright Service d9016e506e
feat(chromium): roll to r1133 (#32391)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-09-02 09:49:38 +02:00
Simon Knott 3f09d10601
fix(test runner): perform shallow clone check in config directory (#32299)
Our CI operates on shallow clones. In vcs.ts, we perform a check for
shallow clones in `process.cwd()` instead of the test directory. This
makes the test in
3c208aeeff/tests/playwright-test/only-changed.spec.ts (L201)
failing in CI, but only for PRs. The fix is to perform the check on. the
test directory.
2024-09-02 09:11:04 +02:00
Simon Knott cf8c14f884
feat(html reporter): open html attachments in new tab (#32389)
Closes https://github.com/microsoft/playwright/issues/32281.

HTML attachments get a linkified name that opens the attachment in a new
tab.
2024-09-02 08:35:53 +02:00
Kuba Janik a6b320e362
fix(ui-mode): format request body when headers are lower case (#32395)
Resolves https://github.com/microsoft/playwright/issues/32396

Currently, the request body is not formatted when content type header is
lower case (`content-type`). Even though the value is
`application/json`.

It happens because we are looking only for `Content-Type` header
ignoring headers that are lower case.

<img width="674" alt="363197933-5178ec23-b9cf-46b5-8284-e8d4d730b036"
src="https://github.com/user-attachments/assets/0ef01b52-7dd8-4f33-b836-9adb86f94cc9">
2024-08-30 16:21:51 +02:00
Simon Knott ed5c21b827
fix(ui): respect --output param (#32351)
Closes https://github.com/microsoft/playwright/issues/32331

We're already passing the `outputDir` param to the UI, but the UI isn't
passing it back to the TestServer. This PR fixes that. I've added it to
`listTests`, which is requires to that
`TestServerDispatcher#_ignoredProjectOutputs` is populated with the
correct output dir. And i've added it to `runGlobalSetup`, which is what
the bug report was about.
2024-08-30 08:29:49 +02:00
Yury Semikhatsky 90e7b9ebac
chore: enforce tags format via typescript types (#32384)
Leverage [template literal
types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html).

Fixes https://github.com/microsoft/playwright/issues/32382
2024-08-29 14:16:49 -07:00
Simon Knott 0a40862bc8
chore(docs): fix typo (#32372) 2024-08-29 14:16:29 -07:00
Pavel Feldman 74a8e59096
chore: allow recorder rewrite annotations (#32381) 2024-08-29 14:16:01 -07:00
Playwright Service 6763d5ab6b
feat(chromium-tip-of-tree): roll to r1254 (#32337) 2024-08-28 15:59:31 -07:00
Yury Semikhatsky 896190edbb
Revert feat(addInitScript): support cjs modules (#32364)
Reverting https://github.com/microsoft/playwright/pull/32282 and
https://github.com/microsoft/playwright/pull/32240.
2024-08-28 15:39:48 -07:00
Yury Semikhatsky d8137f228f
docs: update snippets to fix typescript errors (#32363)
Reference: https://github.com/microsoft/playwright/issues/9468
2024-08-28 14:24:01 -07:00
Yury Semikhatsky 22fe985c54
docs: add SUPPORT.md (#32362) 2024-08-28 11:01:34 -07:00
Yury Semikhatsky 5271fe1f26
chore: remove unused request param from route.continue (#32307) 2024-08-28 08:24:44 -07:00
Playwright Service d61b207ce3
feat(webkit): roll to r2066 (#32343)
Fixes https://github.com/microsoft/playwright/issues/30305

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
2024-08-28 08:23:39 -07:00
Pavel Feldman ec681ca78c
chore: pass explicit recorder app factory (#32349) 2024-08-27 20:24:19 -07:00
Pavel Feldman 0b5456d00b
chore: perform action based on frame path (#32347) 2024-08-27 17:17:57 -07:00
Yury Semikhatsky acd2a4ddad
docs: global beforeEach/beforeAll hooks (#32348)
Fixes https://github.com/microsoft/playwright/issues/9468
2024-08-27 17:04:53 -07:00
Yury Semikhatsky 0fd97cb9ed
tests: delete flaky COOP test (#32346)
The scenario that the test covers is inherently racy and has been flaky
in all browsers.

Fixes https://github.com/microsoft/playwright/issues/32107
2024-08-27 14:53:27 -07:00
Pavel Feldman a1df11011c
chore: split recorder into files (#32345) 2024-08-27 14:10:21 -07:00
Pavel Feldman bc87467b25
chore: generate simple dom descriptions in codegen (#32333) 2024-08-27 11:52:14 -07:00
Yury Semikhatsky 3f085d5689
chore: remove same-site expectations for old browsers (#32334) 2024-08-26 18:41:58 -07:00
Pavel Feldman 177576a51b
chore: add simple dom util (#32332) 2024-08-26 16:28:40 -07:00
Pavel Feldman 6f55b57e5a
chore: move codegen into its own folder (#32330) 2024-08-26 15:24:02 -07:00
Yury Semikhatsky 888a5b53e7
docs: avoid confustion with incognito mode (#32327)
Fixes https://github.com/microsoft/playwright/issues/32321
2024-08-26 11:02:41 -07:00
Pavel Feldman 4340d153df
chore: deprecate locator.frameLocator() (#32306) 2024-08-26 10:28:54 -07:00
Pavel Feldman 3d9342aa77
chore: update removeAllListeners docs (#32305)
Closes https://github.com/microsoft/playwright/issues/31474
2024-08-26 09:29:02 -07:00
Max Schmitt 67d3d5f203
fix(clock): don't throw for |null| or |undefined| callbacks (#32309)
Fixes https://github.com/microsoft/playwright/issues/32293

This aligns it how Chromium and other browsers are doing it.
2024-08-26 09:26:38 -07:00
Max Schmitt 54709880c2
test: update Modernizir expectations (#32308)
Looks like `hiddenscroll` was different when an external monitor was
connected.
2024-08-26 08:32:22 -07:00
Max Schmitt 596f497633
fix: don't throw error on about:blank when blocking ServiceWorker (#32310)
Fixes https://github.com/microsoft/playwright/issues/32292
2024-08-26 08:27:21 -07:00
Playwright Service 5acd2dbf48
feat(webkit): roll to r2065 (#32322)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-26 10:25:59 +02:00
Simon Knott 1511d8643e
fix(test runner): expect.poll error reporting should handle non-expect errors (#32257)
Closes https://github.com/microsoft/playwright/issues/32256

We were expecting all errors to be of type `ExpectError`, but apparently
`expect` propagates rejections in the polling functions right through.
So we also need to handle that case.

I wonder if we have more cases of this. Would it make sense to enable
`useUnknownInCatchVariables` in TypeScript?
2024-08-26 09:39:25 +02:00
Playwright Service 9c81eab329
feat(webkit): roll to r2064 (#32319) 2024-08-26 06:56:08 +02:00
Max Schmitt 54c487c939 test: unskip 'should use ipv6 proxy' for Docker 2024-08-24 11:49:18 +02:00
Dmitry Gozman abe6c04a54
chore: remove noWaitAfter from selectOption (#32283)
This follows removing this option from other methods in v1.46. The two
methods still supporting `noWaitAfter` are `click` and `press`.
2024-08-23 14:50:43 -07:00
Pavel Feldman 9d86bc5336
fix(dupe): render dupe test error indicator (#32303)
Fixes https://github.com/microsoft/playwright/issues/32093
2024-08-23 14:33:37 -07:00
Pavel Feldman 37eb66df10
chore: extract performAction in recorder (#32279) 2024-08-23 10:19:44 -07:00
Pavel Feldman 4edc076935
chore: load env from playwright.env when running codegen (#32280) 2024-08-23 10:19:36 -07:00
Playwright Service 8703dd4f06
feat(webkit): roll to r2063 (#32295) 2024-08-23 17:57:18 +02:00
Max Schmitt 0d4d5758c4
test: update Modernizer tests to Safari 18 (#32290)
Fixes https://github.com/microsoft/playwright/issues/32288

---------

Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-08-23 16:59:55 +02:00
Max Schmitt 787f20c920
chore: fix doclint (#32294) 2024-08-23 16:26:39 +02:00
Max Schmitt 1b220c5289
chore: remove Chromium Windows proxy hacks (#31724)
Fixes https://github.com/microsoft/playwright/issues/17252
2024-08-23 15:17:00 +02:00
Dmitry Gozman 9a5b72d02a
chore: remove TestInfoImpl._stages (#32285)
This is a preparation to a bigger stages cleanup.
2024-08-23 06:16:18 -07:00
Simon Knott 3fb33e7144
chore(ui): decouple TestServerConnection from websocket transport (#32274)
Preparation for https://github.com/microsoft/playwright/issues/32076.
2024-08-23 14:58:34 +02:00
Dmitry Gozman 785ca19e51
fix(webserver): prefix each line of webserver output (#32286)
This unflakes various `web-server.spec.ts` tests and makes the output
more consistent.
2024-08-23 03:52:27 -07:00
Max Schmitt 8c0e173d6c
test: rebase modernizer Linux tests (#32268) 2024-08-23 12:51:49 +02:00
Dmitry Gozman 3a75f23ea1
fix(addInitScript): require non-undefined arg to trigger commonjs module (#32282) 2024-08-23 02:48:56 -07:00
Simon Knott 0b9c036505
chore(ui): add test for font preview (#32225)
Adds a test for the font preview feature.
2024-08-22 17:56:07 +02:00
Playwright Service 947fbc8590
feat(chromium-tip-of-tree): roll to r1253 (#32266)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-22 17:43:39 +02:00
Simon Knott 850436c656
chore(ui): move TeleSuiteUpdater into testIsomorphic (#32273)
Preparation for https://github.com/microsoft/playwright/issues/32076.
2024-08-22 17:29:10 +02:00
Max Schmitt 16e76cb71a
fix(client-certificates): errors during http2 TLS handshake (#32258) 2024-08-22 15:13:54 +02:00
Simon Knott 5368fd7ca7
fix(only-changed): exit successfully if there were no changes (#32197)
Closes https://github.com/microsoft/playwright/issues/32180

I was briefly wondering if we should output a log line a la "no tests
found", but my understanding is that that's the reporters job - so I
didn't change anything in that regard.
2024-08-22 14:53:00 +02:00
Dmitry Gozman 7758b330b1
fix(ui mode): make sure that reload does correctly restart the webserver (#32263)
Fixes #32103.
2024-08-22 05:48:31 -07:00
Dmitry Gozman dc4a8e48eb
docs(fixtures): explain an option array value edge case (#32261)
Closes #32033.
2024-08-22 05:47:19 -07:00
Playwright Service f74c6d77db
chore(driver): roll driver to recent Node.js LTS version (#32264) 2024-08-22 12:07:44 +02:00
Max Schmitt 666a8f22cf
chore: fix api.json serializer for language ports (#32260)
Fixes https://github.com/microsoft/playwright/issues/32241
2024-08-22 10:15:47 +02:00
Max Schmitt e3480d1886
test: add test for TLS renegotiation and client-certificates (#32252) 2024-08-22 08:42:09 +02:00
Dmitry Gozman 571f25a7d3
fix(role): hidden pseudos should not contribute to accessible name (#32251) 2024-08-21 11:14:41 -07:00
Dmitry Gozman d5a7495041
feat(addInitScript): support cjs modules when passing both path and arg (#32240)
This works with scripts bundled by:
- `esbuild entrypoint.ts --bundle --format=cjs --outfile=injected.js`
- webpack with a typical config
  ```js
  module.exports = {
    entry: { 'injected': './entrypoint.js', },
    output: {
      path: require('path').resolve(__dirname),
      filename: '[name].js',
      libraryTarget: 'commonjs2',
    },
  };
  ```
2024-08-21 09:46:38 -07:00
Guillaume M 837e2a883b
docs(browsers): fix typo (#32250) 2024-08-21 17:35:47 +02:00
Yury Semikhatsky 918dbe5e3a
chore: start listening for navigation events before navigation starts (#32237)
There is a chance in case of cross-process navigation that the
navigation event comes before `navigateFrame` finishes.
2024-08-21 08:34:55 -07:00
Max Schmitt 6512bccffd
docs(best-practises): add note about tsc (#32245) 2024-08-21 11:37:53 +02:00
Dmitry Gozman b66cb6caaa
docs(evaluate): improve the guide (#32222) 2024-08-21 01:31:41 -07:00
Pavel Feldman 109cab66f1
chore: extract recorder dialog into a class (#32233) 2024-08-20 10:56:55 -07:00
Pavel Feldman fc4d8f2bb6
chore: roll codicon (#32234) 2024-08-20 10:56:46 -07:00
Dmitry Gozman b4a9b247b4
fix(role): make sure to ignore style/script/noscript/template (#32231)
Even when these are a part of a hidden `aria-labelledby` traversal, all
browsers ignore them anyway.
2024-08-20 09:02:23 -07:00
Simon Knott b599335404
chore(ui): enable react/recommended lint rules (#32214)
Closes https://github.com/microsoft/playwright/issues/32159. I
originally set out to enable Strict Mode for our React UI, but found a
way better thing: Enabling the lint rules we had already installed!

`eslint-plugin-react` is already in of our `package.json`, and this PR
enables it and fixes some of the reported issues. Most of them are
around the `key` prop which is mostly about performance, but there's
also fixes for misspelled `data-testid` props.
2024-08-20 14:16:28 +02:00
Simon Knott 244761a3a2
chore(docs): Rework CI docs (#31988)
This PR moves around some of our CI docs. It moves the GitHub actions
docs from `ci-intro.md` to `ci.md`, reduces `ci-intro.md` to be an
introduction, adds a mention of Sharding to the best practices, and adds
a section on `--only-changed` called "Fail-Fast". Each of those changes
is a separate commit, to make this a little easier to review. If we find
any of those to commits to be contentious, i'll pull them out into
individual PRs.

While rolling this to playwright.dev, we'll also make the following
changes to its sidebar:
- move the `ci.md` document from the "Integrations" section to the
"Playwright Test" section
- make "Best Practices" the last item of the "Getting Started" section

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Yury Semikhatsky <yurys@chromium.org>
2024-08-20 09:03:02 +02:00
Kuba Janik f7e0bd3098
feat(ui-mode): add font preview to network tab (#32209)
Resolves https://github.com/microsoft/playwright/issues/32218

Currently, fonts are displayed as a raw binary file which does not give
any information to the users.
I replaced it with a simple font preview similar to the one found in the
dev tools of web browsers.
It is not a major feature but I think it is a nice addition and it might
be useful to somebody.

<img width="1043" alt="Screenshot 2024-08-17 at 18 33 46"
src="https://github.com/user-attachments/assets/a6cc7b57-7ea8-4a54-869d-57a44712597b">


https://github.com/user-attachments/assets/e52d9a72-fb2c-43c7-bfee-3d6d6edc6b6a
2024-08-20 08:28:02 +02:00
Dmitry Gozman 5271c26af1
fix(trace viewer): do not serve resources with x-unknown content type (#32219)
`x-unknown` is used as a placeholder for "no content-type" in the har.
We should not send it to the browser, because it is meaningfully
different from not sending `Content-Type` header. For example, Chromium
refuses to interpret stylesheets served with `x-unknown` content type.

Fixes https://github.com/microsoft/playwright-java/issues/1651.
2024-08-19 10:29:51 -07:00
Playwright Service 18694f6843
feat(webkit): roll to r2062 (#32147) 2024-08-19 19:29:23 +02:00
Sander c87ca052d1
fix(ct): vue jsx component.update type (#32213)
partial fix for:
https://github.com/microsoft/playwright/issues/31927#issuecomment-2267065378

The options object wasn't treated as partial, unlike in other
frameworks, which led to the `component.update({ props: {} })` type
being selected instead the `component.update(<Component prop={} />)`
during jsx usage.
2024-08-19 05:50:25 -07:00
Max Schmitt 010778f6c5
feat(client-certificates): allow passing certificates from memory (#32210) 2024-08-19 09:24:32 +02:00
Max Schmitt 74f5ce5489
docs: store parent type reference in documentation.js (#32215) 2024-08-19 09:11:20 +02:00
Max Schmitt faf4853259
chore: validate client-certificates on context creation (#32168) 2024-08-19 09:02:14 +02:00
Playwright Service 570e05699e
feat(chromium-tip-of-tree): roll to r1250 (#32202)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-17 10:56:18 +02:00
Max Schmitt 743565ee3e
chore: generate self-signed certificates for socks proxy (#32192) 2024-08-16 20:21:05 +02:00
Simon Knott 3e6bba0b79
fix(only changed): make only-changed work together with list mode (#32196)
Closes https://github.com/microsoft/playwright/issues/32161

Turns out we were wrong in
https://github.com/microsoft/playwright/pull/31727#discussion_r1685793870!

Adds support for `--only-changed` in combination with `--list` by
removing our code to prevent that.
2024-08-16 17:12:45 +02:00
Dmitry Gozman c4bb24f02f
feat(test runner): record trace after a test-scoped fixture teardown times out (#32160)
Fixes #30718, fixes #31537.
2024-08-16 08:03:02 -07:00
Dmitry Gozman e17d1c498b
fix(test runner): timeout in fixture teardown should not prevent other slots (#32157)
When two fixtures have different time slots, timeout in the first one
should not prevent the second one from tearing down.

Similarly, timeout in afterEach hook should not prevent fixture
teardowns.
2024-08-16 04:25:00 -07:00
Simon Knott 06ffdd61c9
fix(only-changed): show nice error message about shallow clones (#32189)
Closes https://github.com/microsoft/playwright/issues/32188

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-08-16 11:41:01 +02:00
Dmitry Gozman 1537d3c2de
chore(test runner): make 'debug' an explicit option internally (#32154)
This allows any time slot that has a legitimate timeout of zero to be
updated later on. See test for an example.

Previously, setting timeout to zero at any moment was considered a
"debug mode" and any subsequent timeouts were ignored.
2024-08-16 01:44:37 -07:00
Rui Figueira b2ccfc3d01
chore(trace-viewer): support opening a source location in embedded trace viewer (#32175)
Related: https://github.com/microsoft/playwright-vscode/pull/513
2024-08-15 14:13:11 -07:00
Playwright Service e7b7c715b0
feat(chromium): roll to r1131 (#32174)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-15 20:41:27 +02:00
Max Schmitt a1d32d997c
fix(client-certificates): improve close handling from target and proxy (#32158) 2024-08-15 10:21:10 +02:00
Max Schmitt aac3a84321
fix(client-certificates): stall on tls handshake errors (#32163)
Extracted from https://github.com/microsoft/playwright/pull/32158.
2024-08-15 08:51:40 +02:00
Debbie O'Brien f927495791
docs: release video and trace viewer video (#32164) 2024-08-14 23:20:19 +02:00
Yury Semikhatsky 60900f8541
chore(webkit): add listeners directly without eventsHelper (#32149)
The listeners are never removed, so there is no point in wrapping them
with the helper
2024-08-14 08:38:49 -07:00
Max Schmitt 4daf5c2303
fix(client-certificates): when server does tls renegotiation (#32155)
Certain https servers like Microsoft IIS aka. TLS servers do the TLS
renegotiation after the TLS handshake. This ends up in two
`'secureConnect'` events due to an upstream Node.js bug:
https://github.com/nodejs/node/issues/54362

Drive-by: Move other listeners like `'close'` / `'end'` to `once()` as
well.

Relates https://github.com/microsoft/playwright/issues/32004
2024-08-14 15:11:29 +02:00
Playwright Service 856c4509a2
feat(chromium-tip-of-tree): roll to r1249 (#32148)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-14 00:46:53 +02:00
Bryant Ung 3280ec5ee3
doc(release notes): Fix 1.46 release notes typos (#32145) 2024-08-13 15:24:47 -07:00
Dmitry Gozman f8eef3897c
chore: move urlMatch to isomorphic (#32142)
To be reused in injected code.
2024-08-13 12:47:02 -07:00
Yury Semikhatsky 6cc53cfce6
chore: move output parsing to concrete browsers (#32129) 2024-08-13 12:20:41 -07:00
Kuba Janik 0588834307
feat: allow URLSearchParams and string as params in APIRequestContext (follow-up) (#32143)
Follow-up to https://github.com/microsoft/playwright/pull/32120

I made some changes suggested by @yury-s in the previous PR that make a
lot of sense:
- added an example to the documentation
- improved tests
  - check params on the client and server end
  - reverted to non-English characters being used as params
2024-08-13 10:39:56 -07:00
Max Schmitt b7ed4d7b9e
docs: deprecate: Request.serviceWorker() (#32136) 2024-08-13 15:59:30 +02:00
Yury Semikhatsky a28f51a0f3
chore: use base BrowserType to reference browser types (#32125) 2024-08-12 22:20:58 -07:00
Kuba Janik 308381eeae
feat: allow URLSearchParams and string as params in APIRequestContext (#32120) 2024-08-12 14:22:03 -07:00
Rui Figueira 3d69c591d3
fix(web): use currentTheme instead of settings in toggleTheme (#32104) 2024-08-12 13:19:30 -07:00
Yury Semikhatsky 2ae196f708
fix(docs): API types do not extend EventEmitter (#32124)
Fixes https://github.com/microsoft/playwright/issues/32097
2024-08-12 11:22:48 -07:00
Simon Knott edd1894ac6
fix(test runner): run project dependencies of --only-changed test files (#32094)
Closes https://github.com/microsoft/playwright/issues/32070. We were
applying `additionalFileMatcher` not just to `filteredProjectSuites`,
but also to `projectSuites`. `projectSuites` is where we take dependency
projects from, though - so `--only-changed` led to empty dependency
projects, resulting in the reported bug.

The fix is to only apply `additionalFileMatcher` on
`filteredProjectSuites`.
2024-08-12 17:26:01 +02:00
Max Schmitt cae779b74f
docs: recommend Ubuntu 24.04 in Docker images (#31435) 2024-08-12 16:39:56 +02:00
Max Schmitt 0d575b4ef6
chore: less 'as any' in html-reporter (#32117)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Simon Knott <info@simonknott.de>
2024-08-12 15:17:42 +02:00
Simon Knott effb1ae234
fix(test runner): align with typescript behaviour for resolving index.js and package.json through path mapping (#32078)
Supercedes https://github.com/microsoft/playwright/pull/31915, closes
https://github.com/microsoft/playwright/issues/31811.

When TypeScript resolves a specifier via path mapping, it does not
interpret `package.json`. If path mapping resolves to a directory, it
only looks at the `index.js` file in that directory if it's in CommonJS
mode.

We need to mirror this in our `esmLoader.ts`.

---------

Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-08-12 15:05:19 +02:00
Simon Knott c8cc4f9c8b
chore(ui): update to react 18 (#32079)
Part of https://github.com/microsoft/playwright/issues/31863. Updates
most of our React usage to React 18. `recorder` doesn't seem to like it
yet. I suspect that some of our code isn't compatible with concurrent
mode, i've investigated that in
https://github.com/microsoft/playwright/pull/32101.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-08-12 13:50:11 +02:00
Dmitry Gozman a30a8805c9
fix(expect): account for timeout during the first locator handler check (#32095)
Also considered an alternative to not perform the locator handler check
during one-shot, but that would be somewhat against the promise of the
locator handler that is supposed to run **before** every expect check.

Fixes #32089.
2024-08-12 01:57:15 -07:00
Max Schmitt ba8f94df56
chore(docs): remove unused generateToc function (#32111) 2024-08-12 10:56:59 +02:00
Simon Knott 45c2e8a3ed
chore(recorder): update to React 18 (#32101)
Part of https://github.com/microsoft/playwright/issues/31863. Updates
`recorder` to use React 18.
2024-08-12 09:19:28 +02:00
Playwright Service e8d845be64
feat(webkit): roll to r2061 (#32109) 2024-08-10 11:44:32 +02:00
Playwright Service 4d26036b7b
feat(webkit): roll to r2060 (#32082)
Reference: https://github.com/microsoft/playwright/pull/32108
2024-08-09 15:31:35 -07:00
Yury Semikhatsky d73c0ba689
test: skip COOP navigation test on wk linux (#32108)
Reference: https://github.com/microsoft/playwright/issues/32107
2024-08-09 15:30:56 -07:00
Dmitry Gozman 9b3e0e5667
chore: simplify binding result dispatch (#32092)
We can now pass an Error object through evaluate.
2024-08-09 03:46:52 -07:00
Max Schmitt 98a6e14e9d
docs: remove redundant TOC usages (#32096) 2024-08-09 12:44:01 +02:00
Yury Semikhatsky 236a8ac2ac
test: enable header overrides on redirect in firefox (#32088)
Fixes: https://github.com/microsoft/playwright/issues/32045
2024-08-08 23:46:36 -07:00
Playwright Service 5cc1e7b299
feat(firefox): roll to r1462 (#32086)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 22:41:49 +02:00
Playwright Service 83b807385d
feat(firefox-beta): roll to r1462 (#32087)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 22:41:09 +02:00
Dmitry Gozman 44445e30e5
fix(ui mode): make sure key for attachment view is unique (#32084)
Fixes #32052.
2024-08-08 10:57:44 -07:00
Pavel Feldman 80e014f4b6
chore: sources tab render polish (#32055) 2024-08-08 10:53:59 -07:00
Playwright Service 69287f26bc
feat(chromium-tip-of-tree): roll to r1248 (#32077)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 14:24:47 +02:00
Dmitry Gozman f24e46c367
fix(types): revert type changes made to support TS 5.5 (#32066)
Regressed in #31532. The TS5.5 changes broke chaining of `extend`s where
the first `extend` did not specify any type arguments.

Fixes #32056.
2024-08-08 05:21:48 -07:00
Playwright Service 05732b50c8
feat(chromium): roll to r1130 (#32074)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 14:13:18 +02:00
Playwright Service 48627ad484
feat(firefox-beta): roll to r1461 (#32068)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 11:37:37 +02:00
Simon Knott 17bb36a7fe
fix(ui): reset higlighted action on keyboard navigation (#32051)
Closes https://github.com/microsoft/playwright/issues/32050

When keyboarding through the action view, the UI continues showing the
hovered action. This makes keyboard nav hard to use.

The fix is to reset the higlighted action on keyboard navigation. This
is what we do when the mouse pointer leaves an action, and what I think
is reasonable.
2024-08-08 10:06:36 +02:00
Playwright Service 3d2b5e6801
feat(firefox-beta): roll to r1460 (#32059)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 08:48:12 +02:00
Playwright Service f8a7a301e6
feat(chromium-tip-of-tree): roll to r1247 (#32030)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-08 08:37:38 +02:00
faulpeltz ca25d2c802
fix: ubuntu version detection for linux mint 22 (#32049)
Add Linux Mint 22 (Ubuntu based distro) version detection for dependency
installation
Linux Mint 22.x -> Ubuntu 24.04

(also see original Linux Mint support PR #28085)
2024-08-07 14:28:03 -07:00
Playwright Service 7449ca21f4
feat(firefox-beta): roll to r1459 (#32054) 2024-08-07 14:21:54 -07:00
Dmitry Gozman ea747afcdd
chore: use a single binding for all Playwright needs (#32039)
This makes it easier to manage bindings, being just init scripts.
Fixes the BFCache binding problem.
Makes bindings removable in Firefox.

Fixes #31515.
2024-08-07 06:20:12 -07:00
Meir Blachman fd9276f2ac
docs: add discord link in readme (#32020) 2024-08-06 15:53:58 -07:00
Kuba Janik 7ec3a93db3
feat(ui-mode): add filters to network tab (#31956) 2024-08-06 14:52:35 -07:00
Pavel Feldman 79ca3f28c5
chore: simplify useSetting to not rely on useSyncExternalStore (#32018) 2024-08-06 14:30:15 -07:00
Yury Semikhatsky 7f60f284c6
docs(auth): use abs path, difference between storage locations (#32037)
Reference: https://github.com/microsoft/playwright/issues/31987
2024-08-06 11:36:49 -07:00
Yury Semikhatsky 43e852334b
docs: route.fallback() vs. route.continue() (#32035)
Fixes https://github.com/microsoft/playwright/issues/31983
2024-08-06 11:35:53 -07:00
Dmitry Gozman a54ed48b42
feat(test runner): --tsconfig cli option (#31932)
Introduce `--tsconfig` to specify a single config to be used for all
imported files, instead of looking up tsconfig for each file separately.

Fixes #12829.
2024-08-06 06:55:15 -07:00
Max Schmitt bff97b4810
test: fix failing client-certificate tests (#32021) 2024-08-06 08:46:35 +02:00
Meir Blachman 5a015b0d6e
docs(release-notes): fix typo in .NET release notes (#32015) 2024-08-06 07:19:55 +02:00
Pavel Feldman 3c87f217df
feat(events): allow waiting for removeAllListeners (#31941) 2024-08-05 21:14:35 -07:00
Yury Semikhatsky 193013c9ee
docs(har): default update mode is minimal (#32016)
Update the documentation to match actual behavior.

The actual behavior today:
* Default mode is `full` when `recordHar` is passed to
`browser.newContext`
* Default mode is `minimal` when calling `context.routeFromHAR` and
`page.routeFromHAR`

Reference https://github.com/microsoft/playwright/issues/31983
2024-08-05 11:29:43 -07:00
Yury Semikhatsky fef27395a5
chore(trace): do not nest API actions based on time (#31990)
They should be properly nested based on Node.js zones now.
2024-08-05 10:06:14 -07:00
Dmitry Gozman 5c9ce6b9d9
test: unflake various tests (#32014) 2024-08-05 08:29:13 -07:00
Max Schmitt 613ccb8d5b
chore(client-certificates): rewrite error for unsupported PFX errors (#32008) 2024-08-05 14:42:29 +02:00
Dmitry Gozman 32ee09dbe6
docs: release notes for 1.46 update (#32010) 2024-08-05 05:35:46 -07:00
Max Schmitt a47d2f998c
chore(lint): bump Microsoft.CodeAnalysis for linting code snippets (#32012) 2024-08-05 14:30:38 +02:00
Max Schmitt 71e614dc5a
fix(client-certificates): report error to the browser if incorrect passphrase (#32007) 2024-08-05 10:54:33 +02:00
Max Schmitt dbc4bc84d6
fix(trace-viewer): popup snapshot utf-8 support (#32006) 2024-08-05 09:11:31 +02:00
Playwright Service c54567a46b
feat(webkit): roll to r2056 (#31999)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-05 06:12:38 +02:00
Max Schmitt d0c840f639
fix(clock): mock time in Event.prototype.timeStamp (#31986)
Ideally we generate the timestamp when the Event gets created. This
patch adds a best-effort logic, since we can't override the constructor
of natively created events, e.g. `MouseEvent`.

Fixes https://github.com/microsoft/playwright/issues/31924
2024-08-02 15:27:54 +02:00
Max Schmitt 878a6a499b
chore: prefer executablePath for page.pause() (#31985)
Motivation: For scenarios where
[`findChromiumChannel`](f17de8222f/packages/playwright-core/src/server/registry/index.ts (L1016))
throws (no branded browser and no normal browser is installed) we were
[silently
catching](f17de8222f/packages/playwright-core/src/server/recorder.ts (L79))
when calling `page.pause()`.

This patch does not invoke `findChromiumChannel` when the
inspectedContext is Chromium based and has an `executablePath`
specified.

Note this was already fixed by #6214, but regressed since then.

Fixes https://github.com/microsoft/playwright/issues/31967
2024-08-02 11:18:51 +02:00
Max Schmitt f17de8222f
chore: run client-certificate tests in service mode (#31973) 2024-08-02 08:34:28 +02:00
Yury Semikhatsky db0980a850
chore(fetch): include response text into failOnStatusCode errors (#31978)
Fixes https://github.com/microsoft/playwright/issues/31834
2024-08-01 17:53:43 -07:00
Yury Semikhatsky 5a83fe55bc
chore(trace-viewer): hide status code field for failed request (#31977)
* Hide 'Status Code:' field for interrupted requests that don't have it.
* Clear up previously selected body when showing aborted requests.
* Highlight interrupted requests in red.
2024-08-01 17:26:52 -07:00
Yury Semikhatsky 5a80ddfaf9
chore: remove bright counter from sidebar tab selector (#31975)
Removing the following icon:

![image](https://github.com/user-attachments/assets/d2de2ed0-f66e-4452-8763-aad1b6e7bb79)

HTML `options` element cannot be styled, so just removing the counter in
sidebar mode:

<img width="348" alt="image"
src="https://github.com/user-attachments/assets/d636dca2-5007-41f7-866e-3a0f604d46fc">
2024-08-01 16:18:10 -07:00
Yury Semikhatsky a828fd5d73
test: ui mode annotations (#31965) 2024-08-01 14:47:50 -07:00
Yury Semikhatsky 1074a765e4
fix(trace): do not place expect into unfinished api calls based on time (#31970)
Fixes https://github.com/microsoft/playwright/issues/31959
2024-08-01 14:14:10 -07:00
Max Schmitt 69561a194a
fix(trace-viewer): make 'hide route actions' work for .NET (#31961) 2024-08-01 21:02:47 +02:00
Max Schmitt 73e0e92a7e
devops: retry download of upstream Node.js for drivers (#31962) 2024-08-01 19:45:25 +02:00
Dmitry Gozman a541751657
feat(ui mode): linkify attachment names and content (#31960)
- Pass `contentType` to the CodeMirror.
- Support `text/markdown` mode.
- Custom mode for non-supported types that linkifies urls.
2024-08-01 09:27:45 -07:00
Simon Knott 76cca7fc2c
fix(ui): only populate settings once (#31958)
We populate `localStorage` using an init script. Currently, this script
isn't just run for the UI though, but also for all iframes. So we're
resetting `localStorage` every time the UI loads an iframe.

This hasn't been a problem in the past, because the only consumer of
`localStorage`, `Settings`, only read from `localStorage` once and kept
most state in `useState` afterwards. With
https://github.com/microsoft/playwright/pull/31911, this is no longer
true, so the bug starts biting us!

The fix is to ensure the init script isn't run on iframes.
2024-08-01 17:28:48 +02:00
Playwright Service c858554dca
feat(chromium-tip-of-tree): roll to r1246 (#31951) 2024-08-01 15:13:15 +02:00
Dmitry Gozman bbe252a3d7
fix(ui mode): api review feedback (#31952)
- Hide "Testing Options" as not ready.
- Update SettingsView margins.
- Include `page.route` and similar methods into "Show route actions".
2024-08-01 05:36:19 -07:00
Playwright Service 6c6f10b678
feat(chromium): roll to r1129 (#31955)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-01 14:32:44 +02:00
Playwright Service a83134b270
feat(ffmpeg): roll to r1010 (#31949) 2024-08-01 13:17:11 +02:00
Yury Semikhatsky 47714d6559
feat(ui-mode): add annotations tab (#31945)
<img width="867" alt="image"
src="https://github.com/user-attachments/assets/7d714723-1d3f-49b2-944a-0a476d79aee8">

---------

Signed-off-by: Dmitry Gozman <dgozman@gmail.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-08-01 03:43:29 -07:00
Playwright Service 6af2635343
feat(chromium-tip-of-tree): roll to r1245 (#31948)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-08-01 10:27:02 +02:00
Yury Semikhatsky 62834e314f
chore(trace-viewer): less bright status code icon (#31940)
<img width="182" alt="image"
src="https://github.com/user-attachments/assets/8b381bcc-46e3-45c7-8fd2-e020436d1bff">

<img width="206" alt="image"
src="https://github.com/user-attachments/assets/4ea02b47-a4da-44f7-9c26-13b05374e89d">

<img width="213" alt="image"
src="https://github.com/user-attachments/assets/38b50e2a-f69c-4a78-abb2-2680453fc5fd">
2024-07-31 17:29:05 -07:00
Yury Semikhatsky 0217defab4
chore(trace-viewer): do not shrink metadata view (#31938)
Avoids the following effect:

![image](https://github.com/user-attachments/assets/694de773-acc0-4266-87f2-eab67a3c7ce2)
2024-07-31 16:37:16 -07:00
Yury Semikhatsky ecd384212d
chore(trace-viewer): copy only file name without line number (#31939)
As discussed in the meeting, copy only file name which is shown in the
same line, do not include highlighted line number.
2024-07-31 15:40:13 -07:00
Dmitry Gozman e62a54af7a
fix(test runner): do not revert the transform (#31930)
This allows a dynamic import of a TS file to be processed by Babel.

For some reason, Playwright used to revert the CJS transforms. However,
ESM loader and transforms are always active, so CJS should be too.
2024-07-31 13:17:09 -07:00
Yury Semikhatsky edb89dcb66
chore: make sure error stack includes message as before #31691 (#31934)
This brings stack formatting to how it was prior to
1686e5174d
so that the ports can use it.
2024-07-31 10:58:37 -07:00
Dmitry Gozman 7c55b94280
fix(trace): make sure the correct attachment name is used for downloads (#31928)
When two attachments have the same content sha1, we used the first one's
name for the downloaded file, no matter which one the user clicked to
download. Now we pass the name explicitly.

References #31912.
2024-07-31 06:20:36 -07:00
Sander c9a12e4ca1
docs(ct): fix component.update example for vue and svelte (#31889) 2024-07-31 13:40:19 +02:00
Simon Knott daca1681c0
refactor(ui): in splitview component, move sidebar and main from children into named properties (#31925)
Pulled out from https://github.com/microsoft/playwright/pull/31900

I stumbled over `React.Children`, because it's the first time I saw that
used. https://react.dev/reference/react/Children lists `React.Children`
it as "Legacy" and mentions it's uncommon. Also, the fact that SplitView
only displays its first two children, and all others are silently
discarded, can be a surprise to some.

By separating things out into `sidebar` and `main`, not only do we give
the two elements names (otherwise one needs to remember that sidebar is
always the first child), but we also prevent any "third children" from
being dropped.
2024-07-31 12:48:46 +02:00
Simon Knott 99724d0322
refactor(ui): some react refactorings (#31900)
Addresses https://github.com/microsoft/playwright/issues/31863. This PR
is chonky, but the individual commits should be easy to review. If
they're not, i'm happy to break them out into individual PRs.

There's two main things this does:

1. Remove some unused imports
2. Add a `clsx`-inspired helper function for classname templating

I wasn't able to replace `ReactDOM.render` with `ReactDOM.createRoot`.
This is the new recommended way starting with React 18, and the existing
one is going to be deprecated at some point. But it somehow breaks our
tests, i'll have to investigate that separately.
2024-07-31 12:12:06 +02:00
Dmitry Gozman 64fe245297
fix(trace viewer): attachment download (#31920)
- Update attachments tab margins.
- Make sure to pass `&download` in attachment urls. This makes them
downloadable, regressed in #28727.
- Do not additionally list image diffs as screenshots.

Fixes #31912.
2024-07-31 02:29:14 -07:00
Max Schmitt 55187207e4
chore: various roll fixes for .NET (#31914) 2024-07-30 19:09:20 +02:00
Simon Knott b8b562888e
refactor(ui): synchronize settings via useSyncExternalStore instead of prop drilling (#31911)
Broken out from https://github.com/microsoft/playwright/pull/31900, part
of https://github.com/microsoft/playwright/issues/31863.

Synchronizes different `useSettings` calls via `useSyncExternalStore`.
This saves us from having to drill down settings props everywhere,
without the big refactoring that a `Context` would be.
2024-07-30 17:57:31 +02:00
Simon Knott 8412d973c0
fix(ui): added test in watched file should be run (#31842)
Closes https://github.com/microsoft/playwright/issues/22211

Currently, when the server notifies the UI about changed files, the UI
determines what files to re-run based on an old test list. By listing
tests before that, we make sure that the test list is up-to-date, and
that added tests are included in the next run.

I've also removed the `listChanged` event as discussed in the team sync.
The event isn't used anywhere and fires in exactly the same cases where
`testFilesChanged` fired, so i've folded them into one another. This allowed simplifying `Watcher`.
2024-07-30 14:17:41 +02:00
Playwright Service 947f925443
feat(webkit): roll to r2054 (#31910)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-30 12:24:14 +02:00
Max Schmitt bd186640df
fix(client-certificates): use matching origin for connections on :443 (#31913)
Motivation: When using client-certificates on a website on port `443`,
we would normalise the user input with `new URL` but still generate a
"bad" representation of the "origin" internally, since the just do
concatenated "host:port".

(The origin doesn't contain the port in case of :443)

We use `clientCertificatesToTLSOptions` in two places:

a) for APIRequestContext, there we pass one from the URL constructor
over and
b) from the socks proxy, there we **now** also pass a "good one" over.

Test plan: We don't want to run the tests on port :443, so only manually
validated the fix.

Relates https://github.com/microsoft/playwright/issues/31906
2024-07-30 12:23:57 +02:00
Max Schmitt 44ce6096bb
feat(html-reporter): add Playwright logo as Favicon (#31908) 2024-07-30 12:02:06 +02:00
Max Schmitt ac0a3fb275
docs(best-practises): make trace icon location more clear (#31909) 2024-07-30 11:19:07 +02:00
Pavel Feldman 58b0c76f20
chore: use soft event emitter (#31868) 2024-07-29 17:11:31 -07:00
Max Schmitt 7e7319da7d
fix(client-certificates): don't use proxy when using BrowserContext.request (#31898) 2024-07-29 16:44:53 +02:00
Dmitry Gozman f232507afa
feat(ui mode): ui updates (#31894)
- Update copy to clipboard button.
- Reveal test source in the Source tab instead of external editor.
- New button to reveal in the external editor in the Source tab.
- Move the Pick Locator button next to snapshot tabs.
2024-07-29 07:32:13 -07:00
Max Schmitt f45cf65921
chore: add maxRetries to APIRequestContext.delete (#31893) 2024-07-29 14:39:30 +02:00
Max Schmitt cc313f3290
fix(client-certificates): error response body Content-Length calculation (#31897) 2024-07-29 14:39:14 +02:00
Max Schmitt acf5ea0904
chore: update browser patches as of Jun, 12, 2024 (#31888) 2024-07-29 10:30:28 +02:00
Playwright Service 1a7d6749da
feat(webkit): roll to r2053 (#31885)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-07-26 20:32:12 +02:00
Playwright Service 7690694677
feat(webkit): roll to r2052 (#31882) 2024-07-26 20:29:31 +02:00
Max Schmitt e784e2df01
chore: mark 1.47.0-next (#31879) 2024-07-26 17:50:11 +02:00
Max Schmitt 57c7d9e9bb
docs: add release notes for 1.46 (#31875)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Signed-off-by: Dmitry Gozman <dgozman@gmail.com>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-07-26 08:34:26 -07:00
Dmitry Gozman 9227d1c598
docs: explain a bit more about fixture boxing and custom titles (#31877) 2024-07-26 07:43:58 -07:00
Max Schmitt 6988194c97
test: unflake contextmenu recorder test (#31749) 2024-07-26 12:43:05 +02:00
Max Schmitt b214941a01
chore: make it more clear that --only-changed is per file (#31874) 2024-07-26 12:41:33 +02:00
Max Schmitt 47e4e45bc2
chore: update WebKit version to 18.0 (#31873) 2024-07-26 11:32:51 +02:00
Max Schmitt 09581b615d
fix(client-certificates): return target errors on response when using http2 (#31867) 2024-07-26 11:28:45 +02:00
Max Schmitt 335d31bf65
devops: remove GHA todo in primary workflow for itest (#31871)
This TODO got added during our GHA refactoring a while ago, where I
thought it might make sense to run our itests in `bash`. We didn't do it
before the refactoring either. It seems good to keep them running in
`pwsh` instead, so lets just remove the TODO.

Investigation notes: Running in `bash` on Windows via `Git Bash` seems
like doing a lot of magic, especially with path handling. Things
[like](a02ed38e60/tests/installation/registry.ts (L143))
this break then, since `tar` even when using `Git Bash` [doesn't accept
a Windows
path](https://sourceforge.net/p/mingw/mailman/mingw-users/thread/54CE104A.7060108@hccnet.nl/).

Signed-off-by: Max Schmitt <max@schmitt.mx>
2024-07-26 11:04:51 +02:00
Max Schmitt 81b3c0c402
fix(client-certificates): include socks-certs in npm package (#31872) 2024-07-26 11:04:38 +02:00
Max Schmitt a02ed38e60
chore: reduce file reads in client-certificates internal TLS server (#31865) 2024-07-25 22:36:25 +02:00
Dmitry Gozman a41cebc1c9
feat(ui mode): introduce Testing Options and Settings (#31841)
Testing Options control tests, while Settings are UI mode settings.

<img width="298" alt="Screenshot 2024-07-25 at 10 54 22 AM"
src="https://github.com/user-attachments/assets/7b6f5fff-687b-48d1-80b3-d1e6f2a257e8">


These sections are separately expandable, collapsed by default.

<img width="294" alt="Screenshot 2024-07-24 at 2 06 25 PM"
src="https://github.com/user-attachments/assets/5d35ac8c-9289-46ca-aaa2-ebc5419fa0c4">

References #31520.

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Simon Knott <info@simonknott.de>
2024-07-25 11:23:43 -07:00
Max Schmitt a966abfd31
test: unflake happy-eyeballs tests (#31861) 2024-07-25 20:22:51 +02:00
Dmitry Gozman d8d5289e86
fix(remote): make sure api calls reject before browser is closed (#31858)
Upon calling `browser.close()` or dropping remote connection, make sure
to reject api calls before resolving `browser.close()` and firing a
`disconnected` event.

This change aligns the order guarantee with non-remote case.
2024-07-25 09:57:34 -07:00
Max Schmitt 0c6ecf8df4
chore: use happy eyeballs for client-certificates (#31859) 2024-07-25 18:55:47 +02:00
Playwright Service d3e2c6cbb2
feat(chromium-tip-of-tree): roll to r1244 (#31856)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-25 18:54:24 +02:00
Max Schmitt 90af289ba2
test: use managed http2 server for client-certificates (#31844) 2024-07-25 18:53:38 +02:00
Simon Knott b06a95dd75
feat(trace viewer): show baseURL in Metadata pane (#31852)
Resolves https://github.com/microsoft/playwright/issues/31847 by adding
playwright config's `baseURL` value to the `context-options` trace
event, and showing that in the Trace Viewer.

Because the added property is optional, I didn't increment the trace
format version.

I've also considered pulling the `baseURL` from the existing
`browser.newContext` step to get around modifying the trace format, but
that felt pretty hacky.


https://github.com/user-attachments/assets/ecaef747-727d-4937-9ca3-1605ca9907b9

---------

Signed-off-by: Simon Knott <info@simonknott.de>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-07-25 17:14:46 +02:00
Simon Knott 4d4ed2a5c4
chore: enforce single quotes in JSX (#31855)
Discovered in
https://github.com/microsoft/playwright/pull/31852#discussion_r1691133106:
We're not enforcing single quotes for JSX, and it shows! We need to
start enforcing it to prevent even greater damage from being done ;D
2024-07-25 13:06:26 +02:00
Playwright Service 3ce948e972
chore(driver): roll driver to recent Node.js LTS version (#31854) 2024-07-25 12:52:50 +02:00
Simon Knott a1a4216b88
chore(ui): add test expectation that doesn't immediately pass on blank tree (#31850)
Followup to #31815
2024-07-25 12:21:24 +02:00
Playwright Service bdbe4795f1
feat(chromium): roll to r1128 (#31848)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-25 09:42:53 +02:00
Max Schmitt 7570c25b3d
chore: remove glob from client-certificate matching (#31846)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-07-24 19:13:03 +02:00
Max Schmitt ca149be154
test: skip SharedArrayBuffer on macOS 12 (#31845) 2024-07-24 18:45:03 +02:00
Elio Struyf 1e94abb683
docs: added MS Teams and mail reporter (#31579) 2024-07-24 11:55:45 +02:00
Max Schmitt c5b7ce86dc
feat(client-certificates): add http2 support (#31786) 2024-07-24 11:39:39 +02:00
Pavel Feldman c74843a914
chore(fetch): pass flush and finishFlush options to brotli (#31833)
Fixes https://github.com/microsoft/playwright/issues/31814
2024-07-23 18:28:34 -07:00
Yury Semikhatsky 13b5510d57
docs(webkit): supprot for non-core features may differ between OSes (#31831)
Fixes: https://github.com/microsoft/playwright/issues/31017
2024-07-23 17:35:02 -07:00
Pavel Feldman 7735affef4
fix(ui): print the web server output in the ui mode (#31824)
Fixes https://github.com/microsoft/playwright/issues/31300
2024-07-23 16:52:32 -07:00
Yury Semikhatsky 1918ae5c4a
fix(webkit): reenable CrossOriginOpenerPolicy (#31765)
Depends on https://github.com/microsoft/playwright-browsers/pull/1160
Fixes: https://github.com/microsoft/playwright/issues/14043
2024-07-23 15:02:47 -07:00
Max Schmitt c4862c022c
chore: client certificates api review (#31826) 2024-07-23 22:56:36 +02:00
Yury Semikhatsky 383e4b3c73
Revert "feat: introduce touchscreen.touch() for dispatching raw touch… (#31823)
… events (#31457)"

This reverts commit a3e31fd2c4.
2024-07-23 10:29:37 -07:00
Max Schmitt b9c4b6bff0
chore: client certificates refactorings (#31822) 2024-07-23 19:18:31 +02:00
Simon Knott f23d02a211
feat(test runner): --only-changed option (#31727)
Introduces an `--only-changed [base ref]` option.

`playwright test --only-changed` filters the test run to only run test
suites that have uncommitted changes.
`playwright test --only-changed=foo` runs only tests that were changed
since commit `foo`.

In pull request CI, this can be used to run changed tests first and fail
fast: `--only-changed=$GITHUB_BASE_REF`.
During local development, it can be used to quickly filter down to the
touched set of tests suites.
In some rare usecases, this can also help to cut down on CI usage for
pull requests. Tread with caution though.

File dependencies are taken into account to ensure that if you touched a
utility file, all relevant tests are still executed.

Closes https://github.com/microsoft/playwright/issues/15075
2024-07-23 18:04:17 +02:00
Simon Knott 2cc4e14756
fix(core): update maxRetries docs (#31810) 2024-07-23 08:27:27 -07:00
Dmitry Gozman e86c8af599
chore: rename route fixture in ct (#31817)
Addresses review feedback.
2024-07-23 07:43:28 -07:00
Max Schmitt 526e4118fa
chore: use socks.Duplex constructor instead of extending (#31816) 2024-07-23 15:44:16 +02:00
Simon Knott bbe5df3f5f
fix(ui): when --grep is used, UI should only show selected tests (#31815)
Closes https://github.com/microsoft/playwright/issues/31617.
2024-07-23 15:29:08 +02:00
Playwright Service d5a77c0f0b
feat(chromium-tip-of-tree): roll to r1243 (#31812)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-23 15:22:06 +02:00
Andrey Lushnikov d23ea26947
feat(firefox): roll Firefox & Firefox-Beta to 1458 (#31807)
Fixes https://github.com/microsoft/playwright/issues/31525
Closes https://github.com/microsoft/playwright/pull/31806
Closes https://github.com/microsoft/playwright/pull/31805
2024-07-23 10:37:00 +02:00
Simon Knott 1408a45595
chore(ct): remove suite dependency by connecting dependency graphs at read time, not write time (#31794)
Broken out of https://github.com/microsoft/playwright/pull/31727 as per
@dgozman's
[request](https://github.com/microsoft/playwright/pull/31727#discussion_r1685793229).

The PR goal is to remove the `suite` argument from the Component
testing's Vite Plugin. `suite` is used to enrich Vite's dependency graph
with information about dependencies between test suites and helper
files. It essentially merges the Vite graph with the
`compilationCache.ts > fileDependencies` graph, and then writes the
result back into `compilationCache.ts > externalDependencies`.

By refactoring this to make the connection on the reading end in
`collectAffectedTestFiles`, we can drop the `suite` parameter.

We didn't yet have a test that depended on the dependency graph being
connected correctly between `fileDependencies` and
`externalDepedencies`, so I've [extended an existing
test](53a539938b)
to capture that.
2024-07-23 10:19:58 +02:00
Pavel Feldman cf1a313a0c
chore: allow empty string in regex patterns (#31804) 2024-07-22 13:02:12 -07:00
Dmitry Gozman d87cb7a303
feat(trace viewer): allow hiding route actions (#31726)
Adds a new settings tab above the actions list.

<img width="307" alt="settings tab"
src="https://github.com/user-attachments/assets/792212b7-e2fd-4a5c-8878-654e2e060505">

Toggling the "Show route actions" checkbox hides all route calls:
`continue`, `fulfill`, `fallback`, `abort` and `fetch`.

References #30970.
2024-07-22 11:34:34 -07:00
Yury Semikhatsky e269092ef9
Revert "fix: add 'window-management' to chromium browser (#31687)" (#31801)
This reverts commit 0aa2f06f68.

Discussed the new permission in the API review and decided not to
proceed with the feature as we are not ready to commit to supporting it
yet:
* the API is Chromium specific
* the API is still experimental
* there is no clarity to what extend the screen manipulation APIs will
work in old headless which is our main test environment

We'll keep an eye on the demand for the feature and may get back to
implementing it in the future.

Reference: https://github.com/microsoft/playwright/issues/27198
2024-07-22 11:27:12 -07:00
Yury Semikhatsky bef87849e3
chore: show error when opening newer trace with old viewer (#31781)
Reference: https://github.com/microsoft/playwright-java/issues/1617
2024-07-22 08:16:25 -07:00
Josh Soref 7abbbd0c84
docs: spelling (#31779)
Fixes misspellings identified by the [check-spelling
action](https://github.com/marketplace/actions/check-spelling).

The misspellings have been reported at
https://github.com/jsoref/playwright/actions/runs/10015023629#summary-27685777352

The action will report that the changes in this PR would make it happy:
https://github.com/jsoref/playwright/actions/runs/10015023971#summary-27685778305

---

I understand that the commit messages will need to be reworded to match
house style. For the time being, these are merely noting the changes
they contain so that when I rebase or need to drop things, I can. --
I've already rebased once as someone fixed one of the items that my
draft work was going to fix.

---

## Testing
* The tests _mostly_ passed when I managed to trigger them, but there
were a handful of things that I didn't quite understand
* There are a large number of warnings relating to a bad interaction
between any workflow that uses this local action
b535139b32/.github/actions/run-test/action.yml (L74-L80)
and the action it calls -- I've opened Azure/login#474 asking them to
refactor their action so that it doesn't cause so much noise while
running this repository's tests
* I'm vaguely curious as to why this repository has a `branch`
constraint for its `pull_request` events in its workflows -- that
constraint gave me a number of additional headaches while trying to
prepare this branch for this PR.

---------

Signed-off-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
2024-07-22 06:45:22 -07:00
Playwright Service af3d2ba9fe
feat(webkit): roll to r2048 (#31778)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-20 14:27:41 +02:00
Dmitry Gozman b535139b32
fix(trace viewer): library-only trace should not merge actions (#31768)
Without `wallTime`, actions are matched by `actionName:undefined` and
all actions with the same are merged.

Fixes #31764.
2024-07-19 11:18:22 -07:00
Max Schmitt b8546eb35e
test: unflake client-certificate WebKit tests (#31776) 2024-07-19 15:08:04 +02:00
Simon Knott b269ceb773
chore(policy files): Update SECURITY.md to V0.0.9 (#31775)
Prompted by https://github.com/microsoft/playwright/pull/31738. There's
an updated `SECURITY.md` at
https://github.com/microsoft/repo-templates/blob/main/shared/SECURITY.md.
This PR pulls that into Playwright.

Signed-off-by: Simon Knott <info@simonknott.de>
2024-07-19 14:56:32 +02:00
Max Schmitt f570c747d5
test: unskip har http2 test on WebKit Windows (#31774) 2024-07-19 13:44:56 +02:00
Max Schmitt f104e920e0
fix(client-certificates): pass TLS servername for SNI (#31761) 2024-07-19 12:55:20 +02:00
Max Schmitt 0ecae56750
test: unflake 'should have ignoreHTTPSErrors=false by default' (#31771) 2024-07-19 12:04:12 +02:00
Yury Semikhatsky d007ff3b62
chore: make WKInterceptableRequest._requestId private (#31762)
With COOP navigation we may need to take over request in the new
provisional page where it will have different id. This is preparation to
that.
2024-07-18 15:19:53 -07:00
Max Schmitt 708def8804
fix(client-certificates): keep ignoreHTTPSErrors false by default (#31760) 2024-07-18 22:37:11 +02:00
Max Schmitt 6dbc7b54e8
feat(ui-mode): highlight console message in timeline on hover (#31756) 2024-07-18 16:39:40 +02:00
Playwright Service 097f28def9
feat(chromium-tip-of-tree): roll to r1242 (#31751)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-18 14:46:42 +02:00
Playwright Service 26c9478648
feat(chromium): roll to r1127 (#31755)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-18 14:46:19 +02:00
Max Schmitt 297b1a8afe
test: move page-clock tests into library/ tests folder (#31752) 2024-07-18 14:45:45 +02:00
Max Schmitt 453e3bdf9d
test: fix client-certificates tests on Windows (#31750) 2024-07-18 13:43:56 +02:00
Dmitry Gozman e78ce8521d
feat(chromium-tip-of-tree): roll to r1241 (#31748)
Closes https://github.com/microsoft/playwright/pull/31650
Closes https://github.com/microsoft/playwright/pull/31705
Relates https://github.com/microsoft/playwright/issues/31747
2024-07-18 12:11:03 +02:00
Dmitry Gozman 056997c41f
fix(toHaveScreenshot): attach "expected" when writing a missing expectation (#31745)
Previously, only the "actual" attachment was created, pointing to the
file in `test-results`. Now, the "expected" attachment pointing to the
file in `__screenshots__` is also created. This will help any reporters
that would like to know the "expected" path, for example to do a manual
accept/decline of the baseline.

Fixes #30693.
2024-07-18 02:42:44 -07:00
Dmitry Gozman 6491e5b415
chore: deprecate/remove noWaitAfter from some actions (#31739)
The following actions keep `noWaitAfter` option: `click`, `selectOption`
and `press`.

All other actions that used to have `noWaitAfter` now behave like it was
set to true, not waiting for follow-up navigations. In the docs, this
option is marked as completely ignored.

A small logic change was made to compensate for this behavior: when
waiting for the `hitTargetInterceptor`, we now race it against
navigations to avoid stalling when navigation stalls. Previously,
waiting for the interceptor was disabled when `noWaitAfter` was passed,
and since it's impossible to pass this option now, we mitigate by never
stalling instead.

Fixes #31469.
2024-07-18 00:19:08 -07:00
Matt Kleinsmith e06481a332
fix(recorder): address custom context menus (#31634) 2024-07-17 11:45:48 -07:00
Playwright Service 3cb41739a0
feat(firefox-beta): roll to r1457 (#31733)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-17 18:33:47 +02:00
Yury Semikhatsky 3f15fe8518
feat(reporter): links in attachment names, attachments name only (#31714)
* Allow calling `test.info().attach('My text');` without options (no
path nor body).
* Highlight links in attachment names:

<img width="992" alt="image"
src="https://github.com/user-attachments/assets/770e7876-3e43-4434-8cf1-194ad6ae5819">

Fixes https://github.com/microsoft/playwright/issues/31284
2024-07-17 09:30:49 -07:00
Dmitry Gozman f4399f7f06
fix(toHaveScreenshot): sanitize attachment names and paths (#31712)
... unless an array of file-system-friendly parts is provided.

Motivation: attachment name is used as a file system path when
downloading attachments, so we keep them fs-friendly.

References #30693.
2024-07-17 07:08:43 -07:00
Simon Knott 8eab28d858
fix(list reporter): print step ends in non-TTY mode (#31703)
When used in a terminal, the `list` reporter prints out information
about test steps to help debugging. In non-TTY environments like GitHub
Actions, currently it doesn't.

This PR changes that, so that in non-TTY environments you'll see the
"step end" messages appearing, but not the "step begin" messages. This
is a good middleground, because it helps the user understand test
progress, without being too verbose.

Closes https://github.com/microsoft/playwright/issues/31674
2024-07-17 13:36:37 +02:00
Max Schmitt ed6abf86c7
fix(expect): throw unsupported error when using this.equals() in expect (#31723) 2024-07-17 13:22:00 +02:00
Max Schmitt e11c0c0cbb
fix(connect): annotate internal api calls correctly (#31715) 2024-07-17 09:00:47 +02:00
Max Schmitt 3694c1422d
Revert "test: rebase golden snapshots on Chromium macOS arm64 (#31344)" (#31711)
This reverts commit 02416877da.

Since we landed
3127571b24
- we should revert this one as well.
2024-07-16 21:16:55 +02:00
Max Schmitt bb2e9d1175
chore: make 'npm run clean' ignore .DS_Store (#31710) 2024-07-16 20:55:12 +02:00
Max Schmitt 6a9e60d6a1
fix(ct): import ct* flavour types from ct-core and then from pwt (#31642) 2024-07-16 19:32:51 +02:00
Yury Semikhatsky 8021312c99
chore: enable notification permission tests in WebKit (#31699)
The Notifications API has been supported in WebKit since 2022, enable
related permission and tests.
2024-07-16 09:44:38 -07:00
Max Schmitt f66f5b800e
docs: fix broken anchor links (#31707) 2024-07-16 16:11:20 +02:00
Max Schmitt 7ce9b7e56b
fix(setInputFiles): throw when uploading file in directory upload (#31706) 2024-07-16 15:55:35 +02:00
damar Zaky 96e0a96ac1
docs: fix grammar and typos in various files (#31678)
- docs/src/best-practices-js.md
- docs/src/codegen.md
- docs/src/debug.md
- docs/src/events.md
- docs/src/library-js.md
- docs/src/locators.md
- docs/src/other-locators.md
- docs/src/test-components-js.md
- docs/src/trace-viewer.md

---------

Signed-off-by: damar Zaky <damzaky@gmail.com>
2024-07-16 06:15:25 -07:00
Playwright Service a5ca9b7d37
feat(webkit): roll to r2047 (#31701)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-16 08:28:58 +02:00
Yury Semikhatsky 37ffbd757e
chore: remove unused project to id mapping from html builder (#31698) 2024-07-15 14:35:11 -07:00
Ismael Onilearan 0aa2f06f68
fix: add 'window-management' to chromium browser (#31687) 2024-07-15 14:34:57 -07:00
Yury Semikhatsky de39d227f7
chore: linkify urls in attachments body (#31673)
Reference: https://github.com/microsoft/playwright/issues/31284
2024-07-15 12:20:22 -07:00
Max Schmitt d463d1f285
fix(snapshotter): allow rendering of & in STYLE tags (#31627)
Fixes https://github.com/microsoft/playwright/issues/31607
2024-07-15 17:33:22 +02:00
Max Schmitt 950875f0db
fix(docs): index all deeply nested types (#31690) 2024-07-15 16:35:15 +02:00
Simon Knott 58bcdde956
docs(contributing): some updates to recommended test commands (#31693)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-07-15 16:32:50 +02:00
Dmitry Gozman 6ee8f1de2d
Revert "chore: move artifacts recording to TestLifecycleInstrumentation (#30935)" (#31686)
This reverts commit ba5b460444.
2024-07-15 07:01:51 -07:00
Dmitry Gozman 1686e5174d
chore: allow evaluating Error objects (#31691)
Previously, Error objects were replaced with strings.
Now, Error objects are reconstructed back from the serialized value.
2024-07-15 05:47:40 -07:00
Dmitry Gozman 074cc7d467
Revert "feat(trace): record trace upon browser closure (#31563)" (#31677)
This reverts commit bc27ca225e. Considered
too risky.
2024-07-15 01:08:51 -07:00
Yury Semikhatsky 1b4d9003c6
fix(har): ignore boundary when matching multipart/form-data body (#31672)
Fixes https://github.com/microsoft/playwright/issues/31495
2024-07-12 16:59:48 -07:00
Max Schmitt 459b762565
chore: remove unused kTestSdkObjects (#31665) 2024-07-12 11:56:16 -07:00
Pavel Feldman 297143885a
fix(clock): ensure Date.now() is an integer (#31648)
Fixes https://github.com/microsoft/playwright/issues/31644
2024-07-12 11:44:25 -07:00
Max Schmitt 3127571b24
Revert "fix(chromium): pass --enable-gpu when running headless (#30937)"
This reverts commit d0b052e1e0.
2024-07-12 20:12:56 +02:00
Jorge Caridad fb59e6372b
docs: fix typos in various documentation files (#31656) 2024-07-12 10:24:52 -07:00
Playwright Service 68595ac385
feat(webkit): roll to r2045 (#31664)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-12 19:24:38 +02:00
Max Schmitt 71a668eb86
test: skip windows/CR client-certificates proxy tests (#31662) 2024-07-12 14:34:32 +02:00
Max Schmitt 9569cb5c1e
feat: support client certificates (#31529)
Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Dmitry Gozman <dgozman@gmail.com>
2024-07-12 11:42:24 +02:00
Dmitry Gozman 229000501e
chore: introduce helpers for non-stalling eval on page/context (#31658) 2024-07-12 02:26:16 -07:00
Max Schmitt 1b85ec9dc2
test: unflake signals temp dir removal test (#31655) 2024-07-12 09:34:04 +02:00
Playwright Service 2441c765b1
feat(chromium): roll to r1126 (#31649)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-12 00:03:29 +02:00
Max Schmitt 97e2aa07a5
test: fix Windows Socks tests (#31654) 2024-07-11 23:16:24 +02:00
Yury Semikhatsky 01e2c8ab06
docs: document numeric values of PLAYWRIGHT_FORCE_TTY (#31653)
Fixes https://github.com/microsoft/playwright/issues/31647
2024-07-11 14:02:47 -07:00
Daniel Flores b13bd66d20
docs: add missing pytest-playwright installation command (#31645) 2024-07-11 21:27:54 +02:00
Max Schmitt 4554372e45
chore: remove unused dependencies (#31638) 2024-07-11 14:13:12 +02:00
Pavel Feldman 77e50635ee
chore: fix build warnings (#31616) 2024-07-11 14:12:59 +02:00
Max Schmitt 89eef55dc7
chore: use own socks5 server for tests (#31639) 2024-07-11 14:12:48 +02:00
Playwright Service 2b77ed4d7a
feat(firefox): roll to r1457 (#31633)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-11 07:44:48 +02:00
Max Schmitt a3b0f0cba8
chore: address deprecated Vite warnings (#31618) 2024-07-10 22:32:08 +02:00
Matvey Chernyshov ba62f83454
chore: add android keys for channels switching (#31619) 2024-07-10 13:15:45 -07:00
Dmitry Gozman a1f82b0bb6
fix(trace): do not corrupt test runner actions when no library trace is present (#31564)
Recent logic that matches either by `stepId` or by `apiName`+`wallTime`
did not account for "no library trace" scenario.
2024-07-10 09:12:06 -07:00
Stanislav Grishaev ce2b138eeb
chore: add iPhone 15 device family (#31623)
Fixes https://github.com/microsoft/playwright/issues/31573

---------

Signed-off-by: Max Schmitt <max@schmitt.mx>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-07-10 13:58:36 +02:00
Playwright Service dcff807ab8
feat(webkit): roll to r2044 (#31628)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-10 13:25:43 +02:00
Pavel Feldman f374f8db38
chore: follow up to the attachments preview change (#31598) 2024-07-09 09:58:59 -07:00
Playwright Service 067e423d14
feat(chromium-tip-of-tree): roll to r1239 (#31610)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-09 13:58:03 +02:00
Max Schmitt 0c11d6ed80
feat(trace-viewer): allow pasting traces (#31608) 2024-07-09 13:36:35 +02:00
Max Schmitt 5c8fe5c33c
docs: make x/y more clear (#31606)
Fixes https://github.com/microsoft/playwright/issues/31567
2024-07-09 12:52:51 +02:00
Playwright Service 1ea55acab3
chore(driver): roll driver to recent Node.js LTS version (#31609)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-09 12:07:34 +02:00
Álvaro Martínez 00131c1e3f
feat(trace-viewer): display text attachments in ui mode (#31215) 2024-07-08 11:16:14 -07:00
Michael Render 1d930542e1
docs(clock): Fix C# version of clock documentation (#31560) 2024-07-08 19:01:04 +02:00
Dmitry Gozman 21c4531618
fix(selector generator): do not reparent to invisible ancestor (#31590)
Fixes #31335.
2024-07-08 09:07:25 -07:00
Max Schmitt 4dfa55d1f1
chore(trace-viewer): move call tab copy button next to the value (#31586) 2024-07-08 10:23:19 +02:00
Dmitry Gozman 48db1b1663
fix(ui mode): allow --updateSnapshots (#31584)
Fixes #31408.
2024-07-08 01:08:57 -07:00
Dmitry Gozman bc27ca225e
feat(trace): record trace upon browser closure (#31563)
Retaining traces in the following scenarios:
- browser crash;
- manual `browser.close()`;
- implicit `browser.close()` from the `browser` fixture upon test end.

This does not affect the library, where `browser.close()` will not
retain the trace and will close the browser as fast as possible.

References #31541, #31535, #31537.
2024-07-06 11:34:34 -07:00
Dmitry Gozman 369a1eca48
feat(ct): experimental route fixture (#31554)
This fixture accepts the same arguments as `context.route()`, but also
supports request handlers compatible with msw syntax.
2024-07-06 09:35:20 -07:00
Debbie O'Brien b2bda9fce2
docs: update vs code projects explanation (#31571) 2024-07-05 17:37:00 +02:00
Max Schmitt 1132667ffe
chore: bump TypeScript to v5.5 (#31532) 2024-07-05 16:31:08 +02:00
Max Schmitt 2b94fa2e30 test: fix ESLint (remove unused imports) 2024-07-05 13:44:23 +02:00
Max Schmitt f56978edb2
test: isolate proxy creds between contexts (#31565) 2024-07-05 13:24:06 +02:00
Max Schmitt b79f3076ee
doc(clock): fix code snippets (#31568)
Fixes https://github.com/microsoft/playwright/issues/31566
2024-07-05 13:20:54 +02:00
Playwright Service 95ebfd301f
feat(webkit): roll to r2043 (#31561)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-05 10:57:11 +02:00
ryanrosello-og e36ebb6ede
feat(trace-viewer) add request urls for actions initiated via APIRequestContext (#31534) 2024-07-04 11:59:56 +02:00
Dmitry Gozman 1c69d3e175
chore: update flakiness metadata for better ui presentation (#31528) 2024-07-03 08:39:53 -07:00
Playwright Service 64b62988f6
feat(chromium-tip-of-tree): roll to r1237 (#31536)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-03 14:11:36 +02:00
Max Schmitt 2b974f2139
docs(clock): update time types in Python/.NET (#31511) 2024-07-03 10:46:33 +02:00
Max Schmitt bfbd5f6f2f
test: snapshot with all: unset in StyleSheet (#31514) 2024-07-03 09:40:50 +02:00
Max Schmitt 5bdced9c9b
chore: bump @types/node and chokidar (#31527) 2024-07-03 09:40:37 +02:00
Vitaliy Potapov 1e55a084bc
feat(html-reporter): hide annotations started with "_" (#31489)
Fixes: https://github.com/microsoft/playwright/issues/30179
2024-07-02 16:46:24 -07:00
Joe-Hendley a62260a9f2
feat(html report): linkify test annotations (#31521) 2024-07-02 16:45:16 -07:00
Nicolas Le Cam 9caf3b5f72
chore: Remove obsolete Chromium enabled features (#31513) 2024-07-02 09:10:42 -07:00
ryanrosello-og 262586a46a
feat(trace-viewer) add copy to clipboard on the Source > Stacktrace tab (#31394) 2024-07-02 09:09:39 -07:00
Max Schmitt 9dc7e40084
chore(electron): don't swallow close errors (#31509) 2024-07-01 22:00:03 +02:00
Noah Mayerhofer f62121548a
docs(ci): typo (#31508) 2024-07-01 20:57:16 +02:00
KeisukeYamashita 1f92376508
docs(ci): added Drone CI docs for Node.js (#31499) 2024-07-01 19:44:17 +02:00
Max Schmitt 9a3e0967e6
fix(electron): tracing with @playwright/test (#31437) 2024-07-01 19:19:38 +02:00
Max Schmitt b349a73645
fix(ct): export package.json (#31504) 2024-07-01 18:51:59 +02:00
Max Schmitt d1e76d9a92
docs(release-notes): fix .NET snippets (#31496) 2024-07-01 18:32:23 +02:00
Playwright Service 2136b96df1
feat(webkit): roll to r2041 (#31502)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-07-01 16:14:32 +02:00
Max Schmitt 7040340d61
test: adjust upload folder expectation for msedge (#31454) 2024-07-01 12:19:04 +02:00
Playwright Service 60773f34d8
feat(webkit): roll to r2040 (#31486)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-30 13:21:46 +02:00
4ydx 4089f4593b
fix(codgen): assertValue works with disabled select (#31315) 2024-06-28 13:04:59 -07:00
Debbie O'Brien ea33137a0e
docs: improve clock guide (#31487) 2024-06-28 13:04:39 -07:00
Pavel Feldman f46ae15500
test(clock): fix clock mode bots (#31472) 2024-06-28 11:46:28 -07:00
Debbie O'Brien 93d147cf28
docs: add release video (#31482) 2024-06-28 20:04:31 +02:00
Rui Figueira 9bc45ea2fc
feature(trace-viewer): embedded mode support PoC (#30885)
Companion PR of https://github.com/microsoft/playwright-vscode/pull/483
2024-06-28 10:36:11 -07:00
Playwright Service f1b04aaaf4
feat(webkit): roll to r2039 (#31480) 2024-06-28 15:23:38 +02:00
Yury Semikhatsky a3e31fd2c4
feat: introduce touchscreen.touch() for dispatching raw touch events (#31457) 2024-06-27 14:37:36 -07:00
Playwright Service 33ac75b7ab
feat(chromium-tip-of-tree): roll to r1236 (#31466)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-27 21:07:49 +02:00
Pavel Feldman c9e673c6dc
fix(utility): create utility world when web security is disabled (#31458)
Reverts previous attempt at #31096

Fixes: https://github.com/microsoft/playwright/issues/31431
Fixes: https://github.com/microsoft/playwright/issues/31442
2024-06-27 09:29:20 -07:00
Playwright Service 87785d6092
feat(chromium): roll to r1125 (#31467)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-27 17:01:16 +02:00
Yury Semikhatsky 111876d526
docs: improve addCookies.cookie parameter description (#31456) 2024-06-26 15:39:43 -07:00
Playwright Service 41b185d643
feat(webkit): roll to r2038 (#31441) 2024-06-26 09:20:28 -07:00
Playwright Service 976373ed2c
feat(chromium-tip-of-tree): roll to r1234 (#31418) 2024-06-26 16:51:57 +02:00
Max Schmitt dad305478a
docs: remove unnecessary html card (#31444) 2024-06-26 14:34:05 +02:00
Pavel Feldman da441347e2
fix(runner): do not run beforeEach hooks upon skip modifier (#31426)
Fixes https://github.com/microsoft/playwright/issues/31425
2024-06-25 10:47:37 -07:00
Max Schmitt f11ab2f145
chore: enable keepAlive in happy eyeballs http.Agent (#31434) 2024-06-25 19:05:32 +02:00
Playwright Service a6b6b243d0
chore(driver): roll driver to recent Node.js LTS version (#31432)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-25 12:16:36 +02:00
Pavel Feldman 122818c62c
feat: allow boxing and titling fixtures, simulate context fixture deps (#31423)
Fixes https://github.com/microsoft/playwright/issues/31411
2024-06-24 21:43:43 -07:00
Max Schmitt 47fb9a080d
fix(test-runner): don't add slow annotation twice (#31414) 2024-06-24 23:34:17 +02:00
Yury Semikhatsky 2b12f53332
chore(route): wait for raw headers from browser in case of redirects (#31410)
Redirects are always autoresumed, so the will always receive extra info
with raw headers. We only want to make raw headers available immediately
when there is a route.

Reference https://github.com/microsoft/playwright/issues/31351
2024-06-24 12:25:12 -07:00
Dmitry Gozman de723f39e9
docs: release notes for 1.45 (#31421) 2024-06-24 12:23:46 -07:00
Dmitry Gozman 114b6f0de6
docs: deprecate handle option in exposeBinding (#31419) 2024-06-24 11:29:40 -07:00
Yury Semikhatsky 865f0d8221
docs(java): correctly parse time (#31420) 2024-06-24 11:28:43 -07:00
Himanshu 74976b1da8
docs: Fixes minor typo. Changes These image -> This image (#31413)
Fixes a minor typo in the docker doc in `These image`
2024-06-24 09:04:42 -07:00
Yury Semikhatsky d74ddaebe7
fix: correctly report overridden headers on redirected requests (#31409)
Fixes https://github.com/microsoft/playwright/issues/31351
2024-06-21 17:44:58 -07:00
Max Schmitt 2285bcd55d
test: fix ct-vue-vite tests (#31406) 2024-06-22 00:50:10 +02:00
Romario Nijim 136fb996d1
docs: added more explanation to sharding to make it more understandable. (#31399)
* added more explanation to the sharding section for it to be more
understandable what it is and what it's purpose.
* because from the explanation in the docs. - it sound like that a
"shard" is a machine that is provided by playwright in addition to the
current setup , like a managed machine, but in reality it is simply a
separate job in the CI, dividing tests to separate jobs is sharding,
which sounds a lot easier when you think about it this way because it
could be confusing at the beginning IMO.
2024-06-21 10:20:56 -07:00
Playwright Service 42b9e8375a
feat(chromium): roll to r1124 (#31404)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-21 14:20:01 +02:00
Max Schmitt 7e1b69cf33
test: update Electron to v30 (#30334) 2024-06-21 00:43:26 +02:00
Max Schmitt 6ed3b374a8
fix(electron): allow downloads (#31390) 2024-06-21 00:35:14 +02:00
Max Schmitt 1ebd20a47b
chore: .NET generator fixes (#31401) 2024-06-20 23:33:46 +02:00
Playwright Service 940d20ad0b
feat(webkit): roll to r2037 (#31400)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-20 22:57:25 +02:00
Playwright Service 0694474fe1
feat(webkit): roll to r2036 (#31387)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-20 09:52:59 +02:00
Yury Semikhatsky 95fc2b8a8b
feat(fetch): maxRetries for fetch (#31386)
Fixes https://github.com/microsoft/playwright/issues/30978
2024-06-19 18:10:14 -07:00
Dmitry Gozman 2dfda0a16f
chore: bump ws to 8.17.1 in the utils bundle (#31384)
Follow-up to #31377.
2024-06-19 15:11:54 -07:00
Yury Semikhatsky a2b116aa39
fix(trace): ensure har entry _monotonicTime is always start time (#31385)
* Revert harTracer change from
aeba083da0
to make sure that har.Entry._monotonicTime always represents request
start time. The issue from the corresponding report was due to HEAD and
GET request sent for the same URL, that use case is still addressed as
we match by url + method
* Adjust resources monotonic time as well when several contexts are
shown in the trace viewer.

Fixes https://github.com/microsoft/playwright/issues/31133
2024-06-19 15:06:20 -07:00
Luke Page 94f0cadea3
fix(fs-watcher) ignore node_modules on windows (#31341)
Partially fixes https://github.com/microsoft/playwright/issues/31337 by
supporting ignoring node_modules on windows.

When I debug the function it gets a unix style path filename on windows,
so the function never ignores node_modules. The ignore path globs are
expected to use the unix path seperator and I've tested this fix works
on windows and I assume that since mac uses unix style, it also works
there (this is a pretty standard glob construct (chokidar points at any
match https://github.com/micromatch/anymatch and anymatch has this exact
example in their readme.md)

Signed-off-by: Luke Page <137174537+lukpsaxo@users.noreply.github.com>
2024-06-19 11:14:10 -07:00
dependabot[bot] 82a44f28e2
chore(deps-dev): bump ws from 8.16.0 to 8.17.1 (#31377)
Bumps [ws](https://github.com/websockets/ws) from 8.16.0 to 8.17.1.

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-19 10:42:43 -07:00
Playwright Service 45ee318673
feat(firefox): roll to r1456 (#31375)
Fixes https://github.com/microsoft/playwright/issues/31328
Fixes https://github.com/microsoft/playwright/issues/30837

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Max Schmitt <max@schmitt.mx>
2024-06-19 19:03:58 +02:00
Playwright Service a7958ff95f
feat(firefox-beta): roll to r1456 (#31376)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-19 18:25:57 +02:00
Max Schmitt 8ba4cff10f
devops: add headless new to flakiness dashboard (#31381) 2024-06-19 18:08:22 +02:00
ryanrosello-og ee63843f7d
feat(trace-viewer): add request method/status to the network details tab (#31274) 2024-06-19 09:05:20 -07:00
Max Schmitt 6d38525119
docs: add guide for print dialogs (#31340)
https://github.com/microsoft/playwright-internal/issues/211
Relates https://github.com/microsoft/playwright/issues/6543
2024-06-19 18:04:22 +02:00
Max Schmitt 951040185d
docs(test-parameterize): improve forEach example (#31331) 2024-06-19 17:45:27 +02:00
Dmitry Gozman 6ae9adfa4f
test: add "clock" to the metadata for dashboard traceability (#31370) 2024-06-18 14:56:08 -07:00
Dmitry Gozman ac90a47b73
fix(click): do not retarget <a> to the parent <label> (#31368)
Fixes #31359.
2024-06-18 12:12:19 -07:00
Yury Semikhatsky f6972c1e23
docs: use long for time in milliseconds (#31369)
In Java and .NET int is not enough to store millis since epoch.
2024-06-18 10:47:29 -07:00
Andrey Lushnikov ee7b5e6315
test: make sure main page recording continues after popup closes (#31365)
References https://github.com/microsoft/playwright/issues/30837
2024-06-18 10:29:41 -07:00
Max Schmitt 02416877da
test: rebase golden snapshots on Chromium macOS arm64 (#31344) 2024-06-18 19:09:24 +02:00
Yury Semikhatsky dbc54c763d
test: delete tests for non-existing fastForwardTo (#31366)
The tests repeat `it.describe('fastForward'` above them.
2024-06-18 09:34:32 -07:00
Max Schmitt 5fc56283a6
fix(clock): throw for invalid date (#31356)
Fixes https://github.com/microsoft/playwright/issues/31354
2024-06-18 18:23:55 +02:00
Max Schmitt c6aab05bd5
devops: make Android driver compile (#31360)
Fixes https://github.com/microsoft/playwright/issues/31355

All changes were done with the Android Studio upgrade assistant. It
updates it to the latest Gradle to make it compatible with recent Java
while keeping the `targetSdkVersion` unchanged.
2024-06-18 18:23:29 +02:00
Max Schmitt f05b4daa2f
fix(clock): under reused context (#31357)
We uninstall all the setInitScript but forgot to mark `installed` as
`false`.

Fixes https://github.com/microsoft/playwright/issues/31353
2024-06-18 18:21:33 +02:00
Andrey Lushnikov acf1b1f88c
test: add test reduced motion reset (#31364)
References https://github.com/microsoft/playwright/issues/31328
2024-06-18 09:01:35 -07:00
Robin Munn e1e6c28722
docs: fix typo in 1.45 release notes (#31350) 2024-06-18 10:11:48 +02:00
Yury Semikhatsky 9e6772818e
chore: cache normalized whitespaces in recorder (#31349)
Reference: https://github.com/microsoft/playwright/issues/31254

On the web page from the bug it reduces time to compute selectors by 8x:

**Before:**
<img width="549" alt="before"
src="https://github.com/microsoft/playwright/assets/9798949/f4482860-29d5-4643-92ab-b360a702f232">

**After:**
<img width="580" alt="after"
src="https://github.com/microsoft/playwright/assets/9798949/b6aca6a1-9306-4041-9042-d504dce1c33a">
2024-06-17 18:20:15 -07:00
Yury Semikhatsky 5443b66636
fix(codegen): trim alt selectors to 80 chars (#31346)
Fixes https://github.com/microsoft/playwright/issues/31254
2024-06-17 16:32:22 -07:00
Playwright Service f3f708e01a
feat(firefox-beta): roll to r1454 (#31343)
Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
2024-06-17 21:34:24 +02:00
Dmitry Gozman a002572dd2
test: update some test conditions (#31336) 2024-06-17 10:20:57 -07:00
Pavel Feldman 2a7f17d820
chore: fix simulated clock bots (#31301) 2024-06-17 09:17:38 -07:00
Max Schmitt b62af828c3
docs(input): fix pressSequentially typo (#31333) 2024-06-17 16:27:36 +02:00
dependabot[bot] 6fb214de23
chore(deps-dev): bump braces from 3.0.2 to 3.0.3 (#31293) 2024-06-17 10:52:27 +02:00
Fumiaki MATSUSHIMA 838c572209
fix: select issue in Windows with Edge (#31270) 2024-06-17 10:28:07 +02:00
Sander 1cbc67144a
docs(ct): format story example code (#31317) 2024-06-17 10:27:34 +02:00
Dmitry Gozman 2ae2fb421c
chore: roll stable test runner to 1.45.0-beta-1718411373000 (#31326) 2024-06-14 19:43:35 -07:00
Dmitry Gozman a4deced132
chore: update browser_patches to May 1st (#31325) 2024-06-14 18:38:09 -07:00
Dmitry Gozman 32e25a252b
chore: mark v1.46.0-next (#31324) 2024-06-14 18:22:42 -07:00
1415 changed files with 123731 additions and 33367 deletions

View file

@ -1,11 +0,0 @@
{
"name": "Playwright",
"image": "mcr.microsoft.com/playwright:next",
"postCreateCommand": "npm install && npm run build && apt-get update && apt-get install -y software-properties-common && curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add - && add-apt-repository \"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable\" && apt-get install -y docker-ce-cli",
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"runArgs": [
"-v", "/var/run/docker.sock:/var/run/docker.sock"
]
}

View file

@ -1,21 +0,0 @@
test/assets/modernizr.js
/tests/third_party/
/packages/*/lib/
*.js
/packages/playwright-core/src/generated/*
/packages/playwright-core/src/third_party/
/packages/playwright-core/types/*
/packages/playwright-ct-core/src/generated/*
/index.d.ts
node_modules/
browser_patches/*/checkout/
browser_patches/chromium/output/
**/*.d.ts
output/
test-results/
tests/components/
tests/installation/fixture-scripts/
examples/
DEPS
.cache/
utils/

View file

@ -1,15 +0,0 @@
module.exports = {
extends: "./.eslintrc.js",
parserOptions: {
ecmaVersion: 9,
sourceType: "module",
project: "./tsconfig.json",
},
rules: {
"@typescript-eslint/no-base-to-string": "error",
"@typescript-eslint/no-unnecessary-boolean-literal-compare": 2,
},
parserOptions: {
project: "./tsconfig.json"
},
};

View file

@ -1,127 +0,0 @@
module.exports = {
parser: "@typescript-eslint/parser",
plugins: ["@typescript-eslint", "notice"],
parserOptions: {
ecmaVersion: 9,
sourceType: "module",
},
extends: [
"plugin:react-hooks/recommended"
],
/**
* ESLint rules
*
* All available rules: http://eslint.org/docs/rules/
*
* Rules take the following form:
* "rule-name", [severity, { opts }]
* Severity: 2 == error, 1 == warning, 0 == off.
*/
rules: {
"@typescript-eslint/no-unused-vars": [2, {args: "none"}],
"@typescript-eslint/consistent-type-imports": [2, {disallowTypeAnnotations: false}],
/**
* Enforced rules
*/
// syntax preferences
"object-curly-spacing": ["error", "always"],
"quotes": [2, "single", {
"avoidEscape": true,
"allowTemplateLiterals": true
}],
"no-extra-semi": 2,
"@typescript-eslint/semi": [2],
"comma-style": [2, "last"],
"wrap-iife": [2, "inside"],
"spaced-comment": [2, "always", {
"markers": ["*"]
}],
"eqeqeq": [2],
"accessor-pairs": [2, {
"getWithoutSet": false,
"setWithoutGet": false
}],
"brace-style": [2, "1tbs", {"allowSingleLine": true}],
"curly": [2, "multi-or-nest", "consistent"],
"new-parens": 2,
"arrow-parens": [2, "as-needed"],
"prefer-const": 2,
"quote-props": [2, "consistent"],
"nonblock-statement-body-position": [2, "below"],
// anti-patterns
"no-var": 2,
"no-with": 2,
"no-multi-str": 2,
"no-caller": 2,
"no-implied-eval": 2,
"no-labels": 2,
"no-new-object": 2,
"no-octal-escape": 2,
"no-self-compare": 2,
"no-shadow-restricted-names": 2,
"no-cond-assign": 2,
"no-debugger": 2,
"no-dupe-keys": 2,
"no-duplicate-case": 2,
"no-empty-character-class": 2,
"no-unreachable": 2,
"no-unsafe-negation": 2,
"radix": 2,
"valid-typeof": 2,
"no-implicit-globals": [2],
"no-unused-expressions": [2, { "allowShortCircuit": true, "allowTernary": true, "allowTaggedTemplates": true}],
"no-proto": 2,
// es2015 features
"require-yield": 2,
"template-curly-spacing": [2, "never"],
// spacing details
"space-infix-ops": 2,
"space-in-parens": [2, "never"],
"array-bracket-spacing": [2, "never"],
"comma-spacing": [2, { "before": false, "after": true }],
"keyword-spacing": [2, "always"],
"space-before-function-paren": [2, {
"anonymous": "never",
"named": "never",
"asyncArrow": "always"
}],
"no-whitespace-before-property": 2,
"keyword-spacing": [2, {
"overrides": {
"if": {"after": true},
"else": {"after": true},
"for": {"after": true},
"while": {"after": true},
"do": {"after": true},
"switch": {"after": true},
"return": {"after": true}
}
}],
"arrow-spacing": [2, {
"after": true,
"before": true
}],
"@typescript-eslint/func-call-spacing": 2,
"@typescript-eslint/type-annotation-spacing": 2,
// file whitespace
"no-multiple-empty-lines": [2, {"max": 2}],
"no-mixed-spaces-and-tabs": 2,
"no-trailing-spaces": 2,
"linebreak-style": [ process.platform === "win32" ? 0 : 2, "unix" ],
"indent": [2, 2, { "SwitchCase": 1, "CallExpression": {"arguments": 2}, "MemberExpression": 2 }],
"key-spacing": [2, {
"beforeColon": false
}],
// copyright
"notice/notice": [2, {
"mustMatch": "Copyright",
"templateFile": require("path").join(__dirname, "utils", "copyright.js"),
}],
}
};

View file

@ -24,6 +24,7 @@ body:
## Make a minimal reproduction
To file the report, you will need a GitHub repository with a minimal (but complete) example and simple/clear steps on how to reproduce the bug.
The simpler you can make it, the more likely we are to successfully verify and fix the bug. You can create a new project with `npm init playwright@latest new-project` and then add the test code there.
Please make sure you only include the code and the dependencies absolutely necessary for your repro. Due to the security considerations, we can only run the code we trust. Major web frameworks are Ok to use, but smaller convenience libraries are not.
- type: markdown
attributes:
value: |

View file

@ -14,12 +14,12 @@ runs:
fi
echo "Allowing microphone access to all apps"
version=$(sw_vers -productVersion | cut -d. -f1)
if [[ "$version" == "14" ]]; then
if [[ "$version" == "14" || "$version" == "15" ]]; then
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
elif [[ "$version" == "12" || "$version" == "13" ]]; then
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR REPLACE INTO access VALUES('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159);"
else
echo "macOS version is unsupported. Version is $version, exiting"
exit 1
echo "Skipping unsupported macOS version $version"
exit 0
fi
echo "Successfully allowed microphone access"

14
.github/dependabot.yml vendored Normal file
View file

@ -0,0 +1,14 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
groups:
actions:
patterns:
- "*"

View file

@ -22,6 +22,7 @@ jobs:
env:
DEBUG: pw:install
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
- run: npm run build
- name: Download blob report artifact
@ -34,7 +35,7 @@ jobs:
run: |
npx playwright merge-reports --config .github/workflows/merge.config.ts ./all-blob-reports
env:
NODE_OPTIONS: --max-old-space-size=4096
NODE_OPTIONS: --max-old-space-size=8192
- name: Azure Login
uses: azure/login@v2
@ -120,21 +121,3 @@ jobs:
]),
});
core.info('Posted comment: ' + response.html_url);
const check = await github.rest.checks.create({
...context.repo,
name: 'Merge report (${{ github.event.workflow_run.name }})',
head_sha: '${{ github.event.workflow_run.head_sha }}',
status: 'completed',
conclusion: 'success',
details_url: reportUrl,
output: {
title: 'Test results for "${{ github.event.workflow_run.name }}"',
summary: [
reportMd,
'',
'---',
`Full [HTML report](${reportUrl}). Merge [workflow run](${mergeWorkflowUrl}).`
].join('\n'),
}
});

View file

@ -16,7 +16,7 @@ env:
jobs:
doc-and-lint:
name: "docs & lint"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@ -35,21 +35,27 @@ jobs:
exit 1
fi
- name: Audit prod NPM dependencies
run: npm audit --omit dev
run: node utils/check_audit.js
lint-snippets:
name: "Lint snippets"
runs-on: ubuntu-22.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- uses: actions/setup-python@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- uses: actions/setup-dotnet@v3
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: '21'
- run: npm ci
- run: pip install -r utils/doclint/linting-code-snippets/python/requirements.txt
- run: mvn package
working-directory: utils/doclint/linting-code-snippets/java
- run: node utils/doclint/linting-code-snippets/cli.js

View file

@ -1,4 +1,4 @@
export default {
testDir: '../../tests',
reporter: [['markdown'], ['html']]
reporter: [[require.resolve('../../packages/playwright/lib/reporters/markdown')], ['html']]
};

View file

@ -12,7 +12,7 @@ on:
jobs:
check:
name: Check
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
if: github.repository == 'microsoft/playwright'
steps:
- uses: actions/checkout@v4
@ -28,6 +28,10 @@ jobs:
commit_sha: context.sha,
});
const commitHeader = data.message.split('\n')[0];
const prMatch = commitHeader.match(/#(\d+)/);
const formattedCommit = prMatch
? `https://github.com/microsoft/playwright/pull/${prMatch[1]}`
: `https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.sha} (${commitHeader})`;
const title = '[Ports]: Backport client side changes for ' + currentPlaywrightVersion;
for (const repo of ['playwright-python', 'playwright-java', 'playwright-dotnet']) {
@ -50,11 +54,11 @@ jobs:
issueBody = issueCreateData.body;
}
const newBody = issueBody.trimEnd() + `
- [ ] https://github.com/${context.repo.owner}/${context.repo.repo}/commit/${context.sha} (${commitHeader})`;
- [ ] ${formattedCommit}`;
const data = await github.rest.issues.update({
owner: context.repo.owner,
repo: repo,
issue_number: issueNumber,
body: newBody
})
}
}

View file

@ -14,7 +14,7 @@ env:
jobs:
publish-canary:
name: "publish canary NPM"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
if: github.repository == 'microsoft/playwright'
permissions:
id-token: write # This is required for OIDC login (azure/login) to succeed
@ -65,7 +65,7 @@ jobs:
publish-trace-viewer:
name: "publish Trace Viewer to trace.playwright.dev"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
if: github.repository == 'microsoft/playwright'
steps:
- uses: actions/checkout@v4

View file

@ -2,12 +2,6 @@ name: "publish release - Docker"
on:
workflow_dispatch:
inputs:
is_release:
required: true
type: boolean
description: "Is this a release image?"
release:
types: [published]
@ -45,6 +39,3 @@ jobs:
- name: Login to ACR via OIDC
run: az acr login --name playwright
- run: ./utils/docker/publish_docker.sh stable
if: (github.event_name != 'workflow_dispatch' && !github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release == 'true')
- run: ./utils/docker/publish_docker.sh canary
if: (github.event_name != 'workflow_dispatch' && github.event.release.prerelease) || (github.event_name == 'workflow_dispatch' && github.event.inputs.is_release != 'true')

View file

@ -10,7 +10,7 @@ env:
jobs:
publish-driver-release:
name: "publish playwright driver to CDN"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
if: github.repository == 'microsoft/playwright'
permissions:
id-token: write # This is required for OIDC login (azure/login) to succeed

View file

@ -10,7 +10,7 @@ env:
jobs:
publish-npm-release:
name: "publish to NPM"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
if: github.repository == 'microsoft/playwright'
permissions:
contents: read

View file

@ -7,7 +7,7 @@ on:
jobs:
publish-trace-viewer:
name: "publish Trace Viewer to trace.playwright.dev"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
if: github.repository == 'microsoft/playwright'
steps:
- uses: actions/checkout@v4

View file

@ -3,16 +3,28 @@ name: Roll Browser into Playwright
on:
repository_dispatch:
types: [roll_into_pw]
workflow_dispatch:
inputs:
browser:
description: 'Browser name, e.g. chromium'
required: true
type: string
revision:
description: 'Browser revision without v prefix, e.g. 1234'
required: true
type: string
env:
ELECTRON_SKIP_BINARY_DOWNLOAD: 1
BROWSER: ${{ github.event.client_payload.browser || github.event.inputs.browser }}
REVISION: ${{ github.event.client_payload.revision || github.event.inputs.revision }}
permissions:
contents: write
jobs:
roll:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@ -24,19 +36,19 @@ jobs:
run: npx playwright install-deps
- name: Roll to new revision
run: |
./utils/roll_browser.js ${{ github.event.client_payload.browser }} ${{ github.event.client_payload.revision }}
./utils/roll_browser.js $BROWSER $REVISION
npm run build
- name: Prepare branch
id: prepare-branch
run: |
BRANCH_NAME="roll-into-pw-${{ github.event.client_payload.browser }}/${{ github.event.client_payload.revision }}"
BRANCH_NAME="roll-into-pw-${BROWSER}/${REVISION}"
echo "BRANCH_NAME=$BRANCH_NAME" >> $GITHUB_OUTPUT
git config --global user.name github-actions
git config --global user.email 41898282+github-actions[bot]@users.noreply.github.com
git checkout -b "$BRANCH_NAME"
git add .
git commit -m "feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}"
git push origin $BRANCH_NAME
git commit -m "feat(${BROWSER}): roll to r${REVISION}"
git push origin $BRANCH_NAME --force
- name: Create Pull Request
uses: actions/github-script@v7
with:
@ -47,7 +59,7 @@ jobs:
repo: 'playwright',
head: 'microsoft:${{ steps.prepare-branch.outputs.BRANCH_NAME }}',
base: 'main',
title: 'feat(${{ github.event.client_payload.browser }}): roll to r${{ github.event.client_payload.revision }}',
title: 'feat(${{ env.BROWSER }}): roll to r${{ env.REVISION }}',
});
await github.rest.issues.addLabels({
owner: 'microsoft',

71
.github/workflows/tests_bidi.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: tests BiDi
on:
workflow_dispatch:
pull_request:
branches:
- main
paths:
- .github/workflows/tests_bidi.yml
- packages/playwright-core/src/server/bidi/**
- tests/bidi/**
schedule:
# Run every day at midnight
- cron: '0 0 * * *'
env:
FORCE_COLOR: 1
jobs:
test_bidi:
name: BiDi
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-24.04
permissions:
id-token: write # This is required for OIDC login (azure/login) to succeed
contents: read # This is required for actions/checkout to succeed
strategy:
fail-fast: false
matrix:
channel: [bidi-chromium, bidi-firefox-nightly]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
- run: npm run build
- run: npx playwright install --with-deps chromium
if: matrix.channel == 'bidi-chromium'
- run: npx -y @puppeteer/browsers install firefox@nightly
if: matrix.channel == 'bidi-firefox-nightly'
- name: Run tests
run: xvfb-run --auto-servernum --server-args="-screen 0 1280x960x24" -- npm run biditest -- --project=${{ matrix.channel }}*
env:
PWTEST_USE_BIDI_EXPECTATIONS: '1'
- name: Upload csv report to GitHub
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: csv-report-${{ matrix.channel }}
path: test-results/report.csv
retention-days: 7
- name: Azure Login
if: ${{ !cancelled() && github.ref == 'refs/heads/main' }}
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_BLOB_REPORTS_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_BLOB_REPORTS_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_BLOB_REPORTS_SUBSCRIPTION_ID }}
- name: Upload report.csv to Azure
if: ${{ !cancelled() && github.ref == 'refs/heads/main' }}
run: |
REPORT_DIR='bidi-reports'
azcopy cp "./test-results/report.csv" "https://mspwblobreport.blob.core.windows.net/\$web/$REPORT_DIR/${{ matrix.channel }}.csv"
echo "Report url: https://mspwblobreport.z1.web.core.windows.net/$REPORT_DIR/${{ matrix.channel }}.csv"
env:
AZCOPY_AUTO_LOGIN_TYPE: AZCLI

View file

@ -24,9 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
# Stick with macos-latest-large for now which is Intel-based until
# https://github.com/microsoft/playwright/issues/30705 is fixed.
os: [ubuntu-latest, macos-latest-large, windows-latest]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@ -66,7 +64,7 @@ jobs:
contents: read # This is required for actions/checkout to succeed
steps:
- uses: actions/checkout@v4
- uses: actions/setup-dotnet@v3
- uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- run: dotnet build
@ -88,11 +86,15 @@ jobs:
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
test_clock_frozen_time_linux:
name: Frozen time library
name: time library - ${{ matrix.clock }}
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
permissions:
id-token: write # This is required for OIDC login (azure/login) to succeed
contents: read # This is required for actions/checkout to succeed
strategy:
fail-fast: false
matrix:
clock: [frozen, realtime]
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
@ -101,32 +103,36 @@ jobs:
node-version: 20
browsers-to-install: chromium
command: npm run test -- --project=chromium-*
bot-name: "frozen-time-library-chromium-linux"
bot-name: "${{ matrix.clock }}-time-library-chromium-linux"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PW_FREEZE_TIME: 1
PW_CLOCK: ${{ matrix.clock }}
test_clock_frozen_time_test_runner:
name: Frozen time test runner
name: time test runner - ${{ matrix.clock }}
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-22.04
permissions:
id-token: write # This is required for OIDC login (azure/login) to succeed
contents: read # This is required for actions/checkout to succeed
strategy:
fail-fast: false
matrix:
clock: [frozen, realtime]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
node-version: 20
command: npm run ttest
bot-name: "frozen-time-runner-chromium-linux"
bot-name: "${{ matrix.clock }}-time-runner-chromium-linux"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PW_FREEZE_TIME: 1
PW_CLOCK: ${{ matrix.clock }}
test_electron:
name: Electron - ${{ matrix.os }}
@ -141,6 +147,13 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- name: Setup Ubuntu Binary Installation # TODO: Remove when https://github.com/electron/electron/issues/42510 is fixed
if: ${{ runner.os == 'Linux' }}
run: |
if grep -q "Ubuntu 24" /etc/os-release; then
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
fi
shell: bash
- uses: ./.github/actions/run-test
with:
browsers-to-install: chromium

View file

@ -215,11 +215,17 @@ jobs:
- uses: actions/checkout@v4
- run: npm install -g yarn@1
- run: npm install -g pnpm@8
- name: Setup Ubuntu Binary Installation # TODO: Remove when https://github.com/electron/electron/issues/42510 is fixed
if: ${{ runner.os == 'Linux' }}
run: |
if grep -q "Ubuntu 24" /etc/os-release; then
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
fi
shell: bash
- uses: ./.github/actions/run-test
with:
command: npm run itest
bot-name: "package-installations-${{ matrix.os }}"
# TODO: figure out why itest fails with 'bash' on Windows.
shell: ${{ matrix.os == 'windows-latest' && 'pwsh' || 'bash' }}
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}

View file

@ -50,8 +50,15 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos-12, macos-13, macos-14]
# Intel: *-large
# Arm64: *-xlarge
os: [macos-13-large, macos-13-xlarge, macos-14-large, macos-14-xlarge]
browser: [chromium, firefox, webkit]
include:
- os: macos-15-large
browser: webkit
- os: macos-15-xlarge
browser: webkit
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@ -100,6 +107,13 @@ jobs:
- uses: actions/checkout@v4
- run: npm install -g yarn@1
- run: npm install -g pnpm@8
- name: Setup Ubuntu Binary Installation # TODO: Remove when https://github.com/electron/electron/issues/42510 is fixed
if: ${{ runner.os == 'Linux' }}
run: |
if grep -q "Ubuntu 24" /etc/os-release; then
sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
fi
shell: bash
- uses: ./.github/actions/run-test
with:
node-version: ${{ matrix.node_version }}
@ -116,7 +130,13 @@ jobs:
fail-fast: false
matrix:
browser: [chromium, firefox, webkit]
os: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04, macos-14, windows-latest]
os: [ubuntu-24.04, macos-14-xlarge, windows-latest]
include:
# We have different binaries per Ubuntu version for WebKit.
- browser: webkit
os: ubuntu-20.04
- browser: webkit
os: ubuntu-22.04
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
@ -177,359 +197,95 @@ jobs:
PWTEST_TRACE: 1
PWTEST_CHANNEL: ${{ matrix.channel }}
chrome_stable_linux:
name: "Chrome Stable (Linux)"
test_chromium_channels:
name: Test ${{ matrix.channel }} on ${{ matrix.runs-on }}
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-20.04
runs-on: ${{ matrix.runs-on }}
strategy:
fail-fast: false
matrix:
channel: [chrome, chrome-beta, msedge, msedge-beta, msedge-dev]
runs-on: [ubuntu-20.04, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chrome
browsers-to-install: ${{ matrix.channel }}
command: npm run ctest
bot-name: "chrome-stable-linux"
bot-name: ${{ matrix.channel }}-${{ matrix.runs-on }}
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chrome
chrome_stable_win:
name: "Chrome Stable (Win)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chrome
command: npm run ctest
bot-name: "chrome-stable-windows"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chrome
chrome_stable_mac:
name: "Chrome Stable (Mac)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chrome
command: npm run ctest
bot-name: "chrome-stable-mac"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chrome
PWTEST_CHANNEL: ${{ matrix.channel }}
chromium_tot:
name: Chromium tip-of-tree ${{ matrix.os }}
name: Chromium tip-of-tree ${{ matrix.os }}${{ matrix.headed }}
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, macos-12, windows-latest]
os: [ubuntu-20.04, macos-13, windows-latest]
headed: ['--headed', '']
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chromium-tip-of-tree
command: npm run ctest
bot-name: "tip-of-tree-${{ matrix.os }}"
command: npm run ctest -- ${{ matrix.headed }}
bot-name: "chromium-tip-of-tree-${{ matrix.os }}${{ matrix.headed }}"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chromium-tip-of-tree
chromium_tot_headed:
name: Chromium tip-of-tree headed ${{ matrix.os }}
chromium_tot_headless_shell:
name: Chromium tip-of-tree headless-shell-${{ matrix.os }}
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
os: [ubuntu-20.04]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chromium-tip-of-tree
command: npm run ctest -- --headed
bot-name: "tip-of-tree-headed-${{ matrix.os }}"
browsers-to-install: chromium-tip-of-tree-headless-shell
command: npm run ctest
bot-name: "chromium-tip-of-tree-headless-shell-${{ matrix.os }}"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chromium-tip-of-tree
PWTEST_CHANNEL: chromium-tip-of-tree-headless-shell
firefox_beta_linux:
name: "Firefox Beta (Linux)"
firefox_beta:
name: Firefox Beta ${{ matrix.os }}
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-20.04
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-20.04, windows-latest, macos-latest]
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: firefox-beta chromium
command: npm run ftest
bot-name: "firefox-beta-linux"
bot-name: "firefox-beta-${{ matrix.os }}"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: firefox-beta
firefox_beta_win:
name: "Firefox Beta (Win)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: firefox-beta chromium
command: npm run ftest -- --workers=1
bot-name: "firefox-beta-windows"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: firefox-beta
firefox_beta_mac:
name: "Firefox Beta (Mac)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
# Stick with macos-latest-large for now which is Intel-based until
# https://github.com/microsoft/playwright/issues/30705 is fixed.
runs-on: macos-latest-large
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: firefox-beta chromium
command: npm run ftest
bot-name: "firefox-beta-mac"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: firefox-beta
edge_stable_mac:
name: "Edge Stable (Mac)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge
command: npm run ctest
bot-name: "edge-stable-mac"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge
edge_stable_win:
name: "Edge Stable (Win)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge
command: npm run ctest
bot-name: "edge-stable-windows"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge
edge_stable_linux:
name: "Edge Stable (Linux)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge
command: npm run ctest
bot-name: "edge-stable-linux"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge
edge_beta_mac:
name: "Edge Beta (Mac)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge-beta
command: npm run ctest
bot-name: "edge-beta-mac"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge-beta
edge_beta_win:
name: "Edge Beta (Win)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge-beta
command: npm run ctest
bot-name: "edge-beta-windows"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge-beta
edge_beta_linux:
name: "Edge Beta (Linux)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge-beta
command: npm run ctest
bot-name: "edge-beta-linux"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge-beta
edge_dev_mac:
name: "Edge Dev (Mac)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge-dev
command: npm run ctest
bot-name: "edge-dev-mac"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge-dev
edge_dev_win:
name: "Edge Dev (Win)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge-dev
command: npm run ctest
bot-name: "edge-dev-windows"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge-dev
edge_dev_linux:
name: "Edge Dev (Linux)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: msedge-dev
command: npm run ctest
bot-name: "edge-dev-linux"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: msedge-dev
chrome_beta_linux:
name: "Chrome Beta (Linux)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chrome-beta
command: npm run ctest
bot-name: "chrome-beta-linux"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chrome-beta
chrome_beta_win:
name: "Chrome Beta (Win)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chrome-beta
command: npm run ctest
bot-name: "chrome-beta-windows"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chrome-beta
chrome_beta_mac:
name: "Chrome Beta (Mac)"
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
browsers-to-install: chrome-beta
command: npm run ctest
bot-name: "chrome-beta-mac"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PWTEST_CHANNEL: chrome-beta
build-playwright-driver:
name: "build-playwright-driver"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
@ -540,19 +296,25 @@ jobs:
- run: npx playwright install-deps
- run: utils/build/build-playwright-driver.sh
test_linux_chromium_headless_new:
name: Linux Chromium Headless New
test_channel_chromium:
name: Test channel=chromium
environment: ${{ github.event_name == 'push' && 'allow-uploading-flakiness-results' || null }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
runs-on: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/run-test
with:
# TODO: this should pass --no-shell.
# However, codegen tests do not inherit the channel and try to launch headless shell.
browsers-to-install: chromium
command: npm run ctest
bot-name: "headless-new"
bot-name: "channel-chromium-${{ matrix.runs-on }}"
flakiness-client-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_CLIENT_ID }}
flakiness-tenant-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_TENANT_ID }}
flakiness-subscription-id: ${{ secrets.AZURE_FLAKINESS_DASHBOARD_SUBSCRIPTION_ID }}
env:
PLAYWRIGHT_CHROMIUM_USE_HEADLESS_NEW: 1
PWTEST_CHANNEL: chromium

View file

@ -34,7 +34,7 @@ jobs:
PLAYWRIGHT_SERVICE_RUN_ID: ${{ github.run_id }}-${{ github.run_attempt }}-${{ github.sha }}
- name: Upload blob report to GitHub
if: ${{ !cancelled() }}
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: all-blob-reports
path: blob-report
@ -53,7 +53,7 @@ jobs:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1
- run: npm run build
- name: Download blob report artifact
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: all-blob-reports
path: all-blob-reports

View file

@ -9,7 +9,7 @@ on:
jobs:
trigger:
name: "trigger"
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
steps:
- run: |
curl -X POST \

4
.gitignore vendored
View file

@ -33,4 +33,6 @@ test-results
/tests/installation/output/
/tests/installation/.registry.json
.cache/
.eslintcache
.eslintcache
playwright.env
/firefox/

View file

@ -1,88 +1,87 @@
# Contributing
- [How to Contribute](#how-to-contribute)
* [Getting Code](#getting-code)
* [Code reviews](#code-reviews)
* [Code Style](#code-style)
* [API guidelines](#api-guidelines)
* [Commit Messages](#commit-messages)
* [Writing Documentation](#writing-documentation)
* [Adding New Dependencies](#adding-new-dependencies)
* [Running & Writing Tests](#running--writing-tests)
* [Public API Coverage](#public-api-coverage)
- [Contributor License Agreement](#contributor-license-agreement)
* [Code of Conduct](#code-of-conduct)
## Choose an issue
## How to Contribute
Playwright **requires an issue** for every contribution, except for minor documentation updates. We strongly recommend to pick an issue labeled `open-to-a-pull-request` for your first contribution to the project.
We strongly recommend that you open an issue before beginning any code modifications. This is particularly important if the changes involve complex logic or if the existing code isn't immediately clear. By doing so, we can discuss and agree upon the best approach to address a bug or implement a feature, ensuring that our efforts are aligned.
If you are passioned about a bug/feature, but cannot find an issue describing it, **file an issue first**. This will facilitate the discussion and you might get some early feedback from project maintainers before spending your time on creating a pull request.
### Getting Code
Make sure you're running Node.js 20 to verify and upgrade NPM do:
## Make a change
Make sure you're running Node.js 20 or later.
```bash
node --version
npm --version
npm i -g npm@latest
```
1. Clone this repository
Clone the repository. If you plan to send a pull request, it might be better to [fork the repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo) first.
```bash
git clone https://github.com/microsoft/playwright
cd playwright
```
2. Install dependencies
Install dependencies and run the build in watch mode.
```bash
npm ci
npm run watch
npx playwright install
```
3. Build Playwright
**Experimental dev mode with Hot Module Replacement for recorder/trace-viewer/UI Mode**
```bash
npm run build
```
PW_HMR=1 npm run watch
PW_HMR=1 npx playwright show-trace
PW_HMR=1 npm run ctest -- --ui
PW_HMR=1 npx playwright codegen
PW_HMR=1 npx playwright show-report
```
4. Run all Playwright tests locally. For more information about tests, read [Running & Writing Tests](#running--writing-tests).
Playwright is a multi-package repository that uses npm workspaces. For browser APIs, look at [`packages/playwright-core`](https://github.com/microsoft/playwright/blob/main/packages/playwright-core). For test runner, see [`packages/playwright`](https://github.com/microsoft/playwright/blob/main/packages/playwright).
```bash
npm test
```
Note that some files are generated by the build, so the watch process might override your changes if done in the wrong file. For example, TypeScript types for the API are generated from the [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src).
### Code reviews
Coding style is fully defined in [.eslintrc](https://github.com/microsoft/playwright/blob/main/.eslintrc.js). Before creating a pull request, or at any moment during development, run linter to check all kinds of things:
```bash
npm run lint
```
All submissions, including submissions by project members, require review. We
use GitHub pull requests for this purpose. Consult
[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
information on using pull requests.
Comments should have an explicit purpose and should improve readability rather than hinder it. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory.
### Code Style
### Write documentation
- Coding style is fully defined in [.eslintrc](https://github.com/microsoft/playwright/blob/main/.eslintrc.js)
- Comments should be generally avoided. If the code would not be understood without comments, consider re-writing the code to make it self-explanatory.
Every part of the public API should be documented in [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src), in the same change that adds/changes the API. We use markdown files with custom structure to specify the API. Take a look around for an example.
To run code linter, use:
Various other files are generated from the API specification. If you are running `npm run watch`, these will be re-generated automatically.
```bash
npm run eslint
```
Larger changes will require updates to the documentation guides as well. This will be made clear during the code review.
### API guidelines
## Add a test
When authoring new API methods, consider the following:
Playwright requires a test for almost any new or modified functionality. An exception would be a pure refactoring, but chances are you are doing more than that.
- Expose as little information as needed. When in doubt, dont expose new information.
- Methods are used in favor of getters/setters.
- The only exception is namespaces, e.g. `page.keyboard` and `page.coverage`
- All string literals must be lowercase. This includes event names and option values.
- Avoid adding "sugar" API (API that is trivially implementable in user-space) unless they're **very** common.
There are multiple [test suites](https://github.com/microsoft/playwright/blob/main/tests) in Playwright that will be executed on the CI. The two most important that you need to run locally are:
### Commit Messages
- Library tests cover APIs not related to the test runner.
```bash
# fast path runs all tests in Chromium
npm run ctest
Commit messages should follow the Semantic Commit Messages format:
# slow path runs all tests in three browsers
npm run test
```
- Test runner tests.
```bash
npm run ttest
```
Since Playwright tests are using Playwright under the hood, everything from our documentation applies, for example [this guide on running and debugging tests](https://playwright.dev/docs/running-tests#running-tests).
Note that tests should be *hermetic*, and not depend on external services. Tests should work on all three platforms: macOS, Linux and Windows.
## Write a commit message
Commit messages should follow the [Semantic Commit Messages](https://www.conventionalcommits.org/en/v1.0.0/) format:
```
label(namespace): title
@ -93,144 +92,57 @@ footer
```
1. *label* is one of the following:
- `fix` - playwright bug fixes.
- `feat` - playwright features.
- `docs` - changes to docs, e.g. `docs(api.md): ..` to change documentation.
- `test` - changes to playwright tests infrastructure.
- `devops` - build-related work, e.g. CI related patches and general changes to the browser build infrastructure
- `fix` - bug fixes
- `feat` - new features
- `docs` - documentation-only changes
- `test` - test-only changes
- `devops` - changes to the CI or build
- `chore` - everything that doesn't fall under previous categories
2. *namespace* is put in parenthesis after label and is optional. Must be lowercase.
3. *title* is a brief summary of changes.
4. *description* is **optional**, new-line separated from title and is in present tense.
5. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to github issues.
1. *namespace* is put in parenthesis after label and is optional. Must be lowercase.
1. *title* is a brief summary of changes.
1. *description* is **optional**, new-line separated from title and is in present tense.
1. *footer* is **optional**, new-line separated from *description* and contains "fixes" / "references" attribution to github issues.
Example:
```
fix(firefox): make sure session cookies work
feat(trace viewer): network panel filtering
This patch fixes session cookies in the firefox browser.
This patch adds a filtering toolbar to the network panel.
<link to a screenshot>
Fixes #123, fixes #234
Fixes #123, references #234.
```
### Writing Documentation
## Send a pull request
All API classes, methods, and events should have a description in [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src). There's a [documentation linter](https://github.com/microsoft/playwright/tree/main/utils/doclint) which makes sure documentation is aligned with the codebase.
All submissions, including submissions by project members, require review. We use GitHub pull requests for this purpose. Consult [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more information on using pull requests.
To run the documentation linter, use:
After a successful code review, one of the maintainers will merge your pull request. Congratulations!
```bash
npm run doc
```
## More details
To build the documentation site locally and test how your changes will look in practice:
**No new dependencies**
1. Clone the [microsoft/playwright.dev](https://github.com/microsoft/playwright.dev) repo
1. Follow [the playwright.dev README instructions to "roll docs"](https://github.com/microsoft/playwright.dev/#roll-docs) against your local `playwright` repo with your changes in progress
1. Follow [the playwright.dev README instructions to "run dev server"](https://github.com/microsoft/playwright.dev/#run-dev-server) to view your changes
There is a very high bar for new dependencies, including updating to a new version of an existing dependency. We recommend to explicitly discuss this in an issue and get a green light from a maintainer, before creating a pull request that updates dependencies.
### Adding New Dependencies
For all dependencies (both installation and development):
- **Do not add** a dependency if the desired functionality is easily implementable.
- If adding a dependency, it should be well-maintained and trustworthy.
A barrier for introducing new installation dependencies is especially high:
- **Do not add** installation dependency unless it's critical to project success.
### Running & Writing Tests
- Every feature should be accompanied by a test.
- Every public api event/method should be accompanied by a test.
- Tests should be *hermetic*. Tests should not depend on external services.
- Tests should work on all three platforms: Mac, Linux and Win. This is especially important for screenshot tests.
Playwright tests are located in [`tests`](https://github.com/microsoft/playwright/blob/main/tests) and use `@playwright/test` test runner.
These are integration tests, making sure public API methods and events work as expected.
- To run all tests:
```bash
npx playwright install
npm run test
```
Be sure to run `npm run build` or let `npm run watch` run before you re-run the
tests after making your changes to check them.
- To run all tests in Chromium
```bash
npm run ctest # also `ftest` for firefox and `wtest` for WebKit
```
- To run the Playwright test runner tests
```bash
npm run ttest
npm run ttest -- --grep "specific test"
```
- To run a specific test, substitute `it` with `it.only`, or use the `--grep 'My test'` CLI parameter:
```js
...
// Using "it.only" to run a specific test
it.only('should work', async ({server, page}) => {
const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok).toBe(true);
});
// or
playwright test --config=xxx --grep 'should work'
```
- To disable a specific test, substitute `it` with `it.skip`:
```js
...
// Using "it.skip" to skip a specific test
it.skip('should work', async ({server, page}) => {
const response = await page.goto(server.EMPTY_PAGE);
expect(response.ok).toBe(true);
});
```
- To run tests in non-headless (headed) mode:
```bash
npm run ctest -- --headed
```
- To run tests with custom browser executable, specify `CRPATH`, `WKPATH` or `FFPATH` env variable that points to browser executable:
**Custom browser build**
To run tests with custom browser executable, specify `CRPATH`, `WKPATH` or `FFPATH` env variable that points to browser executable:
```bash
CRPATH=<path-to-executable> npm run ctest
```
- To run tests in slow-mode:
You will also find `DEBUG=pw:browser` useful for debugging custom builds.
```bash
SLOW_MO=500 npm run wtest -- --headed
```
**Building documentation site**
- When should a test be marked with `skip` or `fail`?
The [playwright.dev](https://playwright.dev/) documentation site lives in a separate repository, and documentation from [`docs/src`](https://github.com/microsoft/playwright/blob/main/docs/src) is frequently rolled there.
- **`skip(condition)`**: This test *should ***never*** work* for `condition`
where `condition` is usually a certain browser like `FFOX` (for Firefox),
`WEBKIT` (for WebKit), and `CHROMIUM` (for Chromium).
For example, the [alt-click downloads test](https://github.com/microsoft/playwright/blob/471ccc72d3f0847caa36f629b394a028c7750d93/test/download.spec.js#L86) is marked
with `skip(FFOX)` since an alt-click in Firefox will not produce a download
even if a person was driving the browser.
- **`fail(condition)`**: This test *should ***eventually*** work* for `condition`
where `condition` is usually a certain browser like `FFOX` (for Firefox),
`WEBKIT` (for WebKit), and `CHROMIUM` (for Chromium).
For example, the [alt-click downloads test](https://github.com/microsoft/playwright/blob/471ccc72d3f0847caa36f629b394a028c7750d93/test/download.spec.js#L86) is marked
with `fail(CHROMIUM || WEBKIT)` since Playwright performing these actions
currently diverges from what a user would experience driving a Chromium or
WebKit.
Most of the time this should not concern you. However, if you are doing something unusual in the docs, you can build locally and test how your changes will look in practice:
1. Clone the [microsoft/playwright.dev](https://github.com/microsoft/playwright.dev) repo.
1. Follow [the playwright.dev README instructions to "roll docs"](https://github.com/microsoft/playwright.dev/#roll-docs) against your local `playwright` repo with your changes in progress.
1. Follow [the playwright.dev README instructions to "run dev server"](https://github.com/microsoft/playwright.dev/#run-dev-server) to view your changes.
## Contributor License Agreement

35
FILING_ISSUES.md Normal file
View file

@ -0,0 +1,35 @@
# How to File a Bug Report That Actually Gets Resolved
Make sure youre on the latest Playwright release before filing. Check existing GitHub issues to avoid duplicates.
## Use the Template
Follow the **Bug Report** template. It guides you step-by-step:
- Fill it out thoroughly.
- Clearly list the steps needed to reproduce the bug.
- Provide what you expected to see versus what happened in reality.
- Include system info from `npx envinfo --preset playwright`.
## Keep Your Repro Minimal
We can't parse your entire code base. Reduce it down to the absolute essentials:
- Start a fresh project (`npm init playwright@latest new-project`).
- Add only the code/DOM needed to show the problem.
- Only use major frameworks if necessary (React, Angular, static HTTP server, etc.).
- Avoid adding extra libraries unless absolutely necessary. Note that we won't install any suspect dependencies.
## Why This Matters
- Most issues that lack a repro turn out to be misconfigurations or usage errors.
- We can't fix problems if we cant reproduce them ourselves.
- We cant debug entire private projects or handle sensitive credentials.
- Each confirmed bug will have a test in our repo, so your repro must be as clean as possible.
## More Help
- [Stack Overflows Minimal Reproducible Example Guide](https://stackoverflow.com/help/minimal-reproducible-example)
- [Playwright Debugging Tools](https://playwright.dev/docs/debug)
## Bottom Line
A well-isolated bug speeds up verification and resolution. Minimal, public repro or its unlikely we can assist.

View file

@ -1,6 +1,6 @@
# 🎭 Playwright
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-127.0.6533.5-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-127.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-17.4-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop -->
[![npm version](https://img.shields.io/npm/v/playwright.svg)](https://www.npmjs.com/package/playwright) <!-- GEN:chromium-version-badge -->[![Chromium version](https://img.shields.io/badge/chromium-134.0.6998.35-blue.svg?logo=google-chrome)](https://www.chromium.org/Home)<!-- GEN:stop --> <!-- GEN:firefox-version-badge -->[![Firefox version](https://img.shields.io/badge/firefox-135.0-blue.svg?logo=firefoxbrowser)](https://www.mozilla.org/en-US/firefox/new/)<!-- GEN:stop --> <!-- GEN:webkit-version-badge -->[![WebKit version](https://img.shields.io/badge/webkit-18.2-blue.svg?logo=safari)](https://webkit.org/)<!-- GEN:stop --> [![Join Discord](https://img.shields.io/badge/join-discord-infomational)](https://aka.ms/playwright/discord)
## [Documentation](https://playwright.dev) | [API reference](https://playwright.dev/docs/api/class-playwright)
@ -8,9 +8,9 @@ Playwright is a framework for Web Testing and Automation. It allows testing [Chr
| | Linux | macOS | Windows |
| :--- | :---: | :---: | :---: |
| Chromium <!-- GEN:chromium-version -->127.0.6533.5<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->17.4<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->127.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Chromium <!-- GEN:chromium-version -->134.0.6998.35<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| WebKit <!-- GEN:webkit-version -->18.2<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
| Firefox <!-- GEN:firefox-version -->135.0<!-- GEN:stop --> | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Headless execution is supported for all browsers on all platforms. Check out [system requirements](https://playwright.dev/docs/intro#system-requirements) for details.
@ -46,7 +46,6 @@ npx playwright install
You can optionally install only selected browsers, see [install browsers](https://playwright.dev/docs/cli#install-browsers) for more details. Or you can install no browsers at all and use existing [browser channels](https://playwright.dev/docs/browsers).
* [Getting started](https://playwright.dev/docs/intro)
* [Installation configuration](https://playwright.dev/docs/installation)
* [API reference](https://playwright.dev/docs/api/class-playwright)
## Capabilities
@ -163,7 +162,7 @@ test('Intercept network requests', async ({ page }) => {
## Resources
* [Documentation](https://playwright.dev/docs/intro)
* [Documentation](https://playwright.dev)
* [API reference](https://playwright.dev/docs/api/class-playwright/)
* [Contribution guide](CONTRIBUTING.md)
* [Changelog](https://github.com/microsoft/playwright/releases)

View file

@ -1,20 +1,20 @@
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.3 BLOCK -->
<!-- BEGIN MICROSOFT SECURITY.MD V0.0.9 BLOCK -->
## Security
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet) and [Xamarin](https://github.com/xamarin).
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below.
If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below.
## Reporting Security Issues
**Please do not report security vulnerabilities through public GitHub issues.**
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report).
Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc).
If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/security.md/msrc/pgp).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc).
Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
@ -28,7 +28,7 @@ Please include the requested information listed below (as much as you can provid
This information will help us triage your report more quickly.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs.
If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs.
## Preferred Languages
@ -36,6 +36,6 @@ We prefer all communications to be in English.
## Policy
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd).
Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd).
<!-- END MICROSOFT SECURITY.MD BLOCK -->

17
SUPPORT.md Normal file
View file

@ -0,0 +1,17 @@
# Support
## How to file issues and get help
This project uses GitHub issues to track bugs and feature requests. Please search the [existing issues][gh-issues] before filing new ones to avoid duplicates. For new issues, file your bug or feature request as a new issue using corresponding template.
For help and questions about using this project, please see the [docs site for Playwright][docs].
Join our community [Discord Server][discord-server] to connect with other developers using Playwright and ask questions in our 'help-playwright' forum.
## Microsoft Support Policy
Support for Playwright is limited to the resources listed above.
[gh-issues]: https://github.com/microsoft/playwright/issues/
[docs]: https://playwright.dev/
[discord-server]: https://aka.ms/playwright/discord

View file

@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/mozilla/gecko-dev"
BASE_BRANCH="release"
BASE_REVISION="f8704c84a751716bad093b9bdc482db53fe5b3ea"
BASE_REVISION="5cfa81898f6eef8fb1abe463e5253cea5bc17f3f"

View file

@ -145,9 +145,13 @@ class NetworkRequest {
}
this._expectingInterception = false;
this._expectingResumedRequest = undefined; // { method, headers, postData }
this._overriddenHeadersForRedirect = redirectedFrom?._overriddenHeadersForRedirect;
this._sentOnResponse = false;
this._fulfilled = false;
if (this._pageNetwork)
if (this._overriddenHeadersForRedirect)
overrideRequestHeaders(httpChannel, this._overriddenHeadersForRedirect);
else if (this._pageNetwork)
appendExtraHTTPHeaders(httpChannel, this._pageNetwork.combinedExtraHTTPHeaders());
this._responseBodyChunks = [];
@ -194,6 +198,7 @@ class NetworkRequest {
// Public interception API.
fulfill(status, statusText, headers, base64body) {
this._fulfilled = true;
this._interceptedChannel.synthesizeStatus(status, statusText);
for (const header of headers) {
this._interceptedChannel.synthesizeHeader(header.name, header.value);
@ -228,20 +233,13 @@ class NetworkRequest {
if (!this._expectingResumedRequest)
return;
const { method, headers, postData } = this._expectingResumedRequest;
this._overriddenHeadersForRedirect = headers;
this._expectingResumedRequest = undefined;
if (headers) {
for (const header of requestHeaders(this.httpChannel)) {
// We cannot remove the "host" header.
if (header.name.toLowerCase() === 'host')
continue;
this.httpChannel.setRequestHeader(header.name, '', false /* merge */);
}
for (const header of headers)
this.httpChannel.setRequestHeader(header.name, header.value, false /* merge */);
} else if (this._pageNetwork) {
if (headers)
overrideRequestHeaders(this.httpChannel, headers);
else if (this._pageNetwork)
appendExtraHTTPHeaders(this.httpChannel, this._pageNetwork.combinedExtraHTTPHeaders());
}
if (method)
this.httpChannel.requestMethod = method;
if (postData !== undefined)
@ -600,6 +598,8 @@ class NetworkObserver {
proxyFilter.onProxyFilterResult(defaultProxyInfo);
return;
}
if (this._targetRegistry.shouldBustHTTPAuthCacheForProxy(proxy))
Services.obs.notifyObservers(null, "net:clear-active-logins");
proxyFilter.onProxyFilterResult(protocolProxyService.newProxyInfo(
proxy.type,
proxy.host,
@ -769,6 +769,20 @@ function requestHeaders(httpChannel) {
return headers;
}
function clearRequestHeaders(httpChannel) {
for (const header of requestHeaders(httpChannel)) {
// We cannot remove the "host" header.
if (header.name.toLowerCase() === 'host')
continue;
httpChannel.setRequestHeader(header.name, '', false /* merge */);
}
}
function overrideRequestHeaders(httpChannel, headers) {
clearRequestHeaders(httpChannel);
appendExtraHTTPHeaders(httpChannel, headers);
}
function causeTypeToString(causeType) {
for (let key in Ci.nsIContentPolicy) {
if (Ci.nsIContentPolicy[key] === causeType)
@ -801,7 +815,8 @@ class ResponseStorage {
return;
}
let encodings = [];
if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion) {
// Note: fulfilled request comes with decoded body right away.
if ((request.httpChannel instanceof Ci.nsIEncodedChannel) && request.httpChannel.contentEncodings && !request.httpChannel.applyConversion && !request._fulfilled) {
const encodingHeader = request.httpChannel.getResponseHeader("Content-Encoding");
encodings = encodingHeader.split(/\s*\t*,\s*\t*/);
}

View file

@ -116,6 +116,7 @@ class TargetRegistry {
this._browserToTarget = new Map();
this._browserIdToTarget = new Map();
this._proxiesWithClashingAuthCacheKeys = new Set();
this._browserProxy = null;
// Cleanup containers from previous runs (if any)
@ -234,12 +235,50 @@ class TargetRegistry {
onOpenWindow(win);
}
// Firefox uses nsHttpAuthCache to cache authentication to the proxy.
// If we're provided with a single proxy with a multiple different authentications, then
// we should clear the nsHttpAuthCache on every request.
shouldBustHTTPAuthCacheForProxy(proxy) {
return this._proxiesWithClashingAuthCacheKeys.has(proxy);
}
_updateProxiesWithSameAuthCacheAndDifferentCredentials() {
const proxyIdToCredentials = new Map();
const allProxies = [...this._browserContextIdToBrowserContext.values()].map(bc => bc._proxy).filter(Boolean);
if (this._browserProxy)
allProxies.push(this._browserProxy);
const proxyAuthCacheKeyAndProxy = allProxies.map(proxy => [
JSON.stringify({
type: proxy.type,
host: proxy.host,
port: proxy.port,
}),
proxy,
]);
this._proxiesWithClashingAuthCacheKeys.clear();
proxyAuthCacheKeyAndProxy.sort(([cacheKey1], [cacheKey2]) => cacheKey1 < cacheKey2 ? -1 : 1);
for (let i = 0; i < proxyAuthCacheKeyAndProxy.length - 1; ++i) {
const [cacheKey1, proxy1] = proxyAuthCacheKeyAndProxy[i];
const [cacheKey2, proxy2] = proxyAuthCacheKeyAndProxy[i + 1];
if (cacheKey1 !== cacheKey2)
continue;
if (proxy1.username === proxy2.username && proxy1.password === proxy2.password)
continue;
// `proxy1` and `proxy2` have the same caching key, but serve different credentials.
// We have to bust HTTP Auth Cache everytime there's a request that will use either of the proxies.
this._proxiesWithClashingAuthCacheKeys.add(proxy1);
this._proxiesWithClashingAuthCacheKeys.add(proxy2);
}
}
async cancelDownload(options) {
this._downloadInterceptor.cancelDownload(options.uuid);
}
setBrowserProxy(proxy) {
this._browserProxy = proxy;
this._updateProxiesWithSameAuthCacheAndDifferentCredentials();
}
getProxyInfo(channel) {
@ -354,7 +393,8 @@ class PageTarget {
this._videoRecordingInfo = undefined;
this._screencastRecordingInfo = undefined;
this._dialogs = new Map();
this.forcedColors = 'no-override';
this.forcedColors = 'none';
this.disableCache = false;
this.mediumOverride = '';
this.crossProcessCookie = {
initScripts: [],
@ -367,7 +407,7 @@ class PageTarget {
onLocationChange: (aWebProgress, aRequest, aLocation) => this._onNavigated(aLocation),
};
this._eventListeners = [
helper.addObserver(this._updateModalDialogs.bind(this), 'tabmodal-dialog-loaded'),
helper.addObserver(this._updateModalDialogs.bind(this), 'common-dialog-loaded'),
helper.addProgressListener(tab.linkedBrowser, navigationListener, Ci.nsIWebProgress.NOTIFY_LOCATION),
helper.addEventListener(this._linkedBrowser, 'DOMModalDialogClosed', event => this._updateModalDialogs()),
helper.addEventListener(this._linkedBrowser, 'WillChangeBrowserRemoteness', event => this._willChangeBrowserRemoteness()),
@ -461,12 +501,26 @@ class PageTarget {
this.updateReducedMotionOverride(browsingContext);
this.updateForcedColorsOverride(browsingContext);
this.updateForceOffline(browsingContext);
this.updateCacheDisabled(browsingContext);
}
updateForceOffline(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).forceOffline = this._browserContext.forceOffline;
}
setCacheDisabled(disabled) {
this.disableCache = disabled;
this.updateCacheDisabled();
}
updateCacheDisabled(browsingContext = this._linkedBrowser.browsingContext) {
const enableFlags = Ci.nsIRequest.LOAD_NORMAL;
const disableFlags = Ci.nsIRequest.LOAD_BYPASS_CACHE |
Ci.nsIRequest.INHIBIT_CACHING;
browsingContext.defaultLoadFlags = (this._browserContext.disableCache || this.disableCache) ? disableFlags : enableFlags;
}
updateTouchOverride(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).touchEventsOverride = this._browserContext.touchOverride ? 'enabled' : 'none';
}
@ -484,7 +538,7 @@ class PageTarget {
}
_updateModalDialogs() {
const prompts = new Set(this._linkedBrowser.tabModalPromptBox ? this._linkedBrowser.tabModalPromptBox.listPrompts() : []);
const prompts = new Set(this._linkedBrowser.tabDialogBox.getContentDialogManager().dialogs.map(dialog => dialog.frameContentWindow.Dialog));
for (const dialog of this._dialogs.values()) {
if (!prompts.has(dialog.prompt())) {
this._dialogs.delete(dialog.id());
@ -581,7 +635,8 @@ class PageTarget {
}
updateForcedColorsOverride(browsingContext = undefined) {
(browsingContext || this._linkedBrowser.browsingContext).forcedColorsOverride = (this.forcedColors !== 'no-override' ? this.forcedColors : this._browserContext.forcedColors) || 'no-override';
const isActive = this.forcedColors === 'active' || this._browserContext.forcedColors === 'active';
(browsingContext || this._linkedBrowser.browsingContext).forcedColorsOverride = isActive ? 'active' : 'none';
}
async setInterceptFileChooserDialog(enabled) {
@ -804,8 +859,8 @@ function fromProtocolReducedMotion(reducedMotion) {
function fromProtocolForcedColors(forcedColors) {
if (forcedColors === 'active' || forcedColors === 'none')
return forcedColors;
if (forcedColors === null)
return undefined;
if (!forcedColors)
return 'none';
throw new Error('Unknown forced colors: ' + forcedColors);
}
@ -837,8 +892,9 @@ class BrowserContext {
this.defaultPlatform = null;
this.touchOverride = false;
this.forceOffline = false;
this.disableCache = false;
this.colorScheme = 'none';
this.forcedColors = 'no-override';
this.forcedColors = 'none';
this.reducedMotion = 'none';
this.videoRecordingOptions = undefined;
this.crossProcessCookie = {
@ -890,12 +946,14 @@ class BrowserContext {
}
this._registry._browserContextIdToBrowserContext.delete(this.browserContextId);
this._registry._userContextIdToBrowserContext.delete(this.userContextId);
this._registry._updateProxiesWithSameAuthCacheAndDifferentCredentials();
}
setProxy(proxy) {
// Clear AuthCache.
Services.obs.notifyObservers(null, "net:clear-active-logins");
this._proxy = proxy;
this._registry._updateProxiesWithSameAuthCacheAndDifferentCredentials();
}
setIgnoreHTTPSErrors(ignoreHTTPSErrors) {
@ -938,6 +996,12 @@ class BrowserContext {
page.updateForceOffline();
}
setCacheDisabled(disabled) {
this.disableCache = disabled;
for (const page of this.pages)
page.updateCacheDisabled();
}
async setDefaultViewport(viewport) {
this.defaultViewportSize = viewport ? viewport.viewportSize : undefined;
this.deviceScaleFactor = viewport ? viewport.deviceScaleFactor : undefined;

View file

@ -105,7 +105,10 @@ class Juggler {
};
// Force create hidden window here, otherwise its creation later closes the web socket!
Services.appShell.hiddenDOMWindow;
// Since https://phabricator.services.mozilla.com/D219834, hiddenDOMWindow is only available on MacOS.
if (Services.appShell.hasHiddenWindow) {
Services.appShell.hiddenDOMWindow;
}
let pipeStopped = false;
let browserHandler;

View file

@ -46,8 +46,6 @@ class FrameTree {
Ci.nsISupportsWeakReference,
]);
this._addedScrollbarsStylesheetSymbol = Symbol('_addedScrollbarsStylesheetSymbol');
this._wdm = Cc["@mozilla.org/dom/workers/workerdebuggermanager;1"].createInstance(Ci.nsIWorkerDebuggerManager);
this._wdmListener = {
QueryInterface: ChromeUtils.generateQI([Ci.nsIWorkerDebuggerManagerListener]),
@ -130,24 +128,12 @@ class FrameTree {
}
_onDOMWindowCreated(window) {
if (!window[this._addedScrollbarsStylesheetSymbol] && this.scrollbarsHidden) {
const styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].getService(Components.interfaces.nsIStyleSheetService);
const ioService = Cc["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
const uri = ioService.newURI('chrome://juggler/content/content/hidden-scrollbars.css', null, null);
const sheet = styleSheetService.preloadSheet(uri, styleSheetService.AGENT_SHEET);
window.windowUtils.addSheet(sheet, styleSheetService.AGENT_SHEET);
window[this._addedScrollbarsStylesheetSymbol] = true;
}
const frame = this.frameForDocShell(window.docShell);
if (!frame)
return;
frame._onGlobalObjectCleared();
}
setScrollbarsHidden(hidden) {
this.scrollbarsHidden = hidden;
}
setJavaScriptDisabled(javaScriptDisabled) {
this._javaScriptDisabled = javaScriptDisabled;
for (const frame of this.frames())

View file

@ -8,6 +8,8 @@ const helper = new Helper();
let sameProcessInstanceNumber = 0;
const topBrowingContextToAgents = new Map();
class JugglerFrameChild extends JSWindowActorChild {
constructor() {
super();
@ -16,46 +18,66 @@ class JugglerFrameChild extends JSWindowActorChild {
}
handleEvent(aEvent) {
if (this._agents && aEvent.type === 'DOMWillOpenModalDialog') {
this._agents.channel.pause();
const agents = this._agents();
if (!agents)
return;
if (aEvent.type === 'DOMWillOpenModalDialog') {
agents.channel.pause();
return;
}
if (this._agents && aEvent.type === 'DOMModalDialogClosed') {
this._agents.channel.resumeSoon();
if (aEvent.type === 'DOMModalDialogClosed') {
agents.channel.resumeSoon();
return;
}
if (this._agents && aEvent.target === this.document)
this._agents.pageAgent.onWindowEvent(aEvent);
if (this._agents && aEvent.target === this.document)
this._agents.frameTree.onWindowEvent(aEvent);
if (aEvent.target === this.document) {
agents.pageAgent.onWindowEvent(aEvent);
agents.frameTree.onWindowEvent(aEvent);
}
}
_agents() {
return topBrowingContextToAgents.get(this.browsingContext.top);
}
actorCreated() {
this.actorName = `content::${this.browsingContext.browserId}/${this.browsingContext.id}/${++sameProcessInstanceNumber}`;
this._eventListeners.push(helper.addEventListener(this.contentWindow, 'load', event => {
this._agents?.pageAgent.onWindowEvent(event);
this._agents()?.pageAgent.onWindowEvent(event);
}));
if (this.document.documentURI.startsWith('moz-extension://'))
return;
this._agents = initialize(this.browsingContext, this.docShell, this);
}
_dispose() {
helper.removeListeners(this._eventListeners);
// We do not cleanup since agents are shared for all frames in the process.
// Child frame events will be forwarded to related top-level agents.
if (this.browsingContext.parent)
return;
// TODO: restore the cleanup.
// Reset transport so that all messages will be pending and will not throw any errors.
// this._channel.resetTransport();
// this._agents.pageAgent.dispose();
// this._agents.frameTree.dispose();
// this._agents = undefined;
let agents = topBrowingContextToAgents.get(this.browsingContext);
if (!agents) {
agents = initialize(this.browsingContext, this.docShell);
topBrowingContextToAgents.set(this.browsingContext, agents);
}
agents.channel.bindToActor(this);
agents.actor = this;
}
didDestroy() {
this._dispose();
helper.removeListeners(this._eventListeners);
if (this.browsingContext.parent)
return;
const agents = topBrowingContextToAgents.get(this.browsingContext);
// The agents are already re-bound to a new actor.
if (agents?.actor !== this)
return;
topBrowingContextToAgents.delete(this.browsingContext);
agents.channel.resetTransport();
agents.pageAgent.dispose();
agents.frameTree.dispose();
}
receiveMessage() { }

View file

@ -120,7 +120,8 @@ class PageAgent {
// After the dragStart event is dispatched and handled by Web,
// it might or might not create a new drag session, depending on its preventing default.
setTimeout(() => {
this._browserPage.emit('pageInputEvent', { type: 'juggler-drag-finalized', dragSessionStarted: !!dragService.getCurrentSession() });
const session = this._getCurrentDragSession();
this._browserPage.emit('pageInputEvent', { type: 'juggler-drag-finalized', dragSessionStarted: !!session });
}, 0);
}
}),
@ -152,7 +153,6 @@ class PageAgent {
getFullAXTree: this._getFullAXTree.bind(this),
insertText: this._insertText.bind(this),
scrollIntoViewIfNeeded: this._scrollIntoViewIfNeeded.bind(this),
setCacheDisabled: this._setCacheDisabled.bind(this),
setFileInputFiles: this._setFileInputFiles.bind(this),
evaluate: this._runtime.evaluate.bind(this._runtime),
callFunction: this._runtime.callFunction.bind(this._runtime),
@ -162,15 +162,6 @@ class PageAgent {
];
}
_setCacheDisabled({cacheDisabled}) {
const enable = Ci.nsIRequest.LOAD_NORMAL;
const disable = Ci.nsIRequest.LOAD_BYPASS_CACHE |
Ci.nsIRequest.INHIBIT_CACHING;
const docShell = this._frameTree.mainFrame().docShell();
docShell.defaultLoadFlags = cacheDisabled ? disable : enable;
}
_emitAllEvents(frame) {
this._browserPage.emit('pageEventFired', {
frameId: frame.id(),
@ -380,7 +371,12 @@ class PageAgent {
const unsafeObject = frame.unsafeObject(objectId);
if (!unsafeObject)
throw new Error('Object is not input!');
const nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
let nsFiles;
if (unsafeObject.webkitdirectory) {
nsFiles = await new Directory(files[0]).getFiles(true);
} else {
nsFiles = await Promise.all(files.map(filePath => File.createFromFileName(filePath)));
}
unsafeObject.mozSetFileArray(nsFiles);
const events = [
new (frame.domWindow().Event)('input', { bubbles: true, cancelable: true, composed: true }),
@ -519,75 +515,26 @@ class PageAgent {
false /* aIgnoreRootScrollFrame */,
true /* aFlushLayout */);
const {defaultPrevented: startPrevented} = await this._dispatchTouchEvent({
await this._dispatchTouchEvent({
type: 'touchstart',
modifiers,
touchPoints: [{x, y}]
});
const {defaultPrevented: endPrevented} = await this._dispatchTouchEvent({
await this._dispatchTouchEvent({
type: 'touchend',
modifiers,
touchPoints: [{x, y}]
});
if (startPrevented || endPrevented)
return;
}
_getCurrentDragSession() {
const frame = this._frameTree.mainFrame();
const winUtils = frame.domWindow().windowUtils;
winUtils.jugglerSendMouseEvent(
'mousemove',
x,
y,
0 /*button*/,
0 /*clickCount*/,
modifiers,
false /*aIgnoreRootScrollFrame*/,
0.0 /*pressure*/,
5 /*inputSource*/,
true /*isDOMEventSynthesized*/,
false /*isWidgetEventSynthesized*/,
0 /*buttons*/,
winUtils.DEFAULT_MOUSE_POINTER_ID /* pointerIdentifier */,
true /*disablePointerEvent*/
);
winUtils.jugglerSendMouseEvent(
'mousedown',
x,
y,
0 /*button*/,
1 /*clickCount*/,
modifiers,
false /*aIgnoreRootScrollFrame*/,
0.0 /*pressure*/,
5 /*inputSource*/,
true /*isDOMEventSynthesized*/,
false /*isWidgetEventSynthesized*/,
1 /*buttons*/,
winUtils.DEFAULT_MOUSE_POINTER_ID /*pointerIdentifier*/,
true /*disablePointerEvent*/,
);
winUtils.jugglerSendMouseEvent(
'mouseup',
x,
y,
0 /*button*/,
1 /*clickCount*/,
modifiers,
false /*aIgnoreRootScrollFrame*/,
0.0 /*pressure*/,
5 /*inputSource*/,
true /*isDOMEventSynthesized*/,
false /*isWidgetEventSynthesized*/,
0 /*buttons*/,
winUtils.DEFAULT_MOUSE_POINTER_ID /*pointerIdentifier*/,
true /*disablePointerEvent*/,
);
const domWindow = frame?.domWindow();
return domWindow ? dragService.getCurrentSession(domWindow) : undefined;
}
async _dispatchDragEvent({type, x, y, modifiers}) {
const session = dragService.getCurrentSession();
const session = this._getCurrentDragSession();
const dropEffect = session.dataTransfer.dropEffect;
if ((type === 'drop' && dropEffect !== 'none') || type === 'dragover') {
@ -611,9 +558,8 @@ class PageAgent {
return;
}
if (type === 'dragend') {
const session = dragService.getCurrentSession();
if (session)
dragService.endDragSession(true);
const session = this._getCurrentDragSession();
session?.endDragSession(true);
return;
}
}

View file

@ -7,24 +7,10 @@ const {FrameTree} = ChromeUtils.import('chrome://juggler/content/content/FrameTr
const {SimpleChannel} = ChromeUtils.import('chrome://juggler/content/SimpleChannel.js');
const {PageAgent} = ChromeUtils.import('chrome://juggler/content/content/PageAgent.js');
const browsingContextToAgents = new Map();
const helper = new Helper();
function initialize(browsingContext, docShell, actor) {
if (browsingContext.parent) {
// For child frames, return agents from the main frame.
return browsingContextToAgents.get(browsingContext.top);
}
let data = browsingContextToAgents.get(browsingContext);
if (data) {
// Rebind from one main frame actor to another one.
data.channel.bindToActor(actor);
return data;
}
data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false };
browsingContextToAgents.set(browsingContext, data);
function initialize(browsingContext, docShell) {
const data = { channel: undefined, pageAgent: undefined, frameTree: undefined, failedToOverrideTimezone: false };
const applySetting = {
geolocation: (geolocation) => {
@ -59,10 +45,6 @@ function initialize(browsingContext, docShell, actor) {
docShell.languageOverride = locale;
},
scrollbarsHidden: (hidden) => {
data.frameTree.setScrollbarsHidden(hidden);
},
javaScriptDisabled: (javaScriptDisabled) => {
data.frameTree.setJavaScriptDisabled(javaScriptDisabled);
},
@ -84,7 +66,6 @@ function initialize(browsingContext, docShell, actor) {
data.frameTree.addBinding(worldName, name, script);
data.frameTree.setInitScripts([...contextCrossProcessCookie.initScripts, ...pageCrossProcessCookie.initScripts]);
data.channel = new SimpleChannel('', 'process-' + Services.appinfo.processID);
data.channel.bindToActor(actor);
data.pageAgent = new PageAgent(data.channel, data.frameTree);
docShell.fileInputInterceptionEnabled = !!pageCrossProcessCookie.interceptFileChooserDialog;

View file

@ -186,6 +186,10 @@ class BrowserHandler {
this._targetRegistry.browserContextForId(browserContextId).requestInterceptionEnabled = enabled;
}
['Browser.setCacheDisabled']({browserContextId, cacheDisabled}) {
this._targetRegistry.browserContextForId(browserContextId).setCacheDisabled(cacheDisabled);
}
['Browser.setIgnoreHTTPSErrors']({browserContextId, ignoreHTTPSErrors}) {
this._targetRegistry.browserContextForId(browserContextId).setIgnoreHTTPSErrors(nullToUndefined(ignoreHTTPSErrors));
}
@ -251,10 +255,6 @@ class BrowserHandler {
await this._targetRegistry.browserContextForId(browserContextId).setDefaultViewport(nullToUndefined(viewport));
}
async ['Browser.setScrollbarsHidden']({browserContextId, hidden}) {
await this._targetRegistry.browserContextForId(browserContextId).applySetting('scrollbarsHidden', nullToUndefined(hidden));
}
async ['Browser.setInitScripts']({browserContextId, scripts}) {
await this._targetRegistry.browserContextForId(browserContextId).setInitScripts(scripts);
}

View file

@ -256,6 +256,13 @@ class PageHandler {
return await this._contentPage.send('disposeObject', options);
}
async ['Heap.collectGarbage']() {
Services.obs.notifyObservers(null, "child-gc-request");
Cu.forceGC();
Services.obs.notifyObservers(null, "child-cc-request");
Cu.forceCC();
}
async ['Network.getResponseBody']({requestId}) {
return this._pageNetwork.getResponseBody(requestId);
}
@ -302,8 +309,8 @@ class PageHandler {
await this._pageTarget.activateAndRun(() => {});
}
async ['Page.setCacheDisabled'](options) {
return await this._contentPage.send('setCacheDisabled', options);
async ['Page.setCacheDisabled']({cacheDisabled}) {
return await this._pageTarget.setCacheDisabled(cacheDisabled);
}
async ['Page.addBinding']({ worldName, name, script }) {

View file

@ -322,6 +322,12 @@ const Browser = {
enabled: t.Boolean,
},
},
'setCacheDisabled': {
params: {
browserContextId: t.Optional(t.String),
cacheDisabled: t.Boolean,
},
},
'setGeolocationOverride': {
params: {
browserContextId: t.Optional(t.String),
@ -388,12 +394,6 @@ const Browser = {
viewport: t.Nullable(pageTypes.Viewport),
}
},
'setScrollbarsHidden': {
params: {
browserContextId: t.Optional(t.String),
hidden: t.Boolean,
}
},
'setInitScripts': {
params: {
browserContextId: t.Optional(t.String),
@ -481,6 +481,17 @@ const Browser = {
},
};
const Heap = {
targets: ['page'],
types: {},
events: {},
methods: {
'collectGarbage': {
params: {},
},
},
};
const Network = {
targets: ['page'],
types: networkTypes,
@ -996,7 +1007,7 @@ const Accessibility = {
}
this.protocol = {
domains: {Browser, Page, Runtime, Network, Accessibility},
domains: {Browser, Heap, Page, Runtime, Network, Accessibility},
};
this.checkScheme = checkScheme;
this.EXPORTED_SYMBOLS = ['protocol', 'checkScheme'];

View file

@ -129,7 +129,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
capability.height = 960;
capability.maxFPS = ScreencastEncoder::fps;
capability.videoType = webrtc::VideoType::kI420;
int error = mCaptureModule->StartCapture(capability);
int error = mCaptureModule->StartCaptureCounted(capability);
if (error) {
fprintf(stderr, "StartCapture error %d\n", error);
return false;
@ -152,7 +152,7 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
mCaptureModule->DeRegisterCaptureDataCallback(this);
else
mCaptureModule->DeRegisterRawFrameCallback(this);
mCaptureModule->StopCapture();
mCaptureModule->StopCaptureCounted();
if (mEncoder) {
mEncoder->finish([this, protect = RefPtr{this}] {
NS_DispatchToMainThread(NS_NewRunnableFunction(

File diff suppressed because it is too large Load diff

View file

@ -47,6 +47,9 @@ pref("permissions.isolateBy.userContext", true);
// |Page.setFileInputFiles| protocol method.
pref("dom.file.createInChild", true);
// Allow uploading directorys in content process.
pref("dom.filesystem.pathcheck.disabled", true);
// Do not warn when closing all open tabs
pref("browser.tabs.warnOnClose", false);
@ -97,6 +100,11 @@ pref("extensions.formautofill.addresses.supported", "off");
// firefox behavior with other browser defaults.
pref("security.enterprise_roots.enabled", true);
// There's a security features warning that might be shown on certain Linux distributions & configurations:
// https://support.mozilla.org/en-US/kb/install-firefox-linux#w_security-features-warning
// This notification should never be shown in automation scenarios.
pref("security.sandbox.warn_unprivileged_namespaces", false);
// Avoid stalling on shutdown, after "xpcom-will-shutdown" phase.
// This at least happens when shutting down soon after launching.
// See AppShutdown.cpp for more details on shutdown phases.

View file

@ -1,3 +1,3 @@
REMOTE_URL="https://github.com/WebKit/WebKit.git"
BASE_BRANCH="main"
BASE_REVISION="e225c278f4c06f451ea92cc68b12986dd2a99979"
BASE_REVISION="76c95d6131edd36775a5eac01e297926fc974be8"

View file

@ -33,6 +33,7 @@
#import <WebKit/WKUserContentControllerPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebpagePreferencesPrivate.h>
#import <WebKit/WKWebsiteDataStorePrivate.h>
#import <WebKit/WebNSURLExtras.h>
#import <WebKit/WebKit.h>
@ -97,7 +98,7 @@ const NSActivityOptions ActivityOptions =
for (NSString *argument in subArray) {
if (![argument hasPrefix:@"--"])
_initialURL = argument;
_initialURL = [argument copy];
if ([argument hasPrefix:@"--user-data-dir="]) {
NSRange range = NSMakeRange(16, [argument length] - 16);
_userDataDir = [[argument substringWithRange:range] copy];
@ -230,7 +231,7 @@ const NSActivityOptions ActivityOptions =
configuration = [[WKWebViewConfiguration alloc] init];
configuration.websiteDataStore = [self persistentDataStore];
configuration._controlledByAutomation = true;
configuration.preferences._fullScreenEnabled = YES;
configuration.preferences.elementFullscreenEnabled = YES;
configuration.preferences._developerExtrasEnabled = YES;
configuration.preferences._mediaDevicesEnabled = YES;
configuration.preferences._mockCaptureDevicesEnabled = YES;
@ -240,6 +241,8 @@ const NSActivityOptions ActivityOptions =
configuration.preferences._hiddenPageDOMTimerThrottlingAutoIncreases = NO;
configuration.preferences._pageVisibilityBasedProcessSuppressionEnabled = NO;
configuration.preferences._domTimersThrottlingEnabled = NO;
// Do not auto play audio and video with sound.
configuration.defaultWebpagePreferences._autoplayPolicy = _WKWebsiteAutoplayPolicyAllowWithoutSound;
_WKProcessPoolConfiguration *processConfiguration = [[[_WKProcessPoolConfiguration alloc] init] autorelease];
processConfiguration.forceOverlayScrollbars = YES;
configuration.processPool = [[[WKProcessPool alloc] _initWithConfiguration:processConfiguration] autorelease];

File diff suppressed because it is too large Load diff

View file

@ -39,5 +39,4 @@ fi
# create a TMP directory to copy all necessary files
cd ./x64/Release
zip $ZIP_PATH ./PrintDeps.exe
7z a "$ZIP_PATH" ./PrintDeps.exe

View file

@ -14,8 +14,6 @@ A few examples of problems this can catch include:
The following examples rely on the [`com.deque.html.axe-core/playwright`](https://mvnrepository.com/artifact/com.deque.html.axe-core/playwright) Maven package which adds support for running the [axe accessibility testing engine](https://www.deque.com/axe/) as part of your Playwright tests.
<!-- TOC -->
## Disclaimer
Automated accessibility tests can detect some common accessibility problems such as missing or invalid properties. But many accessibility problems can only be discovered through manual testing. We recommend using a combination of automated testing, manual accessibility assessments, and inclusive user testing.
@ -72,22 +70,24 @@ For example, you can use [`AxeBuilder.include()`](https://github.com/dequelabs/a
`AxeBuilder.analyze()` will scan the page *in its current state* when you call it. To scan parts of a page that are revealed based on UI interactions, use [Locators](./locators.md) to interact with the page before invoking `analyze()`:
```java
@Test
void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception {
page.navigate("https://your-site.com/");
public class HomepageTests {
@Test
void navigationMenuFlyoutShouldNotHaveAutomaticallyDetectableAccessibilityViolations() throws Exception {
page.navigate("https://your-site.com/");
page.locator("button[aria-label=\"Navigation Menu\"]").click();
page.locator("button[aria-label=\"Navigation Menu\"]").click();
// It is important to waitFor() the page to be in the desired
// state *before* running analyze(). Otherwise, axe might not
// find all the elements your test expects it to scan.
page.locator("#navigation-menu-flyout").waitFor();
// It is important to waitFor() the page to be in the desired
// state *before* running analyze(). Otherwise, axe might not
// find all the elements your test expects it to scan.
page.locator("#navigation-menu-flyout").waitFor();
AxeResults accessibilityScanResults = new AxeBuilder(page)
.include(Arrays.asList("#navigation-menu-flyout"))
.analyze();
AxeResults accessibilityScanResults = new AxeBuilder(page)
.include(Arrays.asList("#navigation-menu-flyout"))
.analyze();
assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations());
assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations());
}
}
```
@ -135,7 +135,7 @@ If the element in question is used repeatedly in many pages, consider [using a t
### Disabling individual scan rules
If your application contains many different pre-existing violations of a specific rule, you can use [`AxeBuilder.disableRules()`](https://github.com/dequelabs/axe-core-maven-html/blob/develop/playwright/README.md#axebuilderdisablerulesliststring-rules) to temporarily disable individual rules until you're able to fix the issues.
If your application contains many different preexisting violations of a specific rule, you can use [`AxeBuilder.disableRules()`](https://github.com/dequelabs/axe-core-maven-html/blob/develop/playwright/README.md#axebuilderdisablerulesliststring-rules) to temporarily disable individual rules until you're able to fix the issues.
You can find the rule IDs to pass to `disableRules()` in the `id` property of the violations you want to suppress. A [complete list of axe's rules](https://github.com/dequelabs/axe-core/blob/master/doc/rule-descriptions.md) can be found in `axe-core`'s documentation.
@ -160,38 +160,40 @@ This approach avoids the downsides of using `AxeBuilder.exclude()` at the cost o
Here is an example of using fingerprints based on only rule IDs and "target" selectors pointing to each violation:
```java
@Test
shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception {
page.navigate("https://your-site.com/");
public class HomepageTests {
@Test
shouldOnlyHaveAccessibilityViolationsMatchingKnownFingerprints() throws Exception {
page.navigate("https://your-site.com/");
AxeResults accessibilityScanResults = new AxeBuilder(page).analyze();
AxeResults accessibilityScanResults = new AxeBuilder(page).analyze();
List<ViolationFingerprint> violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults);
List<ViolationFingerprint> violationFingerprints = fingerprintsFromScanResults(accessibilityScanResults);
assertEquals(Arrays.asList(
new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"),
new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"),
new ViolationFingerprint("label", "[input]")
), violationFingerprints);
}
assertEquals(Arrays.asList(
new ViolationFingerprint("aria-roles", "[span[role=\"invalid\"]]"),
new ViolationFingerprint("color-contrast", "[li:nth-child(2) > span]"),
new ViolationFingerprint("label", "[input]")
), violationFingerprints);
}
// You can make your "fingerprint" as specific as you like. This one considers a violation to be
// "the same" if it corresponds the same Axe rule on the same element.
//
// Using a record type makes it easy to compare fingerprints with assertEquals
public record ViolationFingerprint(String ruleId, String target) { }
// You can make your "fingerprint" as specific as you like. This one considers a violation to be
// "the same" if it corresponds the same Axe rule on the same element.
//
// Using a record type makes it easy to compare fingerprints with assertEquals
public record ViolationFingerprint(String ruleId, String target) { }
public List<ViolationFingerprint> fingerprintsFromScanResults(AxeResults results) {
return results.getViolations().stream()
// Each violation refers to one rule and multiple "nodes" which violate it
.flatMap(violation -> violation.getNodes().stream()
.map(node -> new ViolationFingerprint(
violation.getId(),
// Each node contains a "target", which is a CSS selector that uniquely identifies it
// If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors
node.getTarget().toString()
)))
.collect(Collectors.toList());
public List<ViolationFingerprint> fingerprintsFromScanResults(AxeResults results) {
return results.getViolations().stream()
// Each violation refers to one rule and multiple "nodes" which violate it
.flatMap(violation -> violation.getNodes().stream()
.map(node -> new ViolationFingerprint(
violation.getId(),
// Each node contains a "target", which is a CSS selector that uniquely identifies it
// If the page involves iframes or shadow DOMs, it may be a chain of CSS selectors
node.getTarget().toString()
)))
.collect(Collectors.toList());
}
}
```
@ -210,11 +212,11 @@ This example fixture creates an `AxeBuilder` object which is pre-configured with
```java
class AxeTestFixtures extends TestFixtures {
AxeBuilder makeAxeBuilder() {
return new AxeBuilder(page)
.withTags(['wcag2a', 'wcag2aa', 'wcag21a', 'wcag21aa'])
.exclude('#commonly-reused-element-with-known-issue');
}
AxeBuilder makeAxeBuilder() {
return new AxeBuilder(page)
.withTags(new String[]{"wcag2a", "wcag2aa", "wcag21a", "wcag21aa"})
.exclude("#commonly-reused-element-with-known-issue");
}
}
```
@ -231,7 +233,7 @@ public class HomepageTests extends AxeTestFixtures {
AxeResults accessibilityScanResults = makeAxeBuilder()
// Automatically uses the shared AxeBuilder configuration,
// but supports additional test-specific configuration too
.include('#specific-element-under-test')
.include("#specific-element-under-test")
.analyze();
assertEquals(Collections.emptyList(), accessibilityScanResults.getViolations());

View file

@ -147,7 +147,7 @@ If the element in question is used repeatedly in many pages, consider [using a t
### Disabling individual scan rules
If your application contains many different pre-existing violations of a specific rule, you can use [`AxeBuilder.disableRules()`](https://github.com/dequelabs/axe-core-npm/blob/develop/packages/playwright/README.md#axebuilderdisablerulesrules-stringarray) to temporarily disable individual rules until you're able to fix the issues.
If your application contains many different preexisting violations of a specific rule, you can use [`AxeBuilder.disableRules()`](https://github.com/dequelabs/axe-core-npm/blob/develop/packages/playwright/README.md#axebuilderdisablerulesrules-stringarray) to temporarily disable individual rules until you're able to fix the issues.
You can find the rule IDs to pass to `disableRules()` in the `id` property of the violations you want to suppress. A [complete list of axe's rules](https://github.com/dequelabs/axe-core/blob/master/doc/rule-descriptions.md) can be found in `axe-core`'s documentation.
@ -167,7 +167,7 @@ test('should not have any accessibility violations outside of rules with known i
### Using snapshots to allow specific known issues
If you would like to allow for a more granular set of known issues, you can use [Snapshots](./test-snapshots.md) to verify that a set of pre-existing violations has not changed. This approach avoids the downsides of using `AxeBuilder.exclude()` at the cost of slightly more complexity and fragility.
If you would like to allow for a more granular set of known issues, you can use [Snapshots](./test-snapshots.md) to verify that a set of preexisting violations has not changed. This approach avoids the downsides of using `AxeBuilder.exclude()` at the cost of slightly more complexity and fragility.
Do not use a snapshot of the entire `accessibilityScanResults.violations` array. It contains implementation details of the elements in question, such as a snippet of their rendered HTML; if you include these in your snapshots, it will make your tests prone to breaking every time one of the components in question changes for an unrelated reason:

View file

@ -93,11 +93,20 @@ Element is considered stable when it has maintained the same bounding box for at
## Enabled
Element is considered enabled unless it is a `<button>`, `<select>`, `<input>` or `<textarea>` with a `disabled` property.
Element is considered enabled when it is **not disabled**.
Element is **disabled** when:
- it is a `<button>`, `<select>`, `<input>`, `<textarea>`, `<option>` or `<optgroup>` with a `[disabled]` attribute;
- it is a `<button>`, `<select>`, `<input>`, `<textarea>`, `<option>` or `<optgroup>` that is a part of a `<fieldset>` with a `[disabled]` attribute;
- it is a descendant of an element with `[aria-disabled=true]` attribute.
## Editable
Element is considered editable when it is [enabled] and does not have `readonly` property set.
Element is considered editable when it is [enabled] and is **not readonly**.
Element is **readonly** when:
- it is a `<select>`, `<input>` or `<textarea>` with a `[readonly]` attribute;
- it has an `[aria-readonly=true]` attribute and an aria role that [supports it](https://w3c.github.io/aria/#aria-readonly).
## Receives Events

View file

@ -18,8 +18,6 @@ All of that could be achieved via [APIRequestContext] methods.
The following examples rely on the [`Microsoft.Playwright.MSTest`](./test-runners.md) package which creates a Playwright and Page instance for each test.
<!-- TOC -->
## Writing API Test
[APIRequestContext] can send all kinds of HTTP(S) requests over network.

View file

@ -16,8 +16,6 @@ A few examples where it may come in handy:
All of that could be achieved via [APIRequestContext] methods.
<!-- TOC -->
## Writing API Test
[APIRequestContext] can send all kinds of HTTP(S) requests over network.
@ -196,6 +194,7 @@ public class TestGitHubAPI {
These tests assume that repository exists. You probably want to create a new one before running tests and delete it afterwards. Use `@BeforeAll` and `@AfterAll` hooks for that.
```java
public class TestGitHubAPI {
// ...
void createTestRepository() {
@ -225,6 +224,7 @@ These tests assume that repository exists. You probably want to create a new one
disposeAPIRequestContext();
closePlaywright();
}
}
```
### Complete test example
@ -383,18 +383,20 @@ The following test creates a new issue via API and then navigates to the list of
project to check that it appears at the top of the list. The check is performed using [LocatorAssertions].
```java
@Test
void lastCreatedIssueShouldBeFirstInTheList() {
Map<String, String> data = new HashMap<>();
data.put("title", "[Feature] request 1");
data.put("body", "Feature description");
APIResponse newIssue = request.post("/repos/" + USER + "/" + REPO + "/issues",
RequestOptions.create().setData(data));
assertTrue(newIssue.ok());
public class TestGitHubAPI {
@Test
void lastCreatedIssueShouldBeFirstInTheList() {
Map<String, String> data = new HashMap<>();
data.put("title", "[Feature] request 1");
data.put("body", "Feature description");
APIResponse newIssue = request.post("/repos/" + USER + "/" + REPO + "/issues",
RequestOptions.create().setData(data));
assertTrue(newIssue.ok());
page.navigate("https://github.com/" + USER + "/" + REPO + "/issues");
Locator firstIssue = page.locator("a[data-hovercard-type='issue']").first();
assertThat(firstIssue).hasText("[Feature] request 1");
page.navigate("https://github.com/" + USER + "/" + REPO + "/issues");
Locator firstIssue = page.locator("a[data-hovercard-type='issue']").first();
assertThat(firstIssue).hasText("[Feature] request 1");
}
}
```
@ -404,18 +406,20 @@ The following test creates a new issue via user interface in the browser and the
it was created:
```java
@Test
void lastCreatedIssueShouldBeOnTheServer() {
page.navigate("https://github.com/" + USER + "/" + REPO + "/issues");
page.locator("text=New Issue").click();
page.locator("[aria-label='Title']").fill("Bug report 1");
page.locator("[aria-label='Comment body']").fill("Bug description");
page.locator("text=Submit new issue").click();
String issueId = page.url().substring(page.url().lastIndexOf('/'));
public class TestGitHubAPI {
@Test
void lastCreatedIssueShouldBeOnTheServer() {
page.navigate("https://github.com/" + USER + "/" + REPO + "/issues");
page.locator("text=New Issue").click();
page.locator("[aria-label='Title']").fill("Bug report 1");
page.locator("[aria-label='Comment body']").fill("Bug description");
page.locator("text=Submit new issue").click();
String issueId = page.url().substring(page.url().lastIndexOf('/'));
APIResponse newIssue = request.get("https://github.com/" + USER + "/" + REPO + "/issues/" + issueId);
assertThat(newIssue).isOK();
assertTrue(newIssue.text().contains("Bug report 1"));
APIResponse newIssue = request.get("https://github.com/" + USER + "/" + REPO + "/issues/" + issueId);
assertThat(newIssue).isOK();
assertTrue(newIssue.text().contains("Bug report 1"));
}
}
```

View file

@ -16,8 +16,6 @@ A few examples where it may come in handy:
All of that could be achieved via [APIRequestContext] methods.
<!-- TOC3 -->
## Writing API Test
[APIRequestContext] can send all kinds of HTTP(S) requests over network.

View file

@ -18,8 +18,6 @@ All of that could be achieved via [APIRequestContext] methods.
The following examples rely on the [`pytest-playwright`](./test-runners.md) package which add Playwright fixtures to the Pytest test-runner.
<!-- TOC -->
## Writing API Test
[APIRequestContext] can send all kinds of HTTP(S) requests over network.

View file

@ -136,7 +136,7 @@ Launches Chrome browser on the device, and returns its persistent context.
### option: AndroidDevice.launchBrowser.pkg
* since: v1.9
- `command` <[string]>
- `pkg` <[string]>
Optional package name to launch instead of default Chrome for Android.
@ -177,7 +177,9 @@ Launches a process in the shell on the device and returns a socket to communicat
### param: AndroidDevice.open.command
* since: v1.9
- `command` <[string]> Shell command to execute.
- `command` <[string]>
Shell command to execute.
## async method: AndroidDevice.pinchClose
* since: v1.9
@ -445,7 +447,7 @@ Either a predicate that receives an event or an options object. Optional.
* since: v1.9
- returns: <[AndroidWebView]>
This method waits until [AndroidWebView] matching the [`option: selector`] is opened and returns it. If there is already an open [AndroidWebView] matching the [`option: selector`], returns immediately.
This method waits until [AndroidWebView] matching the [`param: selector`] is opened and returns it. If there is already an open [AndroidWebView] matching the [`param: selector`], returns immediately.
### param: AndroidDevice.webView.selector
* since: v1.9

View file

@ -12,12 +12,22 @@ see [APIRequestContext].
Creates new instances of [APIRequestContext].
### option: APIRequest.newContext.clientCertificates = %%-context-option-clientCertificates-%%
* since: 1.46
### option: APIRequest.newContext.useragent = %%-context-option-useragent-%%
* since: v1.16
### option: APIRequest.newContext.extraHTTPHeaders = %%-context-option-extrahttpheaders-%%
* since: v1.16
### option: APIRequest.newContext.failOnStatusCode
* since: v1.51
- `failOnStatusCode` <[boolean]>
Whether to throw on response codes other than 2xx and 3xx. By default response object is returned
for all status codes.
### option: APIRequest.newContext.httpCredentials = %%-context-option-httpcredentials-%%
* since: v1.16
@ -61,6 +71,7 @@ Methods like [`method: APIRequestContext.get`] take the base URL into considerat
- `localStorage` <[Array]<[Object]>>
- `name` <[string]>
- `value` <[string]>
- `indexedDB` ?<[Array]<[unknown]>> indexedDB to set for context
Populates context with given storage state. This option can be used to initialize context with logged-in information
obtained via [`method: BrowserContext.storageState`] or [`method: APIRequestContext.storageState`]. Either a path to the

View file

@ -138,22 +138,31 @@ context cookies from the response. The method will automatically follow redirect
### param: APIRequestContext.delete.url = %%-fetch-param-url-%%
* since: v1.16
### param: APIRequestContext.delete.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.delete.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.delete.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.delete.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.delete.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.delete.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.delete.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.delete.headers = %%-js-python-csharp-fetch-option-headers-%%
* since: v1.16
### option: APIRequestContext.delete.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.17
### option: APIRequestContext.delete.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.delete.form = %%-js-fetch-option-form-%%
* since: v1.17
### option: APIRequestContext.delete.form = %%-python-fetch-option-form-%%
* since: v1.17
### option: APIRequestContext.delete.form = %%-csharp-fetch-option-form-%%
@ -180,6 +189,9 @@ context cookies from the response. The method will automatically follow redirect
### option: APIRequestContext.delete.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.delete.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.dispose
* since: v1.16
@ -235,7 +247,7 @@ var data = new Dictionary<string, object>() {
await Request.FetchAsync("https://example.com/api/createBook", new() { Method = "post", DataObject = data });
```
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding. Use [FormData] to construct request body and pass it to the request as [`option: multipart`] parameter:
The common way to send file(s) in the body of a request is to upload them as form fields with `multipart/form-data` encoding, by specifiying the `multipart` parameter:
```js
const form = new FormData();
@ -288,21 +300,28 @@ multipart.Set("fileField", file);
await Request.FetchAsync("https://example.com/api/uploadScript", new() { Method = "post", Multipart = multipart });
```
### param: APIRequestContext.fetch.urlOrRequest
* since: v1.16
- `urlOrRequest` <[string]|[Request]>
Target URL or Request to get all parameters from.
### param: APIRequestContext.fetch.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.fetch.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.fetch.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.fetch.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.fetch.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.fetch.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.fetch.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.fetch.method
* since: v1.16
* langs: js, python, csharp
@ -317,7 +336,10 @@ If set changes the fetch method (e.g. [PUT](https://developer.mozilla.org/en-US/
### option: APIRequestContext.fetch.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.16
### option: APIRequestContext.fetch.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.fetch.form = %%-js-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.fetch.form = %%-python-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.fetch.form = %%-csharp-fetch-option-form-%%
@ -344,6 +366,9 @@ If set changes the fetch method (e.g. [PUT](https://developer.mozilla.org/en-US/
### option: APIRequestContext.fetch.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.fetch.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.get
* since: v1.16
- returns: <[APIResponse]>
@ -357,12 +382,24 @@ context cookies from the response. The method will automatically follow redirect
Request parameters can be configured with `params` option, they will be serialized into the URL search parameters:
```js
// Passing params as object
await request.get('https://example.com/api/getText', {
params: {
'isbn': '1234',
'page': 23,
}
});
// Passing params as URLSearchParams
const searchParams = new URLSearchParams();
searchParams.set('isbn', '1234');
searchParams.append('page', 23);
searchParams.append('page', 24);
await request.get('https://example.com/api/getText', { params: searchParams });
// Passing params as string
const queryString = 'isbn=1234&page=23&page=24';
await request.get('https://example.com/api/getText', { params: queryString });
```
```java
@ -391,22 +428,31 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query
### param: APIRequestContext.get.url = %%-fetch-param-url-%%
* since: v1.16
### param: APIRequestContext.get.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.get.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.get.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.get.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.get.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.get.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.get.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.get.headers = %%-js-python-csharp-fetch-option-headers-%%
* since: v1.16
### option: APIRequestContext.get.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.26
### option: APIRequestContext.get.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.get.form = %%-js-fetch-option-form-%%
* since: v1.26
### option: APIRequestContext.get.form = %%-python-fetch-option-form-%%
* since: v1.26
### option: APIRequestContext.get.form = %%-csharp-fetch-option-form-%%
@ -433,6 +479,9 @@ await request.GetAsync("https://example.com/api/getText", new() { Params = query
### option: APIRequestContext.get.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.get.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.head
* since: v1.16
- returns: <[APIResponse]>
@ -444,22 +493,31 @@ context cookies from the response. The method will automatically follow redirect
### param: APIRequestContext.head.url = %%-fetch-param-url-%%
* since: v1.16
### param: APIRequestContext.head.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.head.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.head.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.head.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.head.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.head.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.head.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.head.headers = %%-js-python-csharp-fetch-option-headers-%%
* since: v1.16
### option: APIRequestContext.head.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.26
### option: APIRequestContext.head.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.head.form = %%-python-fetch-option-form-%%
* since: v1.26
### option: APIRequestContext.head.form = %%-js-fetch-option-form-%%
* since: v1.26
### option: APIRequestContext.head.form = %%-csharp-fetch-option-form-%%
@ -486,6 +544,9 @@ context cookies from the response. The method will automatically follow redirect
### option: APIRequestContext.head.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.head.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.patch
* since: v1.16
- returns: <[APIResponse]>
@ -497,22 +558,31 @@ context cookies from the response. The method will automatically follow redirect
### param: APIRequestContext.patch.url = %%-fetch-param-url-%%
* since: v1.16
### param: APIRequestContext.patch.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.patch.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.patch.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.patch.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.patch.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.patch.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.patch.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.patch.headers = %%-js-python-csharp-fetch-option-headers-%%
* since: v1.16
### option: APIRequestContext.patch.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.16
### option: APIRequestContext.patch.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.patch.form = %%-js-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.patch.form = %%-python-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.patch.form = %%-csharp-fetch-option-form-%%
@ -539,6 +609,9 @@ context cookies from the response. The method will automatically follow redirect
### option: APIRequestContext.patch.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.patch.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.post
* since: v1.16
- returns: <[APIResponse]>
@ -671,22 +744,31 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar
### param: APIRequestContext.post.url = %%-fetch-param-url-%%
* since: v1.16
### param: APIRequestContext.post.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.post.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.post.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.post.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.post.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.post.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.post.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.post.headers = %%-js-python-csharp-fetch-option-headers-%%
* since: v1.16
### option: APIRequestContext.post.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.16
### option: APIRequestContext.post.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.post.form = %%-js-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.post.form = %%-python-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.post.form = %%-csharp-fetch-option-form-%%
@ -713,6 +795,9 @@ await request.PostAsync("https://example.com/api/uploadScript", new() { Multipar
### option: APIRequestContext.post.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.post.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.put
* since: v1.16
- returns: <[APIResponse]>
@ -724,22 +809,31 @@ context cookies from the response. The method will automatically follow redirect
### param: APIRequestContext.put.url = %%-fetch-param-url-%%
* since: v1.16
### param: APIRequestContext.put.params = %%-java-csharp-fetch-params-%%
### option: APIRequestContext.put.params = %%-js-fetch-option-params-%%
* since: v1.16
### param: APIRequestContext.put.params = %%-java-fetch-params-%%
* since: v1.18
### option: APIRequestContext.put.params = %%-js-python-fetch-option-params-%%
### option: APIRequestContext.put.params = %%-python-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.put.params = %%-csharp-fetch-option-params-%%
* since: v1.16
### option: APIRequestContext.put.paramsString = %%-csharp-fetch-option-paramsString-%%
* since: v1.47
### option: APIRequestContext.put.headers = %%-js-python-csharp-fetch-option-headers-%%
* since: v1.16
### option: APIRequestContext.put.data = %%-js-python-csharp-fetch-option-data-%%
* since: v1.16
### option: APIRequestContext.put.form = %%-js-python-fetch-option-form-%%
### option: APIRequestContext.put.form = %%-python-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.put.form = %%-js-fetch-option-form-%%
* since: v1.16
### option: APIRequestContext.put.form = %%-csharp-fetch-option-form-%%
@ -766,6 +860,9 @@ context cookies from the response. The method will automatically follow redirect
### option: APIRequestContext.put.maxRedirects = %%-js-python-csharp-fetch-option-maxredirects-%%
* since: v1.26
### option: APIRequestContext.put.maxRetries = %%-js-python-csharp-fetch-option-maxretries-%%
* since: v1.46
## async method: APIRequestContext.storageState
* since: v1.16
- returns: <[Object]>
@ -783,6 +880,7 @@ context cookies from the response. The method will automatically follow redirect
- `localStorage` <[Array]<[Object]>>
- `name` <[string]>
- `value` <[string]>
- `indexedDB` <[Array]<[unknown]>>
Returns storage state for this request context, contains current cookies and local storage snapshot if it was passed to the constructor.
@ -793,3 +891,9 @@ Returns storage state for this request context, contains current cookies and loc
### option: APIRequestContext.storageState.path = %%-storagestate-option-path-%%
* since: v1.16
### option: APIRequestContext.storageState.indexedDB
* since: v1.51
- `indexedDB` ?<boolean>
Set to `true` to include IndexedDB in the storage state snapshot.

View file

@ -60,7 +60,7 @@ An object with all the response HTTP headers associated with this response.
- `name` <[string]> Name of the header.
- `value` <[string]> Value of the header.
An array with all the request HTTP headers associated with this response. Header names are not lower-cased.
An array with all the response HTTP headers associated with this response. Header names are not lower-cased.
Headers with multiple entries, such as `Set-Cookie`, appear in the array multiple times.
## async method: APIResponse.json

View file

@ -14,15 +14,15 @@ test('navigates to login', async ({ page }) => {
```
```java
...
// ...
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
public class TestPage {
...
// ...
@Test
void navigatesToLoginPage() {
...
APIResponse response = page.request().get('https://playwright.dev');
// ...
APIResponse response = page.request().get("https://playwright.dev");
assertThat(response).isOK();
}
}

View file

@ -1,6 +1,5 @@
# class: Browser
* since: v1.8
* extends: [EventEmitter]
A Browser is created via [`method: BrowserType.launch`]. An example of using a [Browser] to create a [Page]:
@ -19,15 +18,15 @@ const { firefox } = require('playwright'); // Or 'chromium' or 'webkit'.
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType firefox = playwright.firefox()
Browser browser = firefox.launch();
Page page = browser.newPage();
page.navigate('https://example.com');
browser.close();
}
}
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType firefox = playwright.firefox();
Browser browser = firefox.launch();
Page page = browser.newPage();
page.navigate("https://example.com");
browser.close();
}
}
}
```
@ -97,7 +96,7 @@ In case this browser is connected to, clears all created contexts belonging to t
browser server.
:::note
This is similar to force quitting the browser. Therefore, you should call [`method: BrowserContext.close`] on any [BrowserContext]'s you explicitly created earlier with [`method: Browser.newContext`] **before** calling [`method: Browser.close`].
This is similar to force-quitting the browser. To close pages gracefully and ensure you receive page close events, call [`method: BrowserContext.close`] on any [BrowserContext] instances you explicitly created earlier using [`method: Browser.newContext`] **before** calling [`method: Browser.close`].
:::
The [Browser] object itself is considered to be disposed and cannot be used anymore.
@ -203,7 +202,7 @@ Browser browser = playwright.firefox().launch(); // Or 'chromium' or 'webkit'.
BrowserContext context = browser.newContext();
// Create a new page in a pristine context.
Page page = context.newPage();
page.navigate('https://example.com');
page.navigate("https://example.com");
// Graceful close up everything
context.close();
@ -256,6 +255,9 @@ await browser.CloseAsync();
### option: Browser.newContext.proxy = %%-context-option-proxy-%%
* since: v1.8
### option: Browser.newContext.clientCertificates = %%-context-option-clientCertificates-%%
* since: 1.46
### option: Browser.newContext.storageState = %%-js-python-context-option-storage-state-%%
* since: v1.8
@ -281,6 +283,9 @@ testing frameworks should explicitly create [`method: Browser.newContext`] follo
### option: Browser.newPage.proxy = %%-context-option-proxy-%%
* since: v1.8
### option: Browser.newPage.clientCertificates = %%-context-option-clientCertificates-%%
* since: 1.46
### option: Browser.newPage.storageState = %%-js-python-context-option-storage-state-%%
* since: v1.8
@ -290,6 +295,20 @@ testing frameworks should explicitly create [`method: Browser.newContext`] follo
### option: Browser.newPage.storageStatePath = %%-csharp-java-context-option-storage-state-path-%%
* since: v1.9
## async method: Browser.removeAllListeners
* since: v1.47
* langs: js
Removes all the listeners of the given type (or all registered listeners if no type given).
Allows to wait for async listeners to complete or to ignore subsequent errors from these listeners.
### param: Browser.removeAllListeners.type
* since: v1.47
- `type` ?<[string]>
### option: Browser.removeAllListeners.behavior = %%-remove-all-listeners-options-behavior-%%
* since: v1.47
## async method: Browser.startTracing
* since: v1.11
* langs: java, js, python
@ -312,7 +331,7 @@ await browser.stopTracing();
```java
browser.startTracing(page, new Browser.StartTracingOptions()
.setPath(Paths.get("trace.json")));
page.goto('https://www.google.com');
page.navigate("https://www.google.com");
browser.stopTracing();
```

View file

@ -1,13 +1,12 @@
# class: BrowserContext
* since: v1.8
* extends: [EventEmitter]
BrowserContexts provide a way to operate multiple independent browser sessions.
If a page opens another page, e.g. with a `window.open` call, the popup will belong to the parent page's browser
context.
Playwright allows creating "incognito" browser contexts with [`method: Browser.newContext`] method. "Incognito" browser
Playwright allows creating isolated non-persistent browser contexts with [`method: Browser.newContext`] method. Non-persistent browser
contexts don't write any browsing data to disk.
```js
@ -357,18 +356,14 @@ await context.AddCookiesAsync(new[] { cookie1, cookie2 });
- `cookies` <[Array]<[Object]>>
- `name` <[string]>
- `value` <[string]>
- `url` ?<[string]> either url or domain / path are required. Optional.
- `domain` ?<[string]> either url or domain / path are required Optional.
- `path` ?<[string]> either url or domain / path are required Optional.
- `url` ?<[string]> Either url or domain / path are required. Optional.
- `domain` ?<[string]> For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com". Either url or domain / path are required. Optional.
- `path` ?<[string]> Either url or domain / path are required Optional.
- `expires` ?<[float]> Unix time in seconds. Optional.
- `httpOnly` ?<[boolean]> Optional.
- `secure` ?<[boolean]> Optional.
- `sameSite` ?<[SameSiteAttribute]<"Strict"|"Lax"|"None">> Optional.
Adds cookies to the browser context.
For the cookie to apply to all subdomains as well, prefix domain with a dot, like this: ".example.com".
## async method: BrowserContext.addInitScript
* since: v1.8
@ -660,7 +655,7 @@ import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType webkit = playwright.webkit()
BrowserType webkit = playwright.webkit();
Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
BrowserContext context = browser.newContext();
context.exposeBinding("pageURL", (source, args) -> source.page().url());
@ -748,83 +743,6 @@ await page.SetContentAsync("<script>\n" +
await page.GetByRole(AriaRole.Button).ClickAsync();
```
An example of passing an element handle:
```js
await context.exposeBinding('clicked', async (source, element) => {
console.log(await element.textContent());
}, { handle: true });
await page.setContent(`
<script>
document.addEventListener('click', event => window.clicked(event.target));
</script>
<div>Click me</div>
<div>Or click me</div>
`);
```
```java
context.exposeBinding("clicked", (source, args) -> {
ElementHandle element = (ElementHandle) args[0];
System.out.println(element.textContent());
return null;
}, new BrowserContext.ExposeBindingOptions().setHandle(true));
page.setContent("" +
"<script>\n" +
" document.addEventListener('click', event => window.clicked(event.target));\n" +
"</script>\n" +
"<div>Click me</div>\n" +
"<div>Or click me</div>\n");
```
```python async
async def print(source, element):
print(await element.text_content())
await context.expose_binding("clicked", print, handle=true)
await page.set_content("""
<script>
document.addEventListener('click', event => window.clicked(event.target));
</script>
<div>Click me</div>
<div>Or click me</div>
""")
```
```python sync
def print(source, element):
print(element.text_content())
context.expose_binding("clicked", print, handle=true)
page.set_content("""
<script>
document.addEventListener('click', event => window.clicked(event.target));
</script>
<div>Click me</div>
<div>Or click me</div>
""")
```
```csharp
var result = new TaskCompletionSource<string>();
var page = await Context.NewPageAsync();
await Context.ExposeBindingAsync("clicked", async (BindingSource _, IJSHandle t) =>
{
return result.TrySetResult(await t.AsElement().TextContentAsync());
});
await page.SetContentAsync("<script>\n" +
" document.addEventListener('click', event => window.clicked(event.target));\n" +
"</script>\n" +
"<div>Click me</div>\n" +
"<div>Or click me</div>\n");
await page.ClickAsync("div");
// Note: it makes sense to await the result here, because otherwise, the context
// gets closed and the binding function will throw an exception.
Assert.AreEqual("Click me", await result.Task);
```
### param: BrowserContext.exposeBinding.name
* since: v1.8
- `name` <[string]>
@ -839,6 +757,7 @@ Callback function that will be called in the Playwright's context.
### option: BrowserContext.exposeBinding.handle
* since: v1.8
* deprecated: This option will be removed in the future.
- `handle` <[boolean]>
Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
@ -894,8 +813,9 @@ import java.util.Base64;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType webkit = playwright.webkit()
BrowserType webkit = playwright.webkit();
Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
BrowserContext context = browser.newContext();
context.exposeFunction("sha256", args -> {
String text = (String) args[0];
MessageDigest crypto;
@ -1043,9 +963,14 @@ specified.
* since: v1.8
- `permissions` <[Array]<[string]>>
A permission or an array of permissions to grant. Permissions can be one of the following values:
A list of permissions to grant.
:::danger
Supported permissions differ between browsers, and even between different versions of the same browser. Any permission may stop working after an update.
:::
Here are some permissions that may be supported by some browsers:
* `'accelerometer'`
* `'accessibility-events'`
* `'ambient-light-sensor'`
* `'background-sync'`
* `'camera'`
@ -1096,6 +1021,20 @@ Creates a new page in the browser context.
Returns all open pages in the context.
## async method: BrowserContext.removeAllListeners
* since: v1.47
* langs: js
Removes all the listeners of the given type (or all registered listeners if no type given).
Allows to wait for async listeners to complete or to ignore subsequent errors from these listeners.
### param: BrowserContext.removeAllListeners.type
* since: v1.47
- `type` ?<[string]>
### option: BrowserContext.removeAllListeners.behavior = %%-remove-all-listeners-options-behavior-%%
* since: v1.47
## property: BrowserContext.request
* since: v1.16
* langs:
@ -1265,7 +1204,7 @@ Enabling routing disables http cache.
- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]>
A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
When a [`option: baseURL`] via the context options was provided and the passed URL is a path,
When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path,
it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
### param: BrowserContext.route.handler
@ -1333,6 +1272,99 @@ When set to `minimal`, only record information necessary for routing from HAR. T
Optional setting to control resource content management. If `attach` is specified, resources are persisted as separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file.
## async method: BrowserContext.routeWebSocket
* since: v1.48
This method allows to modify websocket connections that are made by any page in the browser context.
Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this method before creating any pages.
**Usage**
Below is an example of a simple handler that blocks some websocket messages.
See [WebSocketRoute] for more details and examples.
```js
await context.routeWebSocket('/ws', async ws => {
ws.routeSend(message => {
if (message === 'to-be-blocked')
return;
ws.send(message);
});
await ws.connect();
});
```
```java
context.routeWebSocket("/ws", ws -> {
ws.routeSend(message -> {
if ("to-be-blocked".equals(message))
return;
ws.send(message);
});
ws.connect();
});
```
```python async
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "to-be-blocked":
return
ws.send(message)
async def handler(ws: WebSocketRoute):
ws.route_send(lambda message: message_handler(ws, message))
await ws.connect()
await context.route_web_socket("/ws", handler)
```
```python sync
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "to-be-blocked":
return
ws.send(message)
def handler(ws: WebSocketRoute):
ws.route_send(lambda message: message_handler(ws, message))
ws.connect()
context.route_web_socket("/ws", handler)
```
```csharp
await context.RouteWebSocketAsync("/ws", async ws => {
ws.RouteSend(message => {
if (message == "to-be-blocked")
return;
ws.Send(message);
});
await ws.ConnectAsync();
});
```
### param: BrowserContext.routeWebSocket.url
* since: v1.48
- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]>
Only WebSockets with the url matching this pattern will be routed. A string pattern can be relative to the [`option: Browser.newContext.baseURL`] context option.
### param: BrowserContext.routeWebSocket.handler
* since: v1.48
* langs: js, python
- `handler` <[function]\([WebSocketRoute]\): [Promise<any>|any]>
Handler function to route the WebSocket.
### param: BrowserContext.routeWebSocket.handler
* since: v1.48
* langs: csharp, java
- `handler` <[function]\([WebSocketRoute]\)>
Handler function to route the WebSocket.
## method: BrowserContext.serviceWorkers
* since: v1.11
* langs: js, python
@ -1380,7 +1412,7 @@ This setting will change the default maximum time for all the methods accepting
* since: v1.8
- `timeout` <[float]>
Maximum time in milliseconds
Maximum time in milliseconds. Pass `0` to disable timeout.
## async method: BrowserContext.setExtraHTTPHeaders
* since: v1.8
@ -1479,8 +1511,9 @@ Whether to emulate network being offline for the browser context.
- `localStorage` <[Array]<[Object]>>
- `name` <[string]>
- `value` <[string]>
- `indexedDB` <[Array]<[unknown]>>
Returns storage state for this browser context, contains current cookies and local storage snapshot.
Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB snapshot.
## async method: BrowserContext.storageState
* since: v1.8
@ -1490,6 +1523,17 @@ Returns storage state for this browser context, contains current cookies and loc
### option: BrowserContext.storageState.path = %%-storagestate-option-path-%%
* since: v1.8
### option: BrowserContext.storageState.indexedDB
* since: v1.51
- `indexedDB` ?<boolean>
Set to `true` to include IndexedDB in the storage state snapshot.
If your application uses IndexedDB to store authentication tokens, like Firebase Authentication, enable this.
:::note
IndexedDBs with typed arrays are currently not supported.
:::
## property: BrowserContext.tracing
* since: v1.12
- type: <[Tracing]>

View file

@ -89,13 +89,17 @@ class BrowserTypeExamples
* since: v1.8
- returns: <[Browser]>
This method attaches Playwright to an existing browser instance. When connecting to another browser launched via `BrowserType.launchServer` in Node.js, the major and minor version needs to match the client version (1.2.3 → is compatible with 1.2.x).
This method attaches Playwright to an existing browser instance created via `BrowserType.launchServer` in Node.js.
:::note
The major and minor version of the Playwright instance that connects needs to match the version of Playwright that launches the browser (1.2.3 → is compatible with 1.2.x).
:::
### param: BrowserType.connect.wsEndpoint
* since: v1.10
- `wsEndpoint` <[string]>
A browser websocket endpoint to connect to.
A Playwright browser websocket endpoint to connect to. You obtain this endpoint via `BrowserServer.wsEndpoint`.
### option: BrowserType.connect.headers
* since: v1.11
@ -152,6 +156,10 @@ The default browser context is accessible via [`method: Browser.contexts`].
Connecting over the Chrome DevTools Protocol is only supported for Chromium-based browsers.
:::
:::note
This connection is significantly lower fidelity than the Playwright protocol connection via [`method: BrowserType.connect`]. If you are experiencing issues or attempting to use advanced functionality, you probably want to use [`method: BrowserType.connect`].
:::
**Usage**
```js
@ -343,6 +351,9 @@ use a temporary directory instead.
### option: BrowserType.launchPersistentContext.firefoxUserPrefs2 = %%-csharp-java-browser-option-firefoxuserprefs-%%
* since: v1.40
### option: BrowserType.launchPersistentContext.clientCertificates = %%-context-option-clientCertificates-%%
* since: 1.46
## async method: BrowserType.launchServer
* since: v1.8
* langs: js

View file

@ -1,6 +1,5 @@
# class: CDPSession
* since: v1.8
* extends: [EventEmitter]
The `CDPSession` instances are used to talk raw Chrome Devtools Protocol:
* protocol methods can be called with `session.send` method.

View file

@ -41,7 +41,7 @@ await page.Clock.FastForwardAsync("30:00");
### param: Clock.fastForward.ticks
* since: v1.45
- `ticks` <[int]|[string]>
- `ticks` <[long]|[string]>
Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.
@ -64,8 +64,23 @@ Install fake implementations for the following time-related functions:
Fake timers are used to manually control the flow of time in tests. They allow you to advance time, fire timers, and control the behavior of time-dependent functions. See [`method: Clock.runFor`] and [`method: Clock.fastForward`] for more information.
### option: Clock.install.time
* langs: js, java
* since: v1.45
- `time` <[int]|[string]|[Date]>
- `time` <[long]|[string]|[Date]>
Time to initialize with, current system time by default.
### option: Clock.install.time
* langs: python
* since: v1.45
- `time` <[float]|[string]|[Date]>
Time to initialize with, current system time by default.
### option: Clock.install.time
* langs: csharp
* since: v1.45
- `time` <[string]|[Date]>
Time to initialize with, current system time by default.
@ -103,7 +118,7 @@ await page.Clock.RunForAsync("30:00");
### param: Clock.runFor.ticks
* since: v1.45
- `ticks` <[int]|[string]>
- `ticks` <[long]|[string]>
Time may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds.
@ -136,7 +151,8 @@ page.clock.pause_at("2020-02-02")
```
```java
page.clock().pauseAt(Instant.parse("2020-02-02"));
SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd");
page.clock().pauseAt(format.parse("2020-02-02"));
page.clock().pauseAt("2020-02-02");
```
@ -145,10 +161,61 @@ await page.Clock.PauseAtAsync(DateTime.Parse("2020-02-02"));
await page.Clock.PauseAtAsync("2020-02-02");
```
### param: Clock.pauseAt.time
* since: v1.45
- `time` <[int]|[string]|[Date]>
For best results, install the clock before navigating the page and set it to a time slightly before the intended test time. This ensures that all timers run normally during page loading, preventing the page from getting stuck. Once the page has fully loaded, you can safely use [`method: Clock.pauseAt`] to pause the clock.
```js
// Initialize clock with some time before the test time and let the page load
// naturally. `Date.now` will progress as the timers fire.
await page.clock.install({ time: new Date('2024-12-10T08:00:00') });
await page.goto('http://localhost:3333');
await page.clock.pauseAt(new Date('2024-12-10T10:00:00'));
```
```python async
# Initialize clock with some time before the test time and let the page load
# naturally. `Date.now` will progress as the timers fire.
await page.clock.install(time=datetime.datetime(2024, 12, 10, 8, 0, 0))
await page.goto("http://localhost:3333")
await page.clock.pause_at(datetime.datetime(2024, 12, 10, 10, 0, 0))
```
```python sync
# Initialize clock with some time before the test time and let the page load
# naturally. `Date.now` will progress as the timers fire.
page.clock.install(time=datetime.datetime(2024, 12, 10, 8, 0, 0))
page.goto("http://localhost:3333")
page.clock.pause_at(datetime.datetime(2024, 12, 10, 10, 0, 0))
```
```java
// Initialize clock with some time before the test time and let the page load
// naturally. `Date.now` will progress as the timers fire.
SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-12-10T08:00:00")));
page.navigate("http://localhost:3333");
page.clock().pauseAt(format.parse("2024-12-10T10:00:00"));
```
### param: Clock.pauseAt.time
* langs: js, java
* since: v1.45
- `time` <[long]|[string]|[Date]>
Time to pause at.
### param: Clock.pauseAt.time
* langs: python
* since: v1.45
- `time` <[float]|[string]|[Date]>
Time to pause at.
### param: Clock.pauseAt.time
* langs: csharp
* since: v1.45
- `time` <[Date]|[string]>
Time to pause at.
## async method: Clock.resume
* since: v1.45
@ -161,6 +228,8 @@ Resumes timers. Once this method is called, time resumes flowing, timers are fir
Makes `Date.now` and `new Date()` return fixed fake time at all times,
keeps all the timers running.
Use this method for simple scenarios where you only need to test with a predefined time. For more advanced scenarios, use [`method: Clock.install`] instead. Read docs on [clock emulation](../clock.md) to learn more.
**Usage**
```js
@ -182,8 +251,8 @@ page.clock.set_fixed_time("2020-02-02")
```
```java
page.clock().setFixedTime(Instant.now());
page.clock().setFixedTime(Instant.parse("2020-02-02"));
page.clock().setFixedTime(new Date());
page.clock().setFixedTime(new SimpleDateFormat("yyy-MM-dd").parse("2020-02-02"));
page.clock().setFixedTime("2020-02-02");
```
@ -194,15 +263,30 @@ await page.Clock.SetFixedTimeAsync("2020-02-02");
```
### param: Clock.setFixedTime.time
* langs: js, java
* since: v1.45
- `time` <[int]|[string]|[Date]>
- `time` <[long]|[string]|[Date]>
Time to be set in milliseconds.
### param: Clock.setFixedTime.time
* langs: python
* since: v1.45
- `time` <[float]|[string]|[Date]>
Time to be set.
### param: Clock.setFixedTime.time
* langs: csharp
* since: v1.45
- `time` <[string]|[Date]>
Time to be set.
## async method: Clock.setSystemTime
* since: v1.45
Sets current system time but does not trigger any timers.
Sets system time, but does not trigger any timers. Use this to test how the web page reacts to a time shift, for example switching from summer to winter time, or changing time zones.
**Usage**
@ -225,8 +309,8 @@ page.clock.set_system_time("2020-02-02")
```
```java
page.clock().setSystemTime(Instant.now());
page.clock().setSystemTime(Instant.parse("2020-02-02"));
page.clock().setSystemTime(new Date());
page.clock().setSystemTime(new SimpleDateFormat("yyy-MM-dd").parse("2020-02-02"));
page.clock().setSystemTime("2020-02-02");
```
@ -237,5 +321,22 @@ await page.Clock.SetSystemTimeAsync("2020-02-02");
```
### param: Clock.setSystemTime.time
* langs: js, java
* since: v1.45
- `time` <[int]|[string]|[Date]>
- `time` <[long]|[string]|[Date]>
Time to be set in milliseconds.
### param: Clock.setSystemTime.time
* langs: python
* since: v1.45
- `time` <[float]|[string]|[Date]>
Time to be set.
### param: Clock.setSystemTime.time
* langs: csharp
* since: v1.45
- `time` <[string]|[Date]>
Time to be set.

View file

@ -44,8 +44,8 @@ ConsoleMessage msg = page.waitForConsoleMessage(() -> {
});
// Deconstruct console.log arguments
msg.args().get(0).jsonValue() // hello
msg.args().get(1).jsonValue() // 42
msg.args().get(0).jsonValue(); // hello
msg.args().get(1).jsonValue(); // 42
```
```python async

View file

@ -164,7 +164,6 @@ This method checks the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked. If not, this method throws.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -178,7 +177,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: ElementHandle.check.force = %%-input-force-%%
* since: v1.8
### option: ElementHandle.check.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.check.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.check.timeout = %%-input-timeout-%%
@ -251,8 +250,6 @@ This method double clicks the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that
if the first click of the `dblclick()` triggers a navigation event, this method will throw.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -278,7 +275,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: ElementHandle.dblclick.force = %%-input-force-%%
* since: v1.8
### option: ElementHandle.dblclick.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.dblclick.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.dblclick.timeout = %%-input-timeout-%%
@ -537,7 +534,7 @@ Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
### option: ElementHandle.fill.force = %%-input-force-%%
* since: v1.13
### option: ElementHandle.fill.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.fill.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.fill.timeout = %%-input-timeout-%%
@ -573,7 +570,6 @@ This method hovers over the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to hover over the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -598,7 +594,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: ElementHandle.hover.trial = %%-input-trial-%%
* since: v1.11
### option: ElementHandle.hover.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.hover.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.28
## async method: ElementHandle.innerHTML
@ -870,7 +866,7 @@ await handle.SelectOptionAsync(new[] {
### option: ElementHandle.selectOption.force = %%-input-force-%%
* since: v1.13
### option: ElementHandle.selectOption.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.selectOption.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.selectOption.timeout = %%-input-timeout-%%
@ -920,7 +916,6 @@ This method checks or unchecks an element by performing the following steps:
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked or unchecked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -932,7 +927,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: ElementHandle.setChecked.force = %%-input-force-%%
* since: v1.15
### option: ElementHandle.setChecked.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.setChecked.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.15
### option: ElementHandle.setChecked.position = %%-input-position-%%
@ -961,7 +956,7 @@ This method expects [ElementHandle] to point to an
### param: ElementHandle.setInputFiles.files = %%-input-files-%%
* since: v1.8
### option: ElementHandle.setInputFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.setInputFiles.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.setInputFiles.timeout = %%-input-timeout-%%
@ -978,7 +973,6 @@ This method taps the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.touchscreen`] to tap the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -998,7 +992,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: ElementHandle.tap.force = %%-input-force-%%
* since: v1.8
### option: ElementHandle.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.tap.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.tap.timeout = %%-input-timeout-%%
@ -1039,7 +1033,7 @@ A text to type into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: ElementHandle.type.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.type.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.type.timeout = %%-input-timeout-%%
@ -1058,7 +1052,6 @@ This method checks the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now unchecked. If not, this method throws.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -1072,7 +1065,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: ElementHandle.uncheck.force = %%-input-force-%%
* since: v1.8
### option: ElementHandle.uncheck.noWaitAfter = %%-input-no-wait-after-%%
### option: ElementHandle.uncheck.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: ElementHandle.uncheck.timeout = %%-input-timeout-%%

View file

@ -65,7 +65,7 @@ they are resolved relative to the current working directory. For empty array, cl
### param: FileChooser.setFiles.files = %%-input-files-%%
* since: v1.8
### option: FileChooser.setFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: FileChooser.setFiles.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: FileChooser.setFiles.timeout = %%-input-timeout-%%

View file

@ -6,7 +6,7 @@ The [FormData] is used create form data that is sent via [APIRequestContext].
```java
import com.microsoft.playwright.options.FormData;
...
// ...
FormData form = FormData.create()
.set("firstName", "John")
.set("lastName", "Doe")
@ -28,7 +28,7 @@ the new value onto the end of the existing set of values.
```java
import com.microsoft.playwright.options.FormData;
...
// ...
FormData form = FormData.create()
// Only name and value are set.
.append("firstName", "John")
@ -100,7 +100,7 @@ Sets a field on the form. File values can be passed either as `Path` or as `File
```java
import com.microsoft.playwright.options.FormData;
...
// ...
FormData form = FormData.create()
// Only name and value are set.
.set("firstName", "John")

View file

@ -154,7 +154,7 @@ Raw JavaScript content to be injected into frame.
* since: v1.8
- `type` <[string]>
Script type. Use 'module' in order to load a Javascript ES6 module. See
Script type. Use 'module' in order to load a JavaScript ES6 module. See
[script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details.
## async method: Frame.addStyleTag
@ -198,7 +198,6 @@ This method checks an element matching [`param: selector`] by performing the fol
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -210,7 +209,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.check.force = %%-input-force-%%
* since: v1.8
### option: Frame.check.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.check.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.check.position = %%-input-position-%%
@ -281,7 +280,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.click.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Frame.click.trial = %%-input-trial-%%
### option: Frame.click.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
## async method: Frame.content
@ -303,7 +302,6 @@ This method double clicks an element matching [`param: selector`] by performing
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that
if the first click of the `dblclick()` triggers a navigation event, this method will throw.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -328,7 +326,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.dblclick.modifiers = %%-input-modifiers-%%
* since: v1.8
### option: Frame.dblclick.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.dblclick.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.dblclick.position = %%-input-position-%%
@ -343,7 +341,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.dblclick.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Frame.dblclick.trial = %%-input-trial-%%
### option: Frame.dblclick.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
## async method: Frame.dispatchEvent
@ -463,7 +461,7 @@ Optional event-specific initialization properties.
### option: Frame.dragAndDrop.force = %%-input-force-%%
* since: v1.13
### option: Frame.dragAndDrop.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.dragAndDrop.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.13
### option: Frame.dragAndDrop.strict = %%-input-strict-%%
@ -856,7 +854,7 @@ Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
### option: Frame.fill.force = %%-input-force-%%
* since: v1.13
### option: Frame.fill.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.fill.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.fill.strict = %%-input-strict-%%
@ -1130,7 +1128,6 @@ This method hovers over an element matching [`param: selector`] by performing th
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to hover over the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
[TimeoutError]. Passing zero timeout disables this.
@ -1156,10 +1153,10 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.hover.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Frame.hover.trial = %%-input-trial-%%
### option: Frame.hover.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
### option: Frame.hover.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.hover.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.28
## async method: Frame.innerHTML
@ -1307,7 +1304,7 @@ Returns whether the element is [enabled](../actionability.md#enabled).
* discouraged: Use locator-based [`method: Locator.isHidden`] instead. Read more about [locators](../locators.md).
- returns: <[boolean]>
Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible). [`option: selector`] that does not match any elements is considered hidden.
Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible). [`param: selector`] that does not match any elements is considered hidden.
### param: Frame.isHidden.selector = %%-input-selector-%%
* since: v1.8
@ -1325,7 +1322,7 @@ Returns whether the element is hidden, the opposite of [visible](../actionabilit
* discouraged: Use locator-based [`method: Locator.isVisible`] instead. Read more about [locators](../locators.md).
- returns: <[boolean]>
Returns whether the element is [visible](../actionability.md#visible). [`option: selector`] that does not match any elements is considered not visible.
Returns whether the element is [visible](../actionability.md#visible). [`param: selector`] that does not match any elements is considered not visible.
### param: Frame.isVisible.selector = %%-input-selector-%%
* since: v1.8
@ -1546,7 +1543,7 @@ await frame.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" })
### option: Frame.selectOption.force = %%-input-force-%%
* since: v1.13
### option: Frame.selectOption.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.selectOption.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.selectOption.strict = %%-input-strict-%%
@ -1583,7 +1580,6 @@ This method checks or unchecks an element matching [`param: selector`] by perfor
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked or unchecked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -1598,7 +1594,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.setChecked.force = %%-input-force-%%
* since: v1.15
### option: Frame.setChecked.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.setChecked.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.15
### option: Frame.setChecked.position = %%-input-position-%%
@ -1652,7 +1648,7 @@ This method expects [`param: selector`] to point to an
### param: Frame.setInputFiles.files = %%-input-files-%%
* since: v1.8
### option: Frame.setInputFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.setInputFiles.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.setInputFiles.strict = %%-input-strict-%%
@ -1675,7 +1671,6 @@ This method taps an element matching [`param: selector`] by performing the follo
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.touchscreen`] to tap the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
[TimeoutError]. Passing zero timeout disables this.
@ -1693,7 +1688,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.tap.modifiers = %%-input-modifiers-%%
* since: v1.8
### option: Frame.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.tap.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.tap.position = %%-input-position-%%
@ -1708,7 +1703,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.tap.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Frame.tap.trial = %%-input-trial-%%
### option: Frame.tap.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
## async method: Frame.textContent
@ -1762,7 +1757,7 @@ A text to type into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: Frame.type.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.type.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.type.strict = %%-input-strict-%%
@ -1787,7 +1782,6 @@ This method checks an element matching [`param: selector`] by performing the fol
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now unchecked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -1799,7 +1793,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Frame.uncheck.force = %%-input-force-%%
* since: v1.8
### option: Frame.uncheck.noWaitAfter = %%-input-no-wait-after-%%
### option: Frame.uncheck.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Frame.uncheck.position = %%-input-position-%%

View file

@ -1,30 +1,30 @@
# class: FrameLocator
* since: v1.17
FrameLocator represents a view to the `iframe` on the page. It captures the logic sufficient to retrieve the `iframe` and locate elements in that iframe. FrameLocator can be created with either [`method: Page.frameLocator`] or [`method: Locator.frameLocator`] method.
FrameLocator represents a view to the `iframe` on the page. It captures the logic sufficient to retrieve the `iframe` and locate elements in that iframe. FrameLocator can be created with either [`method: Locator.contentFrame`], [`method: Page.frameLocator`] or [`method: Locator.frameLocator`] method.
```js
const locator = page.frameLocator('#my-frame').getByText('Submit');
const locator = page.locator('#my-frame').contentFrame().getByText('Submit');
await locator.click();
```
```java
Locator locator = page.frameLocator("#my-frame").getByText("Submit");
Locator locator = page.locator("#my-frame").contentFrame().getByText("Submit");
locator.click();
```
```python async
locator = page.frame_locator("#my-frame").get_by_text("Submit")
locator = page.locator("#my-frame").content_frame.get_by_text("Submit")
await locator.click()
```
```python sync
locator = page.frame_locator("my-frame").get_by_text("Submit")
locator = page.locator("my-frame").content_frame.get_by_text("Submit")
locator.click()
```
```csharp
var locator = page.FrameLocator("#my-frame").GetByText("Submit");
var locator = page.Locator("#my-frame").ContentFrame.GetByText("Submit");
await locator.ClickAsync();
```
@ -34,42 +34,42 @@ Frame locators are strict. This means that all operations on frame locators will
```js
// Throws if there are several frames in DOM:
await page.frameLocator('.result-frame').getByRole('button').click();
await page.locator('.result-frame').contentFrame().getByRole('button').click();
// Works because we explicitly tell locator to pick the first frame:
await page.frameLocator('.result-frame').first().getByRole('button').click();
await page.locator('.result-frame').contentFrame().first().getByRole('button').click();
```
```python async
# Throws if there are several frames in DOM:
await page.frame_locator('.result-frame').get_by_role('button').click()
await page.locator('.result-frame').content_frame.get_by_role('button').click()
# Works because we explicitly tell locator to pick the first frame:
await page.frame_locator('.result-frame').first.get_by_role('button').click()
await page.locator('.result-frame').first.content_frame.get_by_role('button').click()
```
```python sync
# Throws if there are several frames in DOM:
page.frame_locator('.result-frame').get_by_role('button').click()
page.locator('.result-frame').content_frame.get_by_role('button').click()
# Works because we explicitly tell locator to pick the first frame:
page.frame_locator('.result-frame').first.get_by_role('button').click()
page.locator('.result-frame').first.content_frame.get_by_role('button').click()
```
```java
// Throws if there are several frames in DOM:
page.frame_locator(".result-frame").getByRole(AriaRole.BUTTON).click();
page.locator(".result-frame").contentFrame().getByRole(AriaRole.BUTTON).click();
// Works because we explicitly tell locator to pick the first frame:
page.frame_locator(".result-frame").first().getByRole(AriaRole.BUTTON).click();
page.locator(".result-frame").first().contentFrame().getByRole(AriaRole.BUTTON).click();
```
```csharp
// Throws if there are several frames in DOM:
await page.FrameLocator(".result-frame").GetByRole(AriaRole.Button).ClickAsync();
await page.Locator(".result-frame").ContentFrame.GetByRole(AriaRole.Button).ClickAsync();
// Works because we explicitly tell locator to pick the first frame:
await page.FrameLocator(".result-frame").First.getByRole(AriaRole.Button).ClickAsync();
await page.Locator(".result-frame").First.ContentFrame.getByRole(AriaRole.Button).ClickAsync();
```
**Converting Locator to FrameLocator**
@ -82,6 +82,7 @@ If you have a [FrameLocator] object it can be converted to [Locator] pointing to
## method: FrameLocator.first
* deprecated: Use [`method: Locator.first`] followed by [`method: Locator.contentFrame`] instead.
* since: v1.17
- returns: <[FrameLocator]>
@ -171,6 +172,7 @@ in that iframe.
### option: FrameLocator.getByTitle.exact = %%-locator-get-by-text-exact-%%
## method: FrameLocator.last
* deprecated: Use [`method: Locator.last`] followed by [`method: Locator.contentFrame`] instead.
* since: v1.17
- returns: <[FrameLocator]>
@ -195,6 +197,7 @@ Returns locator to the last matching frame.
* since: v1.33
## method: FrameLocator.nth
* deprecated: Use [`method: Locator.nth`] followed by [`method: Locator.contentFrame`] instead.
* since: v1.17
- returns: <[FrameLocator]>
@ -217,37 +220,36 @@ For a reverse operation, use [`method: Locator.contentFrame`].
**Usage**
```js
const frameLocator = page.frameLocator('iframe[name="embedded"]');
const frameLocator = page.locator('iframe[name="embedded"]').contentFrame();
// ...
const locator = frameLocator.owner();
await expect(locator).toBeVisible();
```
```java
FrameLocator frameLocator = page.frameLocator("iframe[name=\"embedded\"]");
FrameLocator frameLocator = page.locator("iframe[name=\"embedded\"]").contentFrame();
// ...
Locator locator = frameLocator.owner();
assertThat(locator).isVisible();
```
```python async
frame_locator = page.frame_locator("iframe[name=\"embedded\"]")
frame_locator = page.locator("iframe[name=\"embedded\"]").content_frame
# ...
locator = frame_locator.owner
await expect(locator).to_be_visible()
```
```python sync
frame_locator = page.frame_locator("iframe[name=\"embedded\"]")
frame_locator = page.locator("iframe[name=\"embedded\"]").content_frame
# ...
locator = frame_locator.owner
expect(locator).to_be_visible()
```
```csharp
var frameLocator = Page.FrameLocator("iframe[name=\"embedded\"]");
var frameLocator = Page.Locator("iframe[name=\"embedded\"]").ContentFrame;
// ...
var locator = frameLocator.Owner;
await Expect(locator).ToBeVisibleAsync();
```

View file

@ -104,38 +104,23 @@ await page.Keyboard.PressAsync("Shift+A");
An example to trigger select-all with the keyboard
```js
// on Windows and Linux
await page.keyboard.press('Control+A');
// on macOS
await page.keyboard.press('Meta+A');
await page.keyboard.press('ControlOrMeta+A');
```
```java
// on Windows and Linux
page.keyboard().press("Control+A");
// on macOS
page.keyboard().press("Meta+A");
page.keyboard().press("ControlOrMeta+A");
```
```python async
# on windows and linux
await page.keyboard.press("Control+A")
# on mac_os
await page.keyboard.press("Meta+A")
await page.keyboard.press("ControlOrMeta+A")
```
```python sync
# on windows and linux
page.keyboard.press("Control+A")
# on mac_os
page.keyboard.press("Meta+A")
page.keyboard.press("ControlOrMeta+A")
```
```csharp
// on Windows and Linux
await page.Keyboard.PressAsync("Control+A");
// on macOS
await page.Keyboard.PressAsync("Meta+A");
await page.Keyboard.PressAsync("ControlOrMeta+A");
```
## async method: Keyboard.down
@ -257,7 +242,7 @@ await browser.close();
Page page = browser.newPage();
page.navigate("https://keycode.info");
page.keyboard().press("A");
page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png"));
page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("A.png")));
page.keyboard().press("ArrowLeft");
page.screenshot(new Page.ScreenshotOptions().setPath(Paths.get("ArrowLeft.png")));
page.keyboard().press("Shift+O");

View file

@ -38,7 +38,7 @@ for li in page.get_by_role('listitem').all():
```
```java
for (Locator li : page.getByRole('listitem').all())
for (Locator li : page.getByRole("listitem").all())
li.click();
```
@ -54,7 +54,7 @@ foreach (var li in await page.GetByRole("listitem").AllAsync())
Returns an array of `node.innerText` values for all matching nodes.
:::warning[Asserting text]
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: LocatorAssertions.toHaveText.useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
:::
**Usage**
@ -150,6 +150,67 @@ var button = page.GetByRole(AriaRole.Button).And(page.GetByTitle("Subscribe"));
Additional locator to match.
## async method: Locator.ariaSnapshot
* since: v1.49
- returns: <[string]>
Captures the aria snapshot of the given element.
Read more about [aria snapshots](../aria-snapshots.md) and [`method: LocatorAssertions.toMatchAriaSnapshot`] for the corresponding assertion.
**Usage**
```js
await page.getByRole('link').ariaSnapshot();
```
```java
page.getByRole(AriaRole.LINK).ariaSnapshot();
```
```python async
await page.get_by_role("link").aria_snapshot()
```
```python sync
page.get_by_role("link").aria_snapshot()
```
```csharp
await page.GetByRole(AriaRole.Link).AriaSnapshotAsync();
```
**Details**
This method captures the aria snapshot of the given element. The snapshot is a string that represents the state of the element and its children.
The snapshot can be used to assert the state of the element in the test, or to compare it to state in the future.
The ARIA snapshot is represented using [YAML](https://yaml.org/spec/1.2.2/) markup language:
* The keys of the objects are the roles and optional accessible names of the elements.
* The values are either text content or an array of child elements.
* Generic static text can be represented with the `text` key.
Below is the HTML markup and the respective ARIA snapshot:
```html
<ul aria-label="Links">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<ul>
```
```yml
- list "Links":
- listitem:
- link "Home"
- listitem:
- link "About"
```
### option: Locator.ariaSnapshot.timeout = %%-input-timeout-%%
* since: v1.49
### option: Locator.ariaSnapshot.timeout = %%-input-timeout-js-%%
* since: v1.49
## async method: Locator.blur
* since: v1.28
@ -231,7 +292,6 @@ Performs the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked. If not, this method throws.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -267,7 +327,7 @@ await page.GetByRole(AriaRole.Checkbox).CheckAsync();
### option: Locator.check.force = %%-input-force-%%
* since: v1.14
### option: Locator.check.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.check.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.check.timeout = %%-input-timeout-%%
@ -317,7 +377,7 @@ await page.GetByRole(AriaRole.Textbox).ClearAsync();
### option: Locator.clear.force = %%-input-force-%%
* since: v1.28
### option: Locator.clear.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.clear.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.28
### option: Locator.clear.timeout = %%-input-timeout-%%
@ -434,7 +494,7 @@ await page.Locator("canvas").ClickAsync(new() {
### option: Locator.click.timeout = %%-input-timeout-js-%%
* since: v1.14
### option: Locator.click.trial = %%-input-trial-%%
### option: Locator.click.trial = %%-input-trial-with-modifiers-%%
* since: v1.14
## async method: Locator.count
@ -483,8 +543,6 @@ This method double clicks the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that
if the first click of the `dblclick()` triggers a navigation event, this method will throw.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -510,7 +568,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.dblclick.force = %%-input-force-%%
* since: v1.14
### option: Locator.dblclick.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.dblclick.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.dblclick.timeout = %%-input-timeout-%%
@ -519,7 +577,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.dblclick.timeout = %%-input-timeout-js-%%
* since: v1.14
### option: Locator.dblclick.trial = %%-input-trial-%%
### option: Locator.dblclick.trial = %%-input-trial-with-modifiers-%%
* since: v1.14
## async method: Locator.dispatchEvent
@ -575,13 +633,11 @@ properties:
You can also specify [JSHandle] as the property value if you want live objects to be passed into the event:
```js
// Note you can only create DataTransfer in Chromium and Firefox
const dataTransfer = await page.evaluateHandle(() => new DataTransfer());
await locator.dispatchEvent('dragstart', { dataTransfer });
```
```java
// Note you can only create DataTransfer in Chromium and Firefox
JSHandle dataTransfer = page.evaluateHandle("() => new DataTransfer()");
Map<String, Object> arg = new HashMap<>();
arg.put("dataTransfer", dataTransfer);
@ -589,13 +645,11 @@ locator.dispatchEvent("dragstart", arg);
```
```python async
# note you can only create data_transfer in chromium and firefox
data_transfer = await page.evaluate_handle("new DataTransfer()")
await locator.dispatch_event("#source", "dragstart", {"dataTransfer": data_transfer})
```
```python sync
# note you can only create data_transfer in chromium and firefox
data_transfer = page.evaluate_handle("new DataTransfer()")
locator.dispatch_event("#source", "dragstart", {"dataTransfer": data_transfer})
```
@ -709,7 +763,7 @@ Locator of the element to drag to.
### option: Locator.dragTo.force = %%-input-force-%%
* since: v1.18
### option: Locator.dragTo.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.dragTo.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.18
### option: Locator.dragTo.timeout = %%-input-timeout-%%
@ -810,31 +864,6 @@ If [`param: expression`] throws or rejects, this method throws.
**Usage**
```js
const tweets = page.locator('.tweet .retweets');
expect(await tweets.evaluate(node => node.innerText)).toBe('10 retweets');
```
```java
Locator tweets = page.locator(".tweet .retweets");
assertEquals("10 retweets", tweets.evaluate("node => node.innerText"));
```
```python async
tweets = page.locator(".tweet .retweets")
assert await tweets.evaluate("node => node.innerText") == "10 retweets"
```
```python sync
tweets = page.locator(".tweet .retweets")
assert tweets.evaluate("node => node.innerText") == "10 retweets"
```
```csharp
var tweets = page.Locator(".tweet .retweets");
Assert.AreEqual("10 retweets", await tweets.EvaluateAsync("node => node.innerText"));
```
### param: Locator.evaluate.expression = %%-evaluate-expression-%%
* since: v1.14
@ -986,7 +1015,7 @@ Value to set for the `<input>`, `<textarea>` or `[contenteditable]` element.
### option: Locator.fill.force = %%-input-force-%%
* since: v1.14
### option: Locator.fill.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.fill.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.fill.timeout = %%-input-timeout-%%
@ -1061,6 +1090,9 @@ await rowLocator
### option: Locator.filter.hasNotText = %%-locator-option-has-not-text-%%
* since: v1.33
### option: Locator.filter.visible = %%-locator-option-visible-%%
* since: v1.51
## method: Locator.first
* since: v1.14
- returns: <[Locator]>
@ -1248,7 +1280,6 @@ This method hovers over the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to hover over the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -1270,10 +1301,10 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.hover.timeout = %%-input-timeout-js-%%
* since: v1.14
### option: Locator.hover.trial = %%-input-trial-%%
### option: Locator.hover.trial = %%-input-trial-with-modifiers-%%
* since: v1.14
### option: Locator.hover.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.hover.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.28
## async method: Locator.innerHTML
@ -1295,7 +1326,7 @@ Returns the [`element.innerHTML`](https://developer.mozilla.org/en-US/docs/Web/A
Returns the [`element.innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText).
:::warning[Asserting text]
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
If you need to assert text on the page, prefer [`method: LocatorAssertions.toHaveText`] with [`option: LocatorAssertions.toHaveText.useInnerText`] option to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
:::
### option: Locator.innerText.timeout = %%-input-timeout-%%
@ -1426,7 +1457,7 @@ Boolean disabled = await page.GetByRole(AriaRole.Button).IsDisabledAsync();
* since: v1.14
- returns: <[boolean]>
Returns whether the element is [editable](../actionability.md#editable).
Returns whether the element is [editable](../actionability.md#editable). If the target element is not an `<input>`, `<textarea>`, `<select>`, `[contenteditable]` and does not have a role allowing `[aria-readonly]`, this method throws an error.
:::warning[Asserting editable state]
If you need to assert that an element is editable, prefer [`method: LocatorAssertions.toBeEditable`] to avoid flakiness. See [assertions guide](../test-assertions.md) for more details.
@ -1658,16 +1689,23 @@ var banana = await page.GetByRole(AriaRole.Listitem).Nth(2);
- alias-python: or_
- returns: <[Locator]>
Creates a locator that matches either of the two locators.
Creates a locator matching all elements that match one or both of the two locators.
Note that when both locators match something, the resulting locator will have multiple matches, potentially causing a [locator strictness](../locators.md#strictness) violation.
**Usage**
Consider a scenario where you'd like to click on a "New email" button, but sometimes a security settings dialog shows up instead. In this case, you can wait for either a "New email" button, or a dialog and act accordingly.
:::note
If both "New email" button and security dialog appear on screen, the "or" locator will match both of them,
possibly throwing the ["strict mode violation" error](../locators.md#strictness). In this case, you can use [`method: Locator.first`] to only match one of them.
:::
```js
const newEmail = page.getByRole('button', { name: 'New' });
const dialog = page.getByText('Confirm security settings');
await expect(newEmail.or(dialog)).toBeVisible();
await expect(newEmail.or(dialog).first()).toBeVisible();
if (await dialog.isVisible())
await page.getByRole('button', { name: 'Dismiss' }).click();
await newEmail.click();
@ -1676,7 +1714,7 @@ await newEmail.click();
```java
Locator newEmail = page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("New"));
Locator dialog = page.getByText("Confirm security settings");
assertThat(newEmail.or(dialog)).isVisible();
assertThat(newEmail.or(dialog).first()).isVisible();
if (dialog.isVisible())
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Dismiss")).click();
newEmail.click();
@ -1685,7 +1723,7 @@ newEmail.click();
```python async
new_email = page.get_by_role("button", name="New")
dialog = page.get_by_text("Confirm security settings")
await expect(new_email.or_(dialog)).to_be_visible()
await expect(new_email.or_(dialog).first).to_be_visible()
if (await dialog.is_visible()):
await page.get_by_role("button", name="Dismiss").click()
await new_email.click()
@ -1694,7 +1732,7 @@ await new_email.click()
```python sync
new_email = page.get_by_role("button", name="New")
dialog = page.get_by_text("Confirm security settings")
expect(new_email.or_(dialog)).to_be_visible()
expect(new_email.or_(dialog).first).to_be_visible()
if (dialog.is_visible()):
page.get_by_role("button", name="Dismiss").click()
new_email.click()
@ -1703,7 +1741,7 @@ new_email.click()
```csharp
var newEmail = page.GetByRole(AriaRole.Button, new() { Name = "New" });
var dialog = page.GetByText("Confirm security settings");
await Expect(newEmail.Or(dialog)).ToBeVisibleAsync();
await Expect(newEmail.Or(dialog).First).ToBeVisibleAsync();
if (await dialog.IsVisibleAsync())
await page.GetByRole(AriaRole.Button, new() { Name = "Dismiss" }).ClickAsync();
await newEmail.ClickAsync();
@ -1876,7 +1914,7 @@ String of characters to sequentially press into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: Locator.pressSequentially.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.pressSequentially.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.38
### option: Locator.pressSequentially.timeout = %%-input-timeout-%%
@ -2000,9 +2038,9 @@ Triggers a `change` and `input` event once all the provided options have been se
```html
<select multiple>
<option value="red">Red</div>
<option value="green">Green</div>
<option value="blue">Blue</div>
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select>
```
@ -2059,7 +2097,7 @@ await element.SelectOptionAsync(new[] { "red", "green", "blue" });
### option: Locator.selectOption.force = %%-input-force-%%
* since: v1.14
### option: Locator.selectOption.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.selectOption.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.selectOption.timeout = %%-input-timeout-%%
@ -2133,7 +2171,6 @@ This method checks or unchecks an element by performing the following steps:
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked or unchecked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -2145,7 +2182,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.setChecked.force = %%-input-force-%%
* since: v1.15
### option: Locator.setChecked.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.setChecked.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.15
### option: Locator.setChecked.position = %%-input-position-%%
@ -2286,7 +2323,7 @@ This method expects [Locator] to point to an
### param: Locator.setInputFiles.files = %%-input-files-%%
* since: v1.14
### option: Locator.setInputFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.setInputFiles.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.setInputFiles.timeout = %%-input-timeout-%%
@ -2298,7 +2335,7 @@ This method expects [Locator] to point to an
## async method: Locator.tap
* since: v1.14
Perform a tap gesture on the element matching the locator.
Perform a tap gesture on the element matching the locator. For examples of emulating other gestures by manually dispatching touch events, see the [emulating legacy touch events](../touch-events.md) page.
**Details**
@ -2306,7 +2343,6 @@ This method taps the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.touchscreen`] to tap the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -2326,7 +2362,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.tap.force = %%-input-force-%%
* since: v1.14
### option: Locator.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.tap.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.tap.timeout = %%-input-timeout-%%
@ -2335,7 +2371,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.tap.timeout = %%-input-timeout-js-%%
* since: v1.14
### option: Locator.tap.trial = %%-input-trial-%%
### option: Locator.tap.trial = %%-input-trial-with-modifiers-%%
* since: v1.14
## async method: Locator.textContent
@ -2376,7 +2412,7 @@ A text to type into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: Locator.type.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.type.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.type.timeout = %%-input-timeout-%%
@ -2420,7 +2456,6 @@ This method unchecks the element by performing the following steps:
1. Wait for [actionability](../actionability.md) checks on the element, unless [`option: force`] option is set.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now unchecked. If not, this method throws.
If the element is detached from the DOM at any moment during the action, this method throws.
@ -2434,7 +2469,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Locator.uncheck.force = %%-input-force-%%
* since: v1.14
### option: Locator.uncheck.noWaitAfter = %%-input-no-wait-after-%%
### option: Locator.uncheck.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.14
### option: Locator.uncheck.timeout = %%-input-timeout-%%

View file

@ -14,14 +14,14 @@ test('status becomes submitted', async ({ page }) => {
```
```java
...
// ...
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
public class TestLocator {
...
// ...
@Test
void statusBecomesSubmitted() {
...
// ...
page.getByRole(AriaRole.BUTTON).click();
assertThat(page.locator(".status")).hasText("Submitted");
}
@ -240,6 +240,24 @@ Expected accessible description.
### option: LocatorAssertions.NotToHaveAccessibleDescription.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.44
## async method: LocatorAssertions.NotToHaveAccessibleErrorMessage
* since: v1.50
* langs: python
The opposite of [`method: LocatorAssertions.toHaveAccessibleErrorMessage`].
### param: LocatorAssertions.NotToHaveAccessibleErrorMessage.errorMessage
* since: v1.50
- `errorMessage` <[string]|[RegExp]>
Expected accessible error message.
### option: LocatorAssertions.NotToHaveAccessibleErrorMessage.ignoreCase = %%-assertions-ignore-case-%%
* since: v1.50
### option: LocatorAssertions.NotToHaveAccessibleErrorMessage.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.50
## async method: LocatorAssertions.NotToHaveAccessibleName
* since: v1.44
@ -442,6 +460,23 @@ Expected options currently selected.
### option: LocatorAssertions.NotToHaveValues.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.23
## async method: LocatorAssertions.NotToMatchAriaSnapshot
* since: v1.49
* langs: python
The opposite of [`method: LocatorAssertions.toMatchAriaSnapshot`].
### param: LocatorAssertions.NotToMatchAriaSnapshot.expected
* since: v1.49
- `expected` <string>
### option: LocatorAssertions.NotToMatchAriaSnapshot.timeout = %%-js-assertions-timeout-%%
* since: v1.49
### option: LocatorAssertions.NotToMatchAriaSnapshot.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.49
## async method: LocatorAssertions.toBeAttached
* since: v1.33
@ -524,6 +559,16 @@ await Expect(locator).ToBeCheckedAsync();
* since: v1.18
- `checked` <[boolean]>
Provides state to assert for. Asserts for input to be checked by default.
This option can't be used when [`option: LocatorAssertions.toBeChecked.indeterminate`] is set to true.
### option: LocatorAssertions.toBeChecked.indeterminate
* since: v1.50
- `indeterminate` <[boolean]>
Asserts that the element is in the indeterminate (mixed) state. Only supported for checkboxes and radio buttons.
This option can't be true when [`option: LocatorAssertions.toBeChecked.checked`] is provided.
### option: LocatorAssertions.toBeChecked.timeout = %%-js-assertions-timeout-%%
* since: v1.18
@ -701,7 +746,7 @@ expect(locator).to_be_enabled()
```csharp
var locator = Page.Locator("button.submit");
await Expect(locator).toBeEnabledAsync();
await Expect(locator).ToBeEnabledAsync();
```
### option: LocatorAssertions.toBeEnabled.enabled
@ -1181,7 +1226,7 @@ expect(locator).to_have_accessible_description("Save results to disk")
```csharp
var locator = Page.GetByTestId("save-button");
await Expect(locator).toHaveAccessibleDescriptionAsync("Save results to disk");
await Expect(locator).ToHaveAccessibleDescriptionAsync("Save results to disk");
```
### param: LocatorAssertions.toHaveAccessibleDescription.description
@ -1200,6 +1245,56 @@ Expected accessible description.
* since: v1.44
## async method: LocatorAssertions.toHaveAccessibleErrorMessage
* since: v1.50
* langs:
- alias-java: hasAccessibleErrorMessage
Ensures the [Locator] points to an element with a given [aria errormessage](https://w3c.github.io/aria/#aria-errormessage).
**Usage**
```js
const locator = page.getByTestId('username-input');
await expect(locator).toHaveAccessibleErrorMessage('Username is required.');
```
```java
Locator locator = page.getByTestId("username-input");
assertThat(locator).hasAccessibleErrorMessage("Username is required.");
```
```python async
locator = page.get_by_test_id("username-input")
await expect(locator).to_have_accessible_error_message("Username is required.")
```
```python sync
locator = page.get_by_test_id("username-input")
expect(locator).to_have_accessible_error_message("Username is required.")
```
```csharp
var locator = Page.GetByTestId("username-input");
await Expect(locator).ToHaveAccessibleErrorMessageAsync("Username is required.");
```
### param: LocatorAssertions.toHaveAccessibleErrorMessage.errorMessage
* since: v1.50
- `errorMessage` <[string]|[RegExp]>
Expected accessible error message.
### option: LocatorAssertions.toHaveAccessibleErrorMessage.timeout = %%-js-assertions-timeout-%%
* since: v1.50
### option: LocatorAssertions.toHaveAccessibleErrorMessage.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.50
### option: LocatorAssertions.toHaveAccessibleErrorMessage.ignoreCase = %%-assertions-ignore-case-%%
* since: v1.50
## async method: LocatorAssertions.toHaveAccessibleName
* since: v1.44
* langs:
@ -1231,7 +1326,7 @@ expect(locator).to_have_accessible_name("Save to disk")
```csharp
var locator = Page.GetByTestId("save-button");
await Expect(locator).toHaveAccessibleNameAsync("Save to disk");
await Expect(locator).ToHaveAccessibleNameAsync("Save to disk");
```
### param: LocatorAssertions.toHaveAccessibleName.name
@ -1336,49 +1431,48 @@ Attribute name.
* langs:
- alias-java: hasClass
Ensures the [Locator] points to an element with given CSS classes. This needs to be a full match
or using a relaxed regular expression.
Ensures the [Locator] points to an element with given CSS classes. When a string is provided, it must fully match the element's `class` attribute. To match individual classes or perform partial matches, use a regular expression:
**Usage**
```html
<div class='selected row' id='component'></div>
<div class='middle selected row' id='component'></div>
```
```js
const locator = page.locator('#component');
await expect(locator).toHaveClass(/selected/);
await expect(locator).toHaveClass('selected row');
await expect(locator).toHaveClass('middle selected row');
await expect(locator).toHaveClass(/(^|\s)selected(\s|$)/);
```
```java
assertThat(page.locator("#component")).hasClass(Pattern.compile("selected"));
assertThat(page.locator("#component")).hasClass("selected row");
assertThat(page.locator("#component")).hasClass(Pattern.compile("(^|\\s)selected(\\s|$)"));
assertThat(page.locator("#component")).hasClass("middle selected row");
```
```python async
from playwright.async_api import expect
locator = page.locator("#component")
await expect(locator).to_have_class(re.compile(r"selected"))
await expect(locator).to_have_class("selected row")
await expect(locator).to_have_class(re.compile(r"(^|\\s)selected(\\s|$)"))
await expect(locator).to_have_class("middle selected row")
```
```python sync
from playwright.sync_api import expect
locator = page.locator("#component")
expect(locator).to_have_class(re.compile(r"selected"))
expect(locator).to_have_class("selected row")
expect(locator).to_have_class(re.compile(r"(^|\\s)selected(\\s|$)"))
expect(locator).to_have_class("middle selected row")
```
```csharp
var locator = Page.Locator("#component");
await Expect(locator).ToHaveClassAsync(new Regex("selected"));
await Expect(locator).ToHaveClassAsync("selected row");
await Expect(locator).ToHaveClassAsync(new Regex("(^|\\s)selected(\\s|$)"));
await Expect(locator).ToHaveClassAsync("middle selected row");
```
Note that if array is passed as an expected value, entire lists of elements can be asserted:
When an array is passed, the method asserts that the list of elements located matches the corresponding list of expected class values. Each element's class attribute is matched against the corresponding string or regular expression in the array:
```js
const locator = page.locator('list > .component');
@ -2048,7 +2142,7 @@ await expect(locator).toHaveValues([/R/, /G/]);
```
```java
page.locator("id=favorite-colors").selectOption(["R", "G"]);
page.locator("id=favorite-colors").selectOption(new String[]{"R", "G"});
assertThat(page.locator("id=favorite-colors")).hasValues(new Pattern[] { Pattern.compile("R"), Pattern.compile("G") });
```
@ -2103,3 +2197,91 @@ Expected options currently selected.
### option: LocatorAssertions.toHaveValues.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.23
## async method: LocatorAssertions.toMatchAriaSnapshot
* since: v1.49
* langs:
- alias-java: matchesAriaSnapshot
Asserts that the target element matches the given [accessibility snapshot](../aria-snapshots.md).
**Usage**
```js
await page.goto('https://demo.playwright.dev/todomvc/');
await expect(page.locator('body')).toMatchAriaSnapshot(`
- heading "todos"
- textbox "What needs to be done?"
`);
```
```python async
await page.goto("https://demo.playwright.dev/todomvc/")
await expect(page.locator('body')).to_match_aria_snapshot('''
- heading "todos"
- textbox "What needs to be done?"
''')
```
```python sync
page.goto("https://demo.playwright.dev/todomvc/")
expect(page.locator('body')).to_match_aria_snapshot('''
- heading "todos"
- textbox "What needs to be done?"
''')
```
```csharp
await page.GotoAsync("https://demo.playwright.dev/todomvc/");
await Expect(page.Locator("body")).ToMatchAriaSnapshotAsync(@"
- heading ""todos""
- textbox ""What needs to be done?""
");
```
```java
page.navigate("https://demo.playwright.dev/todomvc/");
assertThat(page.locator("body")).matchesAriaSnapshot("""
- heading "todos"
- textbox "What needs to be done?"
""");
```
### param: LocatorAssertions.toMatchAriaSnapshot.expected
* since: v1.49
- `expected` <string>
### option: LocatorAssertions.toMatchAriaSnapshot.timeout = %%-js-assertions-timeout-%%
* since: v1.49
### option: LocatorAssertions.toMatchAriaSnapshot.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.49
## async method: LocatorAssertions.toMatchAriaSnapshot#2
* since: v1.50
* langs: js
Asserts that the target element matches the given [accessibility snapshot](../aria-snapshots.md).
Snapshot is stored in a separate `.snapshot.yml` file in a location configured by `expect.toMatchAriaSnapshot.pathTemplate` and/or `snapshotPathTemplate` properties in the configuration file.
**Usage**
```js
await expect(page.locator('body')).toMatchAriaSnapshot();
await expect(page.locator('body')).toMatchAriaSnapshot({ name: 'body.snapshot.yml' });
```
### option: LocatorAssertions.toMatchAriaSnapshot#2.name
* since: v1.50
* langs: js
- `name` <[string]>
Name of the snapshot to store in the snapshot folder corresponding to this test.
Generates sequential names if not specified.
### option: LocatorAssertions.toMatchAriaSnapshot#2.timeout = %%-js-assertions-timeout-%%
* since: v1.50
### option: LocatorAssertions.toMatchAriaSnapshot#2.timeout = %%-csharp-java-python-assertions-timeout-%%
* since: v1.50

View file

@ -68,10 +68,14 @@ Shortcut for [`method: Mouse.move`], [`method: Mouse.down`], [`method: Mouse.up`
* since: v1.8
- `x` <[float]>
X coordinate relative to the main frame's viewport in CSS pixels.
### param: Mouse.click.y
* since: v1.8
- `y` <[float]>
Y coordinate relative to the main frame's viewport in CSS pixels.
### option: Mouse.click.button = %%-input-button-%%
* since: v1.8
@ -93,10 +97,14 @@ Shortcut for [`method: Mouse.move`], [`method: Mouse.down`], [`method: Mouse.up`
* since: v1.8
- `x` <[float]>
X coordinate relative to the main frame's viewport in CSS pixels.
### param: Mouse.dblclick.y
* since: v1.8
- `y` <[float]>
Y coordinate relative to the main frame's viewport in CSS pixels.
### option: Mouse.dblclick.button = %%-input-button-%%
* since: v1.8
@ -123,10 +131,14 @@ Dispatches a `mousemove` event.
* since: v1.8
- `x` <[float]>
X coordinate relative to the main frame's viewport in CSS pixels.
### param: Mouse.move.y
* since: v1.8
- `y` <[float]>
Y coordinate relative to the main frame's viewport in CSS pixels.
### option: Mouse.move.steps
* since: v1.8
- `steps` <[int]>

View file

@ -1,6 +1,5 @@
# class: Page
* since: v1.8
* extends: [EventEmitter]
Page provides methods to interact with a single tab in a [Browser], or an
[extension background page](https://developer.chrome.com/extensions/background_pages) in Chromium. One [Browser]
@ -688,7 +687,7 @@ Raw JavaScript content to be injected into frame.
* since: v1.8
- `type` <[string]>
Script type. Use 'module' in order to load a Javascript ES6 module. See
Script type. Use 'module' in order to load a JavaScript ES6 module. See
[script](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script) for more details.
## async method: Page.addStyleTag
@ -735,7 +734,6 @@ This method checks an element matching [`param: selector`] by performing the fol
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -747,7 +745,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.check.force = %%-input-force-%%
* since: v1.8
### option: Page.check.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.check.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.check.position = %%-input-position-%%
@ -814,7 +812,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.click.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Page.click.trial = %%-input-trial-%%
### option: Page.click.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
## async method: Page.close
@ -879,8 +877,6 @@ This method double clicks an element matching [`param: selector`] by performing
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to double click in the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set. Note that
if the first click of the `dblclick()` triggers a navigation event, this method will throw.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
[TimeoutError]. Passing zero timeout disables this.
@ -904,7 +900,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.dblclick.modifiers = %%-input-modifiers-%%
* since: v1.8
### option: Page.dblclick.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.dblclick.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.dblclick.position = %%-input-position-%%
@ -919,7 +915,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.dblclick.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Page.dblclick.trial = %%-input-trial-%%
### option: Page.dblclick.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
## async method: Page.dispatchEvent
@ -1045,9 +1041,9 @@ await page.dragAndDrop('#source', '#target', {
```
```java
page.dragAndDrop("#source", '#target');
page.dragAndDrop("#source", "#target");
// or specify exact positions relative to the top-left corners of the elements:
page.dragAndDrop("#source", '#target', new Page.DragAndDropOptions()
page.dragAndDrop("#source", "#target", new Page.DragAndDropOptions()
.setSourcePosition(34, 7).setTargetPosition(10, 20));
```
@ -1092,7 +1088,7 @@ await Page.DragAndDropAsync("#source", "#target", new()
### option: Page.dragAndDrop.force = %%-input-force-%%
* since: v1.13
### option: Page.dragAndDrop.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.dragAndDrop.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.13
### option: Page.dragAndDrop.strict = %%-input-strict-%%
@ -1221,8 +1217,6 @@ await page.evaluate(() => matchMedia('(prefers-color-scheme: dark)').matches);
// → true
await page.evaluate(() => matchMedia('(prefers-color-scheme: light)').matches);
// → false
await page.evaluate(() => matchMedia('(prefers-color-scheme: no-preference)').matches);
// → false
```
```java
@ -1231,8 +1225,6 @@ page.evaluate("() => matchMedia('(prefers-color-scheme: dark)').matches");
// → true
page.evaluate("() => matchMedia('(prefers-color-scheme: light)').matches");
// → false
page.evaluate("() => matchMedia('(prefers-color-scheme: no-preference)').matches");
// → false
```
```python async
@ -1241,8 +1233,6 @@ await page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
# → True
await page.evaluate("matchMedia('(prefers-color-scheme: light)').matches")
# → False
await page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches")
# → False
```
```python sync
@ -1251,7 +1241,6 @@ page.evaluate("matchMedia('(prefers-color-scheme: dark)').matches")
# → True
page.evaluate("matchMedia('(prefers-color-scheme: light)').matches")
# → False
page.evaluate("matchMedia('(prefers-color-scheme: no-preference)').matches")
```
```csharp
@ -1260,8 +1249,6 @@ await page.EvaluateAsync("matchMedia('(prefers-color-scheme: dark)').matches");
// → true
await page.EvaluateAsync("matchMedia('(prefers-color-scheme: light)').matches");
// → false
await page.EvaluateAsync("matchMedia('(prefers-color-scheme: no-preference)').matches");
// → false
```
### option: Page.emulateMedia.media
@ -1285,16 +1272,16 @@ Passing `'Null'` disables CSS media emulation.
* langs: js, java
- `colorScheme` <null|[ColorScheme]<"light"|"dark"|"no-preference">>
Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. Passing
`null` disables color scheme emulation.
Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. Passing
`null` disables color scheme emulation. `'no-preference'` is deprecated.
### option: Page.emulateMedia.colorScheme
* since: v1.9
* langs: csharp, python
- `colorScheme` <[ColorScheme]<"light"|"dark"|"no-preference"|"null">>
Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. Passing
`'Null'` disables color scheme emulation.
Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. Passing
`'Null'` disables color scheme emulation. `'no-preference'` is deprecated.
### option: Page.emulateMedia.reducedMotion
* since: v1.12
@ -1322,6 +1309,18 @@ Emulates `'forced-colors'` media feature, supported values are `'active'` and `'
* langs: csharp, python
- `forcedColors` <[ForcedColors]<"active"|"none"|"null">>
### option: Page.emulateMedia.contrast
* since: v1.51
* langs: js, java
- `contrast` <null|[Contrast]<"no-preference"|"more">>
Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. Passing `null` disables contrast emulation.
### option: Page.emulateMedia.contrast
* since: v1.51
* langs: csharp, python
- `contrast` <[Contrast]<"no-preference"|"more"|"null">>
## async method: Page.evalOnSelector
* since: v1.9
* discouraged: This method does not wait for the element to pass actionability
@ -1720,7 +1719,7 @@ public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType webkit = playwright.webkit();
Browser browser = webkit.launch({ headless: false });
Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
BrowserContext context = browser.newContext();
Page page = context.newPage();
page.exposeBinding("pageURL", (source, args) -> source.page().url());
@ -1817,80 +1816,6 @@ class PageExamples
}
```
An example of passing an element handle:
```js
await page.exposeBinding('clicked', async (source, element) => {
console.log(await element.textContent());
}, { handle: true });
await page.setContent(`
<script>
document.addEventListener('click', event => window.clicked(event.target));
</script>
<div>Click me</div>
<div>Or click me</div>
`);
```
```java
page.exposeBinding("clicked", (source, args) -> {
ElementHandle element = (ElementHandle) args[0];
System.out.println(element.textContent());
return null;
}, new Page.ExposeBindingOptions().setHandle(true));
page.setContent("" +
"<script>\n" +
" document.addEventListener('click', event => window.clicked(event.target));\n" +
"</script>\n" +
"<div>Click me</div>\n" +
"<div>Or click me</div>\n");
```
```python async
async def print(source, element):
print(await element.text_content())
await page.expose_binding("clicked", print, handle=true)
await page.set_content("""
<script>
document.addEventListener('click', event => window.clicked(event.target));
</script>
<div>Click me</div>
<div>Or click me</div>
""")
```
```python sync
def print(source, element):
print(element.text_content())
page.expose_binding("clicked", print, handle=true)
page.set_content("""
<script>
document.addEventListener('click', event => window.clicked(event.target));
</script>
<div>Click me</div>
<div>Or click me</div>
""")
```
```csharp
var result = new TaskCompletionSource<string>();
await page.ExposeBindingAsync("clicked", async (BindingSource _, IJSHandle t) =>
{
return result.TrySetResult(await t.AsElement().TextContentAsync());
});
await page.SetContentAsync("<script>\n" +
" document.addEventListener('click', event => window.clicked(event.target));\n" +
"</script>\n" +
"<div>Click me</div>\n" +
"<div>Or click me</div>\n");
await page.ClickAsync("div");
Console.WriteLine(await result.Task);
```
### param: Page.exposeBinding.name
* since: v1.8
- `name` <[string]>
@ -1905,6 +1830,7 @@ Callback function that will be called in the Playwright's context.
### option: Page.exposeBinding.handle
* since: v1.8
* deprecated: This option will be removed in the future.
- `handle` <[boolean]>
Whether to pass the argument as a handle, instead of passing by value. When passing a handle, only one argument is
@ -1963,26 +1889,27 @@ public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
BrowserType webkit = playwright.webkit();
Browser browser = webkit.launch({ headless: false });
Browser browser = webkit.launch(new BrowserType.LaunchOptions().setHeadless(false));
Page page = browser.newPage();
page.exposeFunction("sha256", args -> {
String text = (String) args[0];
MessageDigest crypto;
try {
crypto = MessageDigest.getInstance("SHA-256");
String text = (String) args[0];
MessageDigest crypto = MessageDigest.getInstance("SHA-256");
byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(token);
} catch (NoSuchAlgorithmException e) {
return null;
}
byte[] token = crypto.digest(text.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(token);
});
page.setContent("<script>\n" +
page.setContent(
"<script>\n" +
" async function onClick() {\n" +
" document.querySelector('div').textContent = await window.sha256('PLAYWRIGHT');\n" +
" }\n" +
"</script>\n" +
"<button onclick=\"onClick()\">Click me</button>\n" +
"<div></div>\n");
"<div></div>"
);
page.click("button");
}
}
@ -2123,7 +2050,7 @@ Value to fill for the `<input>`, `<textarea>` or `[contenteditable]` element.
### option: Page.fill.force = %%-input-force-%%
* since: v1.13
### option: Page.fill.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.fill.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.fill.strict = %%-input-strict-%%
@ -2183,7 +2110,7 @@ const frame = page.frame({ url: /.*domain.*/ });
```
```java
Frame frame = page.frameByUrl(Pattern.compile(".*domain.*");
Frame frame = page.frameByUrl(Pattern.compile(".*domain.*"));
```
```py
@ -2388,7 +2315,7 @@ Attribute name to get the value for.
- returns: <[null]|[Response]>
Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
last redirect. If can not go back, returns `null`.
last redirect. If cannot go back, returns `null`.
Navigate to the previous page in history.
@ -2406,10 +2333,62 @@ Navigate to the previous page in history.
- returns: <[null]|[Response]>
Returns the main resource response. In case of multiple redirects, the navigation will resolve with the response of the
last redirect. If can not go forward, returns `null`.
last redirect. If cannot go forward, returns `null`.
Navigate to the next page in history.
## async method: Page.requestGC
* since: v1.48
Request the page to perform garbage collection. Note that there is no guarantee that all unreachable objects will be collected.
This is useful to help detect memory leaks. For example, if your page has a large object `'suspect'` that might be leaked, you can check that it does not leak by using a [`WeakRef`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef).
```js
// 1. In your page, save a WeakRef for the "suspect".
await page.evaluate(() => globalThis.suspectWeakRef = new WeakRef(suspect));
// 2. Request garbage collection.
await page.requestGC();
// 3. Check that weak ref does not deref to the original object.
expect(await page.evaluate(() => !globalThis.suspectWeakRef.deref())).toBe(true);
```
```java
// 1. In your page, save a WeakRef for the "suspect".
page.evaluate("globalThis.suspectWeakRef = new WeakRef(suspect)");
// 2. Request garbage collection.
page.requestGC();
// 3. Check that weak ref does not deref to the original object.
assertTrue(page.evaluate("!globalThis.suspectWeakRef.deref()"));
```
```python async
# 1. In your page, save a WeakRef for the "suspect".
await page.evaluate("globalThis.suspectWeakRef = new WeakRef(suspect)")
# 2. Request garbage collection.
await page.request_gc()
# 3. Check that weak ref does not deref to the original object.
assert await page.evaluate("!globalThis.suspectWeakRef.deref()")
```
```python sync
# 1. In your page, save a WeakRef for the "suspect".
page.evaluate("globalThis.suspectWeakRef = new WeakRef(suspect)")
# 2. Request garbage collection.
page.request_gc()
# 3. Check that weak ref does not deref to the original object.
assert page.evaluate("!globalThis.suspectWeakRef.deref()")
```
```csharp
// 1. In your page, save a WeakRef for the "suspect".
await Page.EvaluateAsync("globalThis.suspectWeakRef = new WeakRef(suspect)");
// 2. Request garbage collection.
await Page.RequestGCAsync();
// 3. Check that weak ref does not deref to the original object.
Assert.True(await Page.EvaluateAsync("!globalThis.suspectWeakRef.deref()"));
```
### option: Page.goForward.waitUntil = %%-navigation-wait-until-%%
* since: v1.8
@ -2454,7 +2433,7 @@ Headless mode doesn't support navigation to a PDF document. See the
- `url` <[string]>
URL to navigate page to. The url should include scheme, e.g. `https://`.
When a [`option: baseURL`] via the context options was provided and the passed URL is a path,
When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path,
it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
### option: Page.goto.waitUntil = %%-navigation-wait-until-%%
@ -2484,7 +2463,6 @@ This method hovers over an element matching [`param: selector`] by performing th
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to hover over the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless `noWaitAfter` option is set.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
[TimeoutError]. Passing zero timeout disables this.
@ -2510,10 +2488,10 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.hover.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Page.hover.trial = %%-input-trial-%%
### option: Page.hover.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
### option: Page.hover.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.hover.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.28
## async method: Page.innerHTML
@ -2662,7 +2640,7 @@ Returns whether the element is [enabled](../actionability.md#enabled).
* discouraged: Use locator-based [`method: Locator.isHidden`] instead. Read more about [locators](../locators.md).
- returns: <[boolean]>
Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible). [`option: selector`] that does not match any elements is considered hidden.
Returns whether the element is hidden, the opposite of [visible](../actionability.md#visible). [`param: selector`] that does not match any elements is considered hidden.
### param: Page.isHidden.selector = %%-input-selector-%%
* since: v1.8
@ -2681,7 +2659,7 @@ Returns whether the element is hidden, the opposite of [visible](../actionabilit
* discouraged: Use locator-based [`method: Locator.isVisible`] instead. Read more about [locators](../locators.md).
- returns: <[boolean]>
Returns whether the element is [visible](../actionability.md#visible). [`option: selector`] that does not match any elements is considered not visible.
Returns whether the element is [visible](../actionability.md#visible). [`param: selector`] that does not match any elements is considered not visible.
### param: Page.isVisible.selector = %%-input-selector-%%
* since: v1.8
@ -2787,8 +2765,7 @@ User can inspect selectors or perform manual steps while paused. Resume will con
the place it was paused.
:::note
This method requires Playwright to be started in a headed mode, with a falsy [`option: headless`] value in
the [`method: BrowserType.launch`].
This method requires Playwright to be started in a headed mode, with a falsy [`option: BrowserType.launch.headless`] option.
:::
## async method: Page.pdf
@ -2797,10 +2774,6 @@ the [`method: BrowserType.launch`].
Returns the PDF buffer.
:::note
Generating a pdf is currently only supported in Chromium headless.
:::
`page.pdf()` generates a pdf of the page with `print` css media. To generate a pdf with `screen` media, call
[`method: Page.emulateMedia`] before calling `page.pdf()`:
@ -3165,11 +3138,9 @@ Things to keep in mind:
:::warning
Running the handler will alter your page state mid-test. For example it will change the currently focused element and move the mouse. Make sure that actions that run after the handler are self-contained and do not rely on the focus and mouse state being unchanged.
<br />
<br />
For example, consider a test that calls [`method: Locator.focus`] followed by [`method: Keyboard.press`]. If your handler clicks a button between these two actions, the focused element most likely will be wrong, and key press will happen on the unexpected element. Use [`method: Locator.press`] instead to avoid this problem.
<br />
<br />
Another example is a series of mouse actions, where [`method: Mouse.move`] is followed by [`method: Mouse.down`]. Again, when the handler runs between these two actions, the mouse position will be wrong during the mouse down. Prefer self-contained actions like [`method: Locator.click`] that do not rely on the state being unchanged by a handler.
:::
@ -3190,12 +3161,12 @@ await page.getByRole('button', { name: 'Start here' }).click();
```java
// Setup the handler.
page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () => {
page.addLocatorHandler(page.getByText("Sign up to the newsletter"), () -> {
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("No thanks")).click();
});
// Write the test as usual.
page.goto("https://example.com");
page.navigate("https://example.com");
page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
```
@ -3247,12 +3218,12 @@ await page.getByRole('button', { name: 'Start here' }).click();
```java
// Setup the handler.
page.addLocatorHandler(page.getByText("Confirm your security details")), () => {
page.addLocatorHandler(page.getByText("Confirm your security details"), () -> {
page.getByRole(AriaRole.BUTTON, new Page.GetByRoleOptions().setName("Remind me later")).click();
});
// Write the test as usual.
page.goto("https://example.com");
page.navigate("https://example.com");
page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
```
@ -3304,12 +3275,12 @@ await page.getByRole('button', { name: 'Start here' }).click();
```java
// Setup the handler.
page.addLocatorHandler(page.locator("body")), () => {
page.addLocatorHandler(page.locator("body"), () -> {
page.evaluate("window.removeObstructionsForTestIfNeeded()");
}, new Page.AddLocatorHandlerOptions.setNoWaitAfter(true));
}, new Page.AddLocatorHandlerOptions().setNoWaitAfter(true));
// Write the test as usual.
page.goto("https://example.com");
page.navigate("https://example.com");
page.getByRole("button", Page.GetByRoleOptions().setName("Start here")).click();
```
@ -3355,7 +3326,7 @@ await page.addLocatorHandler(page.getByLabel('Close'), async locator => {
```
```java
page.addLocatorHandler(page.getByLabel("Close"), locator => {
page.addLocatorHandler(page.getByLabel("Close"), locator -> {
locator.click();
}, new Page.AddLocatorHandlerOptions().setTimes(1));
```
@ -3417,6 +3388,32 @@ Specifies the maximum number of times this handler should be called. Unlimited b
By default, after calling the handler Playwright will wait until the overlay becomes hidden, and only then Playwright will continue with the action/assertion that triggered the handler. This option allows to opt-out of this behavior, so that overlay can stay visible after the handler has run.
## async method: Page.removeAllListeners
* since: v1.47
* langs: js
Removes all the listeners of the given type (or all registered listeners if no type given).
Allows to wait for async listeners to complete or to ignore subsequent errors from these listeners.
**Usage**
```js
page.on('request', async request => {
const response = await request.response();
const body = await response.body();
console.log(body.byteLength);
});
await page.goto('https://playwright.dev', { waitUntil: 'domcontentloaded' });
// Waits for all the reported 'request' events to resolve.
await page.removeAllListeners('request', { behavior: 'wait' });
```
### param: Page.removeAllListeners.type
* since: v1.47
- `type` ?<[string]>
### option: Page.removeAllListeners.behavior = %%-remove-all-listeners-options-behavior-%%
* since: v1.47
## async method: Page.removeLocatorHandler
* since: v1.44
@ -3611,7 +3608,7 @@ Enabling routing disables http cache.
- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]>
A glob pattern, regex pattern or predicate receiving [URL] to match while routing.
When a [`option: baseURL`] via the context options was provided and the passed URL is a path,
When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path,
it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
### param: Page.route.handler
@ -3671,7 +3668,7 @@ A glob pattern, regular expression or predicate to match the request URL. Only r
* since: v1.32
- `updateMode` <[HarMode]<"full"|"minimal">>
When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page, cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page, cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `minimal`.
### option: Page.routeFromHAR.updateContent
* since: v1.32
@ -3679,6 +3676,88 @@ When set to `minimal`, only record information necessary for routing from HAR. T
Optional setting to control resource content management. If `attach` is specified, resources are persisted as separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file.
## async method: Page.routeWebSocket
* since: v1.48
This method allows to modify websocket connections that are made by the page.
Note that only `WebSocket`s created after this method was called will be routed. It is recommended to call this method before navigating the page.
**Usage**
Below is an example of a simple mock that responds to a single message. See [WebSocketRoute] for more details and examples.
```js
await page.routeWebSocket('/ws', ws => {
ws.onMessage(message => {
if (message === 'request')
ws.send('response');
});
});
```
```java
page.routeWebSocket("/ws", ws -> {
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
ws.send("response");
});
});
```
```python async
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
ws.send("response")
def handler(ws: WebSocketRoute):
ws.on_message(lambda message: message_handler(ws, message))
await page.route_web_socket("/ws", handler)
```
```python sync
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
ws.send("response")
def handler(ws: WebSocketRoute):
ws.on_message(lambda message: message_handler(ws, message))
page.route_web_socket("/ws", handler)
```
```csharp
await page.RouteWebSocketAsync("/ws", ws => {
ws.OnMessage(frame => {
if (frame.Text == "request")
ws.Send("response");
});
});
```
### param: Page.routeWebSocket.url
* since: v1.48
- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]>
Only WebSockets with the url matching this pattern will be routed. A string pattern can be relative to the [`option: Browser.newContext.baseURL`] context option.
### param: Page.routeWebSocket.handler
* since: v1.48
* langs: js, python
- `handler` <[function]\([WebSocketRoute]\): [Promise<any>|any]>
Handler function to route the WebSocket.
### param: Page.routeWebSocket.handler
* since: v1.48
* langs: csharp, java
- `handler` <[function]\([WebSocketRoute]\)>
Handler function to route the WebSocket.
## async method: Page.screenshot
* since: v1.8
- returns: <[Buffer]>
@ -3778,7 +3857,7 @@ await page.SelectOptionAsync("select#colors", new[] { "red", "green", "blue" });
### option: Page.selectOption.force = %%-input-force-%%
* since: v1.13
### option: Page.selectOption.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.selectOption.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.selectOption.strict = %%-input-strict-%%
@ -3815,7 +3894,6 @@ This method checks or unchecks an element matching [`param: selector`] by perfor
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now checked or unchecked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -3830,7 +3908,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.setChecked.force = %%-input-force-%%
* since: v1.15
### option: Page.setChecked.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.setChecked.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.15
### option: Page.setChecked.position = %%-input-position-%%
@ -3904,7 +3982,7 @@ This setting will change the default maximum time for all the methods accepting
* since: v1.8
- `timeout` <[float]>
Maximum time in milliseconds
Maximum time in milliseconds. Pass `0` to disable timeout.
## async method: Page.setExtraHTTPHeaders
* since: v1.8
@ -3938,7 +4016,7 @@ This method expects [`param: selector`] to point to an
### param: Page.setInputFiles.files = %%-input-files-%%
* since: v1.8
### option: Page.setInputFiles.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.setInputFiles.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.setInputFiles.strict = %%-input-strict-%%
@ -4004,12 +4082,16 @@ await page.GotoAsync("https://www.microsoft.com");
### param: Page.setViewportSize.width
* since: v1.10
* langs: csharp, java
- `width` <[int]> page width in pixels.
- `width` <[int]>
Page width in pixels.
### param: Page.setViewportSize.height
* since: v1.10
* langs: csharp, java
- `height` <[int]> page height in pixels.
- `height` <[int]>
Page height in pixels.
## async method: Page.tap
* since: v1.8
@ -4022,13 +4104,12 @@ This method taps an element matching [`param: selector`] by performing the follo
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.touchscreen`] to tap the center of the element, or the specified [`option: position`].
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
[TimeoutError]. Passing zero timeout disables this.
:::note
[`method: Page.tap`] the method will throw if [`option: hasTouch`] option of the browser context is false.
[`method: Page.tap`] the method will throw if [`option: Browser.newContext.hasTouch`] option of the browser context is false.
:::
### param: Page.tap.selector = %%-input-selector-%%
@ -4040,7 +4121,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.tap.modifiers = %%-input-modifiers-%%
* since: v1.8
### option: Page.tap.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.tap.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.tap.position = %%-input-position-%%
@ -4055,7 +4136,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.tap.timeout = %%-input-timeout-js-%%
* since: v1.8
### option: Page.tap.trial = %%-input-trial-%%
### option: Page.tap.trial = %%-input-trial-with-modifiers-%%
* since: v1.11
## async method: Page.textContent
@ -4113,7 +4194,7 @@ A text to type into a focused element.
Time to wait between key presses in milliseconds. Defaults to 0.
### option: Page.type.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.type.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.type.strict = %%-input-strict-%%
@ -4138,7 +4219,6 @@ This method unchecks an element matching [`param: selector`] by performing the f
set. If the element is detached during the checks, the whole action is retried.
1. Scroll the element into view if needed.
1. Use [`property: Page.mouse`] to click in the center of the element.
1. Wait for initiated navigations to either succeed or fail, unless [`option: noWaitAfter`] option is set.
1. Ensure that the element is now unchecked. If not, this method throws.
When all steps combined have not finished during the specified [`option: timeout`], this method throws a
@ -4150,7 +4230,7 @@ When all steps combined have not finished during the specified [`option: timeout
### option: Page.uncheck.force = %%-input-force-%%
* since: v1.8
### option: Page.uncheck.noWaitAfter = %%-input-no-wait-after-%%
### option: Page.uncheck.noWaitAfter = %%-input-no-wait-after-removed-%%
* since: v1.8
### option: Page.uncheck.position = %%-input-position-%%
@ -4816,7 +4896,7 @@ await page.RunAndWaitForRequestAsync(async () =>
- `urlOrPredicate` <[string]|[RegExp]|[function]\([Request]\):[boolean]>
Request URL string, regex or predicate receiving [Request] object.
When a [`option: baseURL`] via the context options was provided and the passed URL is a path,
When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path,
it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
### param: Page.waitForRequest.urlOrPredicate
@ -4960,7 +5040,7 @@ await page.RunAndWaitForResponseAsync(async () =>
- `urlOrPredicate` <[string]|[RegExp]|[function]\([Response]\):[boolean]>
Request URL string, regex or predicate receiving [Response] object.
When a [`option: baseURL`] via the context options was provided and the passed URL is a path,
When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path,
it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
### param: Page.waitForResponse.urlOrPredicate
@ -4969,7 +5049,7 @@ it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/We
- `urlOrPredicate` <[string]|[RegExp]|[function]\([Response]\):[boolean]|[Promise]<[boolean]>>
Request URL string, regex or predicate receiving [Response] object.
When a [`option: baseURL`] via the context options was provided and the passed URL is a path,
When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path,
it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor.
### option: Page.waitForResponse.timeout

View file

@ -14,14 +14,14 @@ test('navigates to login', async ({ page }) => {
```
```java
...
// ...
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
public class TestPage {
...
// ...
@Test
void navigatesToLoginPage() {
...
// ...
page.getByText("Sign in").click();
assertThat(page).hasURL(Pattern.compile(".*/login"));
}
@ -59,7 +59,7 @@ namespace PlaywrightTests;
public class ExampleTests : PageTest
{
[TestMethod]
public async Task NavigatetoLoginPage()
public async Task NavigateToLoginPage()
{
await Page.GetByRole(AriaRole.Button, new() { Name = "Sign In" }).ClickAsync();
await Expect(Page).ToHaveURLAsync(new Regex(".*/login"));
@ -83,7 +83,7 @@ assertThat(page).not().hasURL("error");
```
```csharp
await Expect(Page).Not.ToHaveURL("error");
await Expect(Page).Not.ToHaveURLAsync("error");
```
## async method: PageAssertions.NotToHaveTitle
@ -271,7 +271,7 @@ expect(page).to_have_title(re.compile(r".*checkout"))
```
```csharp
await Expect(Page).ToHaveTitle("Playwright");
await Expect(Page).ToHaveTitleAsync("Playwright");
```
### param: PageAssertions.toHaveTitle.titleOrRegExp
@ -296,7 +296,18 @@ Ensures the page is navigated to the given URL.
**Usage**
```js
await expect(page).toHaveURL(/.*checkout/);
// Check for the page URL to be 'https://playwright.dev/docs/intro' (including query string)
await expect(page).toHaveURL('https://playwright.dev/docs/intro');
// Check for the page URL to contain 'doc', followed by an optional 's', followed by '/'
await expect(page).toHaveURL(/docs?\//);
// Check for the predicate to be satisfied
// For example: verify query strings
await expect(page).toHaveURL(url => {
const params = url.searchParams;
return params.has('search') && params.has('options') && params.get('id') === '5';
});
```
```java
@ -320,20 +331,21 @@ expect(page).to_have_url(re.compile(".*checkout"))
```
```csharp
await Expect(Page).ToHaveURL(new Regex(".*checkout"));
await Expect(Page).ToHaveURLAsync(new Regex(".*checkout"));
```
### param: PageAssertions.toHaveURL.urlOrRegExp
### param: PageAssertions.toHaveURL.url
* since: v1.18
- `urlOrRegExp` <[string]|[RegExp]>
- `url` <[string]|[RegExp]|[function]\([URL]\):[boolean]>
Expected URL string or RegExp.
Expected URL string, RegExp, or predicate receiving [URL] to match.
When [`option: Browser.newContext.baseURL`] is provided via the context options and the `url` argument is a string, the two values are merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor and used for the comparison against the current browser URL.
### option: PageAssertions.toHaveURL.ignoreCase
* since: v1.44
- `ignoreCase` <[boolean]>
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression flag if specified.
Whether to perform case-insensitive match. [`option: ignoreCase`] option takes precedence over the corresponding regular expression parameter if specified. A provided predicate ignores this flag.
### option: PageAssertions.toHaveURL.timeout = %%-js-assertions-timeout-%%
* since: v1.18

View file

@ -35,14 +35,13 @@ def test_status_becomes_submitted(page: Page) -> None:
```
```java
...
import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat;
public class TestExample {
...
// ...
@Test
void statusBecomesSubmitted() {
...
// ...
page.locator("#submit-button").click();
assertThat(page.locator(".status")).hasText("Submitted");
}

View file

@ -124,7 +124,7 @@ Headers with multiple entries, such as `Set-Cookie`, appear in the array multipl
* since: v1.15
- returns: <[null]|[string]>
Returns the value of the header matching the name. The name is case insensitive.
Returns the value of the header matching the name. The name is case-insensitive.
### param: Request.headerValue.name
* since: v1.15

View file

@ -126,6 +126,16 @@ Whether to ignore HTTPS errors when sending network requests.
Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded.
Defaults to `20`. Pass `0` to not follow redirects.
## method: RequestOptions.setMaxRetries
* since: v1.46
- returns: <[RequestOptions]>
### param: RequestOptions.setMaxRetries.maxRetries
* since: v1.46
- `maxRetries` <[int]>
Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
## method: RequestOptions.setMethod
* since: v1.18
- returns: <[RequestOptions]>

View file

@ -59,7 +59,7 @@ Headers with multiple entries, such as `Set-Cookie`, appear in the array multipl
* since: v1.15
- returns: <[null]|[string]>
Returns the value of the header matching the name. The name is case insensitive. If multiple headers have
Returns the value of the header matching the name. The name is case-insensitive. If multiple headers have
the same name (except `set-cookie`), they are returned as a list separated by `, `. For `set-cookie`, the `\n` separator is used. If no headers are found, `null` is returned.
### param: Response.headerValue.name
@ -72,7 +72,7 @@ Name of the header.
* since: v1.15
- returns: <[Array]<[string]>>
Returns all values of the headers matching the name, for example `set-cookie`. The name is case insensitive.
Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive.
### param: Response.headerValues.name
* since: v1.15

View file

@ -39,7 +39,7 @@ Optional error code. Defaults to `failed`, could be one of the following:
- alias-java: resume
- alias-python: continue_
Continues route's request with optional overrides.
Sends route's request to the network with optional overrides.
**Usage**
@ -102,7 +102,9 @@ await page.RouteAsync("**/*", async route =>
**Details**
Note that any overrides such as [`option: url`] or [`option: headers`] only apply to the request being routed. If this request results in a redirect, overrides will not be applied to the new redirected request. If you want to propagate a header through redirects, use the combination of [`method: Route.fetch`] and [`method: Route.fulfill`] instead.
The [`option: headers`] option applies to both the routed request and any redirects it initiates. However, [`option: url`], [`option: method`], and [`option: postData`] only apply to the original request and are not carried over to redirected requests.
[`method: Route.continue`] will immediately send the request to the network, other matching handlers won't be invoked. Use [`method: Route.fallback`] If you want next matching handler in the chain to be invoked.
### option: Route.continue.url
* since: v1.8
@ -146,13 +148,15 @@ If set changes the request HTTP headers. Header values will be converted to a st
## async method: Route.fallback
* since: v1.23
Continues route's request with optional overrides. The method is similar to [`method: Route.continue`] with the difference that other matching handlers will be invoked before sending the request.
**Usage**
When several routes match the given pattern, they run in the order opposite to their registration.
That way the last registered route can always override all the previous ones. In the example below,
request will be handled by the bottom-most handler first, then it'll fall back to the previous one and
in the end will be aborted by the first registered route.
**Usage**
```js
await page.route('**/*', async route => {
// Runs last.
@ -386,6 +390,8 @@ await page.RouteAsync("**/*", async route =>
});
```
Use [`method: Route.continue`] to immediately send the request to the network, other matching handlers won't be invoked in that case.
### option: Route.fallback.url
* since: v1.23
- `url` <[string]>
@ -503,6 +509,12 @@ If set changes the request URL. New URL must have same protocol as original one.
Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded.
Defaults to `20`. Pass `0` to not follow redirects.
### option: Route.fetch.maxRetries
* since: v1.46
- `maxRetries` <[int]>
Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
### option: Route.fetch.timeout
* since: v1.33
- `timeout` <[float]>

View file

@ -4,19 +4,25 @@
The Touchscreen class operates in main-frame CSS pixels relative to the top-left corner of the viewport. Methods on the
touchscreen can only be used in browser contexts that have been initialized with `hasTouch` set to true.
This class is limited to emulating tap gestures. For examples of other gestures simulated by manually dispatching touch events, see the [emulating legacy touch events](../touch-events.md) page.
## async method: Touchscreen.tap
* since: v1.8
Dispatches a `touchstart` and `touchend` event with a single touch at the position ([`param: x`],[`param: y`]).
:::note
[`method: Page.tap`] the method will throw if [`option: hasTouch`] option of the browser context is false.
[`method: Page.tap`] the method will throw if [`option: Browser.newContext.hasTouch`] option of the browser context is false.
:::
### param: Touchscreen.tap.x
* since: v1.8
- `x` <[float]>
X coordinate relative to the main frame's viewport in CSS pixels.
### param: Touchscreen.tap.y
* since: v1.8
- `y` <[float]>
Y coordinate relative to the main frame's viewport in CSS pixels.

View file

@ -121,7 +121,7 @@ await context.Tracing.StopAsync(new()
- `name` <[string]>
If specified, intermediate trace files are going to be saved into the files with the
given name prefix inside the [`option: tracesDir`] folder specified in [`method: BrowserType.launch`].
given name prefix inside the [`option: BrowserType.launch.tracesDir`] directory specified in [`method: BrowserType.launch`].
To specify the final trace zip file name, you need to pass `path` option to
[`method: Tracing.stop`] instead.
@ -277,10 +277,84 @@ Trace name to be shown in the Trace Viewer.
- `name` <[string]>
If specified, intermediate trace files are going to be saved into the files with the
given name prefix inside the [`option: tracesDir`] folder specified in [`method: BrowserType.launch`].
given name prefix inside the [`option: BrowserType.launch.tracesDir`] directory specified in [`method: BrowserType.launch`].
To specify the final trace zip file name, you need to pass `path` option to
[`method: Tracing.stopChunk`] instead.
## async method: Tracing.group
* since: v1.49
:::caution
Use `test.step` instead when available.
:::
Creates a new group within the trace, assigning any subsequent API calls to this group, until [`method: Tracing.groupEnd`] is called. Groups can be nested and will be visible in the trace viewer.
**Usage**
```js
// use test.step instead
await test.step('Log in', async () => {
// ...
});
```
```java
// All actions between group and groupEnd
// will be shown in the trace viewer as a group.
page.context().tracing().group("Open Playwright.dev > API");
page.navigate("https://playwright.dev/");
page.getByRole(AriaRole.LINK, new Page.GetByRoleOptions().setName("API")).click();
page.context().tracing().groupEnd();
```
```python sync
# All actions between group and group_end
# will be shown in the trace viewer as a group.
page.context.tracing.group("Open Playwright.dev > API")
page.goto("https://playwright.dev/")
page.get_by_role("link", name="API").click()
page.context.tracing.group_end()
```
```python async
# All actions between group and group_end
# will be shown in the trace viewer as a group.
await page.context.tracing.group("Open Playwright.dev > API")
await page.goto("https://playwright.dev/")
await page.get_by_role("link", name="API").click()
await page.context.tracing.group_end()
```
```csharp
// All actions between GroupAsync and GroupEndAsync
// will be shown in the trace viewer as a group.
await Page.Context.Tracing.GroupAsync("Open Playwright.dev > API");
await Page.GotoAsync("https://playwright.dev/");
await Page.GetByRole(AriaRole.Link, new() { Name = "API" }).ClickAsync();
await Page.Context.Tracing.GroupEndAsync();
```
### param: Tracing.group.name
* since: v1.49
- `name` <[string]>
Group name shown in the trace viewer.
### option: Tracing.group.location
* since: v1.49
- `location` ?<[Object]>
- `file` <[string]>
- `line` ?<[int]>
- `column` ?<[int]>
Specifies a custom location for the group to be shown in the trace viewer. Defaults to the location of the [`method: Tracing.group`] call.
## async method: Tracing.groupEnd
* since: v1.49
Closes the last group created by [`method: Tracing.group`].
## async method: Tracing.stop
* since: v1.12

View file

@ -1,7 +1,9 @@
# class: WebSocket
* since: v1.8
The [WebSocket] class represents websocket connections in the page.
The [WebSocket] class represents WebSocket connections within a page. It provides the ability to inspect and manipulate the data being transmitted and received.
If you want to intercept or modify WebSocket frames, consider using [WebSocketRoute].
## event: WebSocket.close
* since: v1.8

View file

@ -0,0 +1,384 @@
# class: WebSocketRoute
* since: v1.48
Whenever a [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) route is set up with [`method: Page.routeWebSocket`] or [`method: BrowserContext.routeWebSocket`], the `WebSocketRoute` object allows to handle the WebSocket, like an actual server would do.
**Mocking**
By default, the routed WebSocket will not connect to the server. This way, you can mock entire communcation over the WebSocket. Here is an example that responds to a `"request"` with a `"response"`.
```js
await page.routeWebSocket('wss://example.com/ws', ws => {
ws.onMessage(message => {
if (message === 'request')
ws.send('response');
});
});
```
```java
page.routeWebSocket("wss://example.com/ws", ws -> {
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
ws.send("response");
});
});
```
```python async
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
ws.send("response")
await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
lambda message: message_handler(ws, message)
))
```
```python sync
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
ws.send("response")
page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
lambda message: message_handler(ws, message)
))
```
```csharp
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
ws.OnMessage(frame => {
if (frame.Text == "request")
ws.Send("response");
});
});
```
Since we do not call [`method: WebSocketRoute.connectToServer`] inside the WebSocket route handler, Playwright assumes that WebSocket will be mocked, and opens the WebSocket inside the page automatically.
Here is another example that handles JSON messages:
```js
await page.routeWebSocket('wss://example.com/ws', ws => {
ws.onMessage(message => {
const json = JSON.parse(message);
if (json.request === 'question')
ws.send(JSON.stringify({ response: 'answer' }));
});
});
```
```java
page.routeWebSocket("wss://example.com/ws", ws -> {
ws.onMessage(frame -> {
JsonObject json = new JsonParser().parse(frame.text()).getAsJsonObject();
if ("question".equals(json.get("request").getAsString())) {
Map<String, String> result = new HashMap();
result.put("response", "answer");
ws.send(gson.toJson(result));
}
});
});
```
```python async
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
json_message = json.loads(message)
if json_message["request"] == "question":
ws.send(json.dumps({ "response": "answer" }))
await page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
lambda message: message_handler(ws, message)
))
```
```python sync
def message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
json_message = json.loads(message)
if json_message["request"] == "question":
ws.send(json.dumps({ "response": "answer" }))
page.route_web_socket("wss://example.com/ws", lambda ws: ws.on_message(
lambda message: message_handler(ws, message)
))
```
```csharp
await page.RouteWebSocketAsync("wss://example.com/ws", ws => {
ws.OnMessage(frame => {
using var jsonDoc = JsonDocument.Parse(frame.Text);
JsonElement root = jsonDoc.RootElement;
if (root.TryGetProperty("request", out JsonElement requestElement) && requestElement.GetString() == "question")
{
var response = new Dictionary<string, string> { ["response"] = "answer" };
string jsonResponse = JsonSerializer.Serialize(response);
ws.Send(jsonResponse);
}
});
});
```
**Intercepting**
Alternatively, you may want to connect to the actual server, but intercept messages in-between and modify or block them. Calling [`method: WebSocketRoute.connectToServer`] returns a server-side `WebSocketRoute` instance that you can send messages to, or handle incoming messages.
Below is an example that modifies some messages sent by the page to the server. Messages sent from the server to the page are left intact, relying on the default forwarding.
```js
await page.routeWebSocket('/ws', ws => {
const server = ws.connectToServer();
ws.onMessage(message => {
if (message === 'request')
server.send('request2');
else
server.send(message);
});
});
```
```java
page.routeWebSocket("/ws", ws -> {
WebSocketRoute server = ws.connectToServer();
ws.onMessage(frame -> {
if ("request".equals(frame.text()))
server.send("request2");
else
server.send(frame.text());
});
});
```
```python async
def message_handler(server: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
server.send("request2")
else:
server.send(message)
def handler(ws: WebSocketRoute):
server = ws.connect_to_server()
ws.on_message(lambda message: message_handler(server, message))
await page.route_web_socket("/ws", handler)
```
```python sync
def message_handler(server: WebSocketRoute, message: Union[str, bytes]):
if message == "request":
server.send("request2")
else:
server.send(message)
def handler(ws: WebSocketRoute):
server = ws.connect_to_server()
ws.on_message(lambda message: message_handler(server, message))
page.route_web_socket("/ws", handler)
```
```csharp
await page.RouteWebSocketAsync("/ws", ws => {
var server = ws.ConnectToServer();
ws.OnMessage(frame => {
if (frame.Text == "request")
server.Send("request2");
else
server.Send(frame.Text);
});
});
```
After connecting to the server, all **messages are forwarded** between the page and the server by default.
However, if you call [`method: WebSocketRoute.onMessage`] on the original route, messages from the page to the server **will not be forwarded** anymore, but should instead be handled by the [`param: WebSocketRoute.onMessage.handler`].
Similarly, calling [`method: WebSocketRoute.onMessage`] on the server-side WebSocket will **stop forwarding messages** from the server to the page, and [`param: WebSocketRoute.onMessage.handler`] should take care of them.
The following example blocks some messages in both directions. Since it calls [`method: WebSocketRoute.onMessage`] in both directions, there is no automatic forwarding at all.
```js
await page.routeWebSocket('/ws', ws => {
const server = ws.connectToServer();
ws.onMessage(message => {
if (message !== 'blocked-from-the-page')
server.send(message);
});
server.onMessage(message => {
if (message !== 'blocked-from-the-server')
ws.send(message);
});
});
```
```java
page.routeWebSocket("/ws", ws -> {
WebSocketRoute server = ws.connectToServer();
ws.onMessage(frame -> {
if (!"blocked-from-the-page".equals(frame.text()))
server.send(frame.text());
});
server.onMessage(frame -> {
if (!"blocked-from-the-server".equals(frame.text()))
ws.send(frame.text());
});
});
```
```python async
def ws_message_handler(server: WebSocketRoute, message: Union[str, bytes]):
if message != "blocked-from-the-page":
server.send(message)
def server_message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message != "blocked-from-the-server":
ws.send(message)
def handler(ws: WebSocketRoute):
server = ws.connect_to_server()
ws.on_message(lambda message: ws_message_handler(server, message))
server.on_message(lambda message: server_message_handler(ws, message))
await page.route_web_socket("/ws", handler)
```
```python sync
def ws_message_handler(server: WebSocketRoute, message: Union[str, bytes]):
if message != "blocked-from-the-page":
server.send(message)
def server_message_handler(ws: WebSocketRoute, message: Union[str, bytes]):
if message != "blocked-from-the-server":
ws.send(message)
def handler(ws: WebSocketRoute):
server = ws.connect_to_server()
ws.on_message(lambda message: ws_message_handler(server, message))
server.on_message(lambda message: server_message_handler(ws, message))
page.route_web_socket("/ws", handler)
```
```csharp
await page.RouteWebSocketAsync("/ws", ws => {
var server = ws.ConnectToServer();
ws.OnMessage(frame => {
if (frame.Text != "blocked-from-the-page")
server.Send(frame.Text);
});
server.OnMessage(frame => {
if (frame.Text != "blocked-from-the-server")
ws.Send(frame.Text);
});
});
```
## async method: WebSocketRoute.close
* since: v1.48
Closes one side of the WebSocket connection.
### option: WebSocketRoute.close.code
* since: v1.48
- `code` <[int]>
Optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code).
### option: WebSocketRoute.close.reason
* since: v1.48
- `reason` <[string]>
Optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason).
## method: WebSocketRoute.connectToServer
* since: v1.48
- returns: <[WebSocketRoute]>
By default, routed WebSocket does not connect to the server, so you can mock entire WebSocket communication. This method connects to the actual WebSocket server, and returns the server-side [WebSocketRoute] instance, giving the ability to send and receive messages from the server.
Once connected to the server:
* Messages received from the server will be **automatically forwarded** to the WebSocket in the page, unless [`method: WebSocketRoute.onMessage`] is called on the server-side `WebSocketRoute`.
* Messages sent by the [`WebSocket.send()`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send) call in the page will be **automatically forwarded** to the server, unless [`method: WebSocketRoute.onMessage`] is called on the original `WebSocketRoute`.
See examples at the top for more details.
## method: WebSocketRoute.onClose
* since: v1.48
Allows to handle [`WebSocket.close`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close).
By default, closing one side of the connection, either in the page or on the server, will close the other side. However, when [`method: WebSocketRoute.onClose`] handler is set up, the default forwarding of closure is disabled, and handler should take care of it.
### param: WebSocketRoute.onClose.handler
* since: v1.48
* langs: js, python
- `handler` <[function]\([int]|[undefined], [string]|[undefined]\): [Promise<any>|any]>
Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason).
### param: WebSocketRoute.onClose.handler
* since: v1.48
* langs: java
- `handler` <[function]\([null]|[int], [null]|[string]\)>
Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason).
### param: WebSocketRoute.onClose.handler
* since: v1.48
* langs: csharp
- `handler` <[function]\([int?], [string]\)>
Function that will handle WebSocket closure. Received an optional [close code](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#code) and an optional [close reason](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/close#reason).
## method: WebSocketRoute.onMessage
* since: v1.48
This method allows to handle messages that are sent by the WebSocket, either from the page or from the server.
When called on the original WebSocket route, this method handles messages sent from the page. You can handle this messages by responding to them with [`method: WebSocketRoute.send`], forwarding them to the server-side connection returned by [`method: WebSocketRoute.connectToServer`] or do something else.
Once this method is called, messages are not automatically forwarded to the server or to the page - you should do that manually by calling [`method: WebSocketRoute.send`]. See examples at the top for more details.
Calling this method again will override the handler with a new one.
### param: WebSocketRoute.onMessage.handler
* since: v1.48
* langs: js, python
- `handler` <[function]\([string]\): [Promise<any>|any]>
Function that will handle messages.
### param: WebSocketRoute.onMessage.handler
* since: v1.48
* langs: csharp, java
- `handler` <[function]\([WebSocketFrame]\)>
Function that will handle messages.
## method: WebSocketRoute.send
* since: v1.48
Sends a message to the WebSocket. When called on the original WebSocket, sends the message to the page. When called on the result of [`method: WebSocketRoute.connectToServer`], sends the message to the server. See examples at the top for more details.
### param: WebSocketRoute.send.message
* since: v1.48
- `message` <[string]|[Buffer]>
Message to send.
## method: WebSocketRoute.url
* since: v1.48
- returns: <[string]>
URL of the WebSocket created in the page.

View file

@ -62,12 +62,19 @@ Maximum time in milliseconds. Defaults to `0` - no timeout. The default value ca
[`method: Page.setDefaultTimeout`] methods.
## input-no-wait-after
* deprecated: This option will default to `true` in the future.
- `noWaitAfter` <[boolean]>
Actions that initiate navigations are waiting for these navigations to happen and for pages to start loading. You can
opt out of waiting via setting this flag. You would only need this option in the exceptional cases such as navigating
to inaccessible pages. Defaults to `false`.
## input-no-wait-after-removed
* deprecated: This option has no effect.
- `noWaitAfter` <[boolean]>
This option has no effect.
## input-force
- `force` <[boolean]>
@ -129,6 +136,11 @@ defaults to 1. See [UIEvent.detail].
When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it.
## input-trial-with-modifiers
- `trial` <[boolean]>
When set, this method only performs the [actionability](../actionability.md) checks and skips the action. Defaults to `false`. Useful to wait until the element is ready for the action without performing it. Note that keyboard `modifiers` will be pressed regardless of `trial` to allow testing elements which are only visible when those keys are pressed.
## input-source-position
- `sourcePosition` <[Object]>
- `x` <[float]>
@ -247,11 +259,12 @@ Specify environment variables that will be visible to the browser. Defaults to `
- `httpOnly` <[boolean]>
- `secure` <[boolean]>
- `sameSite` <[SameSiteAttribute]<"Strict"|"Lax"|"None">> sameSite flag
- `origins` <[Array]<[Object]>> localStorage to set for context
- `origins` <[Array]<[Object]>>
- `origin` <[string]>
- `localStorage` <[Array]<[Object]>>
- `localStorage` <[Array]<[Object]>> localStorage to set for context
- `name` <[string]>
- `value` <[string]>
- `indexedDB` ?<[Array]<[unknown]>> indexedDB to set for context
Learn more about [storage state and auth](../auth.md).
@ -349,9 +362,15 @@ Emulates consistent window screen size available inside web page via `window.scr
Target URL.
## js-python-fetch-option-params
* langs: js, python
- `params` <[Object]<[string], [string]|[float]|[boolean]>>
## js-fetch-option-params
* langs: js
- `params` <[Object]<[string], [string]|[float]|[boolean]>|[URLSearchParams]|[string]>
Query parameters to be sent with the URL.
## python-fetch-option-params
* langs: python
- `params` <[Object]<[string], [string]|[float]|[boolean]>|[string]>
Query parameters to be sent with the URL.
@ -361,7 +380,13 @@ Query parameters to be sent with the URL.
Query parameters to be sent with the URL.
## java-csharp-fetch-params
## csharp-fetch-option-paramsString
* langs: csharp
- `paramsString` <[string]>
Query parameters to be sent with the URL.
## java-fetch-params
* langs: java
- `options` ?<[RequestOptions]>
@ -386,8 +411,16 @@ Request timeout in milliseconds. Defaults to `30000` (30 seconds). Pass `0` to d
Whether to throw on response codes other than 2xx and 3xx. By default response object is returned
for all status codes.
## js-python-fetch-option-form
* langs: js, python
## js-fetch-option-form
* langs: js
- `form` <[Object]<[string], [string]|[float]|[boolean]>|[FormData]>
Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent as
this request body. If this parameter is specified `content-type` header will be set to `application/x-www-form-urlencoded`
unless explicitly provided.
## python-fetch-option-form
* langs: python
- `form` <[Object]<[string], [string]|[float]|[boolean]>>
Provides an object that will be serialized as html form using `application/x-www-form-urlencoded` encoding and sent as
@ -458,6 +491,12 @@ Whether to ignore HTTPS errors when sending network requests. Defaults to `false
Maximum number of request redirects that will be followed automatically. An error will be thrown if the number is exceeded.
Defaults to `20`. Pass `0` to not follow redirects.
## js-python-csharp-fetch-option-maxretries
* langs: js, python, csharp
- `maxRetries` <[int]>
Maximum number of times network errors should be retried. Currently only `ECONNRESET` error is retried. Does not retry based on HTTP response codes. An error will be thrown if the limit is exceeded. Defaults to `0` - no retries.
## evaluate-expression
- `expression` <[string]>
@ -508,6 +547,27 @@ Sets a consistent viewport for each page. Defaults to an 1280x720 viewport. `no_
Does not enforce fixed viewport, allows resizing window in the headed mode.
## context-option-clientCertificates
- `clientCertificates` <[Array]<[Object]>>
- `origin` <[string]> Exact origin that the certificate is valid for. Origin includes `https` protocol, a hostname and optionally a port.
- `certPath` ?<[path]> Path to the file with the certificate in PEM format.
- `cert` ?<[Buffer]> Direct value of the certificate in PEM format.
- `keyPath` ?<[path]> Path to the file with the private key in PEM format.
- `key` ?<[Buffer]> Direct value of the private key in PEM format.
- `pfxPath` ?<[path]> Path to the PFX or PKCS12 encoded private key and certificate chain.
- `pfx` ?<[Buffer]> Direct value of the PFX or PKCS12 encoded private key and certificate chain.
- `passphrase` ?<[string]> Passphrase for the private key (PEM or PFX).
TLS Client Authentication allows the server to request a client certificate and verify it.
**Details**
An array of client certificates to be used. Each certificate object must have either both `certPath` and `keyPath`, a single `pfxPath`, or their corresponding direct value equivalents (`cert` and `key`, or `pfx`). Optionally, `passphrase` property should be provided if the certificate is encrypted. The `origin` property should be provided with an exact match to the request origin that the certificate is valid for.
:::note
When using WebKit on macOS, accessing `localhost` will not pick up client certificates. You can make it work by replacing `localhost` with `local.playwright`.
:::
## context-option-useragent
- `userAgent` <[string]>
@ -580,14 +640,14 @@ If no origin is specified, the username and password are sent to any servers upo
* langs: js, java
- `colorScheme` <null|[ColorScheme]<"light"|"dark"|"no-preference">>
Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See
Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. See
[`method: Page.emulateMedia`] for more details. Passing `null` resets emulation to system defaults. Defaults to `'light'`.
## context-option-colorscheme-csharp-python
* langs: csharp, python
- `colorScheme` <[ColorScheme]<"light"|"dark"|"no-preference"|"null">>
Emulates `'prefers-colors-scheme'` media feature, supported values are `'light'`, `'dark'`, `'no-preference'`. See
Emulates [prefers-colors-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media feature, supported values are `'light'` and `'dark'`. See
[`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'light'`.
## context-option-reducedMotion
@ -614,6 +674,18 @@ Emulates `'forced-colors'` media feature, supported values are `'active'`, `'non
Emulates `'forced-colors'` media feature, supported values are `'active'`, `'none'`. See [`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'none'`.
## context-option-contrast
* langs: js, java
- `contrast` <null|[ForcedColors]<"no-preference"|"more">>
Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See [`method: Page.emulateMedia`] for more details. Passing `null` resets emulation to system defaults. Defaults to `'no-preference'`.
## context-option-contrast-csharp-python
* langs: csharp, python
- `contrast` <[ForcedColors]<"no-preference"|"more"|"null">>
Emulates `'prefers-contrast'` media feature, supported values are `'no-preference'`, `'more'`. See [`method: Page.emulateMedia`] for more details. Passing `'null'` resets emulation to system defaults. Defaults to `'no-preference'`.
## context-option-logger
* langs: js
- `logger` <[Logger]>
@ -640,7 +712,7 @@ Logger sink for Playwright logging.
- `content` ?<[HarContentPolicy]<"omit"|"embed"|"attach">> Optional setting to control resource content management. If `omit` is specified, content is not persisted. If `attach` is specified, resources are persisted as separate files or entries in the ZIP archive. If `embed` is specified, content is stored inline the HAR file as per HAR specification. Defaults to `attach` for `.zip` output files and to `embed` for all other file extensions.
- `path` <[path]> Path on the filesystem to write the HAR file to. If the file name ends with `.zip`, `content: 'attach'` is used by default.
- `mode` ?<[HarMode]<"full"|"minimal">> When set to `minimal`, only record information necessary for routing from HAR. This omits sizes, timing, page, cookies, security and other types of HAR information that are not used when replaying from HAR. Defaults to `full`.
- `urlFilter` ?<[string]|[RegExp]> A glob or regex pattern to filter requests that are stored in the HAR. When a [`option: baseURL`] via the context options was provided and the passed URL is a path, it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. Defaults to none.
- `urlFilter` ?<[string]|[RegExp]> A glob or regex pattern to filter requests that are stored in the HAR. When a [`option: Browser.newContext.baseURL`] via the context options was provided and the passed URL is a path, it gets merged via the [`new URL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/URL) constructor. Defaults to none.
Enables [HAR](http://www.softwareishard.com/blog/har-12-spec) recording for all pages into `recordHar.path` file. If not
specified, the HAR is not recorded. Make sure to await [`method: BrowserContext.close`] for the HAR to be
@ -706,8 +778,6 @@ not recorded. Make sure to call [`method: BrowserContext.close`] for videos to b
* langs: csharp, java, python
- alias-python: record_video_size
- `recordVideoSize` <[Object]>
If `viewport` is not configured explicitly the video size defaults to 800x450. Actual picture of each page will be
scaled down if necessary to fit the specified size.
- `width` <[int]> Video frame width.
- `height` <[int]> Video frame height.
@ -725,12 +795,6 @@ Actual picture of each page will be scaled down if necessary to fit the specifie
Network proxy settings to use with this context. Defaults to none.
:::note
For Chromium on Windows the browser needs to be launched with the global proxy for this option to work. If all
contexts override the proxy, global proxy will be never used and can be any string, for example
`launch({ proxy: { server: 'http://per-context' } })`.
:::
## context-option-strict
- `strictSelectors` <[boolean]>
@ -746,6 +810,16 @@ Whether to allow sites to register Service workers. Defaults to `'allow'`.
* `'allow'`: [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API) can be registered.
* `'block'`: Playwright will block all registration of Service Workers.
## remove-all-listeners-options-behavior
* langs: js
* since: v1.47
- `behavior` <[RemoveAllListenersBehavior]<"wait"|"ignoreErrors"|"default">>
Specifies whether to wait for already running listeners and what to do if they throw errors:
* `'default'` - do not wait for current listener calls (if any) to finish, if the listener throws, it may result in unhandled error
* `'wait'` - wait for current listener calls (if any) to finish
* `'ignoreErrors'` - do not wait for current listener calls (if any) to finish, all errors thrown by the listeners after removal are silently caught
## unroute-all-options-behavior
* langs: js, csharp, python
* since: v1.41
@ -756,6 +830,7 @@ Specifies whether to wait for already running handlers and what to do if they th
* `'wait'` - wait for current handler calls (if any) to finish
* `'ignoreErrors'` - do not wait for current handler calls (if any) to finish, all errors thrown by the handlers after unrouting are silently caught
## select-options-values
* langs: java, js, csharp
- `values` <[null]|[string]|[ElementHandle]|[Array]<[string]>|[Object]|[Array]<[ElementHandle]>|[Array]<[Object]>>
@ -911,6 +986,8 @@ between the same pixel in compared images, between zero (strict) and one (lax),
- %%-context-option-reducedMotion-csharp-python-%%
- %%-context-option-forcedColors-%%
- %%-context-option-forcedColors-csharp-python-%%
- %%-context-option-contrast-%%
- %%-context-option-contrast-csharp-python-%%
- %%-context-option-logger-%%
- %%-context-option-videospath-%%
- %%-context-option-videosize-%%
@ -939,7 +1016,11 @@ Additional arguments to pass to the browser instance. The list of Chromium flags
## browser-option-channel
- `channel` <[string]>
Browser distribution channel. Supported values are "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", "msedge-canary". Read more about using [Google Chrome and Microsoft Edge](../browsers.md#google-chrome--microsoft-edge).
Browser distribution channel.
Use "chromium" to [opt in to new headless mode](../browsers.md#chromium-new-headless-mode).
Use "chrome", "chrome-beta", "chrome-dev", "chrome-canary", "msedge", "msedge-beta", "msedge-dev", or "msedge-canary" to use branded [Google Chrome and Microsoft Edge](../browsers.md#google-chrome--microsoft-edge).
## browser-option-chromiumsandbox
- `chromiumSandbox` <[boolean]>
@ -982,7 +1063,7 @@ Close the browser process on SIGHUP. Defaults to `true`.
Whether to run browser in headless mode. More details for
[Chromium](https://developers.google.com/web/updates/2017/04/headless-chrome) and
[Firefox](https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Headless_mode). Defaults to `true` unless the
[`option: devtools`] option is `true`.
[`option: BrowserType.launch.devtools`] option is `true`.
## js-python-browser-option-firefoxuserprefs
* langs: js, python
@ -1074,6 +1155,11 @@ Note that outer and inner locators must belong to the same frame. Inner locator
Matches elements that do not contain specified text somewhere inside, possibly in a child or a descendant element. When passed a [string], matching is case-insensitive and searches for a substring.
## locator-option-visible
- `visible` <[boolean]>
Only matches visible or invisible elements.
## locator-options-list-v1.14
- %%-locator-option-has-text-%%
- %%-locator-option-has-%%
@ -1124,6 +1210,7 @@ Specify screenshot type, defaults to `png`.
Specify locators that should be masked when the screenshot is taken. Masked elements will be overlaid with
a pink box `#FF00FF` (customized by [`option: maskColor`]) that completely covers its bounding box.
The mask is also applied to invisible elements, see [Matching only visible elements](../locators.md#matching-only-visible-elements) to disable that.
## screenshot-option-mask-color
* since: v1.35
@ -1426,19 +1513,19 @@ page.get_by_text(re.compile("^hello$", re.IGNORECASE))
```java
// Matches <span>
page.getByText("world")
page.getByText("world");
// Matches first <div>
page.getByText("Hello world")
page.getByText("Hello world");
// Matches second <div>
page.getByText("Hello", new Page.GetByTextOptions().setExact(true))
page.getByText("Hello", new Page.GetByTextOptions().setExact(true));
// Matches both <div>s
page.getByText(Pattern.compile("Hello"))
page.getByText(Pattern.compile("Hello"));
// Matches second <div>
page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE))
page.getByText(Pattern.compile("^hello$", Pattern.CASE_INSENSITIVE));
```
```csharp
@ -1692,7 +1779,9 @@ await Expect(Page.GetByTitle("Issues count")).toHaveText("25 issues");
- `type` ?<[string]>
* langs: js
This option configures a template controlling location of snapshots generated by [`method: PageAssertions.toHaveScreenshot#1`] and [`method: SnapshotAssertions.toMatchSnapshot#1`].
This option configures a template controlling location of snapshots generated by [`method: PageAssertions.toHaveScreenshot#1`], [`method: LocatorAssertions.toMatchAriaSnapshot#2`] and [`method: SnapshotAssertions.toMatchSnapshot#1`].
You can configure templates for each assertion separately in [`property: TestConfig.expect`].
**Usage**
@ -1701,7 +1790,19 @@ import { defineConfig } from '@playwright/test';
export default defineConfig({
testDir: './tests',
// Single template for all assertions
snapshotPathTemplate: '{testDir}/__screenshots__/{testFilePath}/{arg}{ext}',
// Assertion-specific templates
expect: {
toHaveScreenshot: {
pathTemplate: '{testDir}/__screenshots__{/projectName}/{testFilePath}/{arg}{ext}',
},
toMatchAriaSnapshot: {
pathTemplate: '{testDir}/__snapshots__/{testFilePath}/{arg}{ext}',
},
},
});
```
@ -1732,22 +1833,22 @@ test.describe('suite', () => {
The list of supported tokens:
* `{arg}` - Relative snapshot path **without extension**. These come from the arguments passed to the `toHaveScreenshot()` and `toMatchSnapshot()` calls; if called without arguments, this will be an auto-generated snapshot name.
* `{arg}` - Relative snapshot path **without extension**. This comes from the arguments passed to `toHaveScreenshot()`, `toMatchAriaSnapshot()` or `toMatchSnapshot()`; if called without arguments, this will be an auto-generated snapshot name.
* Value: `foo/bar/baz`
* `{ext}` - snapshot extension (with dots)
* `{ext}` - Snapshot extension (with the leading dot).
* Value: `.png`
* `{platform}` - The value of `process.platform`.
* `{projectName}` - Project's file-system-sanitized name, if any.
* Value: `''` (empty string).
* `{snapshotDir}` - Project's [`property: TestConfig.snapshotDir`].
* `{snapshotDir}` - Project's [`property: TestProject.snapshotDir`].
* Value: `/home/playwright/tests` (since `snapshotDir` is not provided in config, it defaults to `testDir`)
* `{testDir}` - Project's [`property: TestConfig.testDir`].
* Value: `/home/playwright/tests` (absolute path is since `testDir` is resolved relative to directory with config)
* `{testDir}` - Project's [`property: TestProject.testDir`].
* Value: `/home/playwright/tests` (absolute path since `testDir` is resolved relative to directory with config)
* `{testFileDir}` - Directories in relative path from `testDir` to **test file**.
* Value: `page`
* `{testFileName}` - Test file name with extension.
* Value: `page-click.spec.ts`
* `{testFilePath}` - Relative path from `testDir` to **test file**
* `{testFilePath}` - Relative path from `testDir` to **test file**.
* Value: `page/page-click.spec.ts`
* `{testName}` - File-system-sanitized test title, including parent describes but excluding file name.
* Value: `suite-test-should-work`

532
docs/src/aria-snapshots.md Normal file
View file

@ -0,0 +1,532 @@
---
id: aria-snapshots
title: "Snapshot testing"
---
import LiteYouTube from '@site/src/components/LiteYouTube';
## Overview
With Playwright's Snapshot testing you can assert the accessibility tree of a page against a predefined snapshot template.
```js
await page.goto('https://playwright.dev/');
await expect(page.getByRole('banner')).toMatchAriaSnapshot(`
- banner:
- heading /Playwright enables reliable end-to-end/ [level=1]
- link "Get started"
- link "Star microsoft/playwright on GitHub"
- link /[\\d]+k\\+ stargazers on GitHub/
`);
```
```python sync
page.goto('https://playwright.dev/')
expect(page.query_selector('banner')).to_match_aria_snapshot("""
- banner:
- heading /Playwright enables reliable end-to-end/ [level=1]
- link "Get started"
- link "Star microsoft/playwright on GitHub"
- link /[\\d]+k\\+ stargazers on GitHub/
""")
```
```python async
await page.goto('https://playwright.dev/')
await expect(page.query_selector('banner')).to_match_aria_snapshot("""
- banner:
- heading /Playwright enables reliable end-to-end/ [level=1]
- link "Get started"
- link "Star microsoft/playwright on GitHub"
- link /[\\d]+k\\+ stargazers on GitHub/
""")
```
```java
page.navigate("https://playwright.dev/");
assertThat(page.locator("banner")).matchesAriaSnapshot("""
- banner:
- heading /Playwright enables reliable end-to-end/ [level=1]
- link "Get started"
- link "Star microsoft/playwright on GitHub"
- link /[\\d]+k\\+ stargazers on GitHub/
""");
```
```csharp
await page.GotoAsync("https://playwright.dev/");
await Expect(page.Locator("banner")).ToMatchAriaSnapshotAsync(@"
- banner:
- heading ""Playwright enables reliable end-to-end testing for modern web apps."" [level=1]
- link ""Get started""
- link ""Star microsoft/playwright on GitHub""
- link /[\\d]+k\\+ stargazers on GitHub/
");
```
<LiteYouTube
id="P4R6hnsE0UY"
title="Getting started with ARIA Snapshots"
/>
## Assertion testing vs Snapshot testing
Snapshot testing and assertion testing serve different purposes in test automation:
### Assertion testing
Assertion testing is a targeted approach where you assert specific values or conditions about elements or components. For instance, with Playwright, [`method: LocatorAssertions.toHaveText`]
verifies that an element contains the expected text, and [`method: LocatorAssertions.toHaveValue`]
confirms that an input field has the expected value.
Assertion tests are specific and generally check the current state of an element or property
against an expected, predefined state.
They work well for predictable, single-value checks but are limited in scope when testing the
broader structure or variations.
**Advantages**
- **Clarity**: The intent of the test is explicit and easy to understand.
- **Specificity**: Tests focus on particular aspects of functionality, making them more robust
against unrelated changes.
- **Debugging**: Failures provide targeted feedback, pointing directly to the problematic aspect.
**Disadvantages**
- **Verbose for complex outputs**: Writing assertions for complex data structures or large outputs
can be cumbersome and error-prone.
- **Maintenance overhead**: As code evolves, manually updating assertions can be time-consuming.
### Snapshot testing
Snapshot testing captures a “snapshot” or representation of the entire
state of an element, component, or data at a given moment, which is then saved for future
comparisons. When re-running tests, the current state is compared to the snapshot, and if there
are differences, the test fails. This approach is especially useful for complex or dynamic
structures, where manually asserting each detail would be too time-consuming. Snapshot testing
is broader and more holistic than assertion testing, allowing you to track more complex changes over time.
**Advantages**
- **Simplifies complex outputs**: For example, testing a UI component's rendered output can be tedious with traditional assertions. Snapshots capture the entire output for easy comparison.
- **Quick Feedback loop**: Developers can easily spot unintended changes in the output.
- **Encourages consistency**: Helps maintain consistent output as code evolves.
**Disadvantages**
- **Over-Reliance**: It can be tempting to accept changes to snapshots without fully understanding
them, potentially hiding bugs.
- **Granularity**: Large snapshots may be hard to interpret when differences arise, especially
if minor changes affect large portions of the output.
- **Suitability**: Not ideal for highly dynamic content where outputs change frequently or
unpredictably.
### When to use
- **Snapshot testing** is ideal for:
- UI testing of whole pages and components.
- Broad structural checks for complex UI components.
- Regression testing for outputs that rarely change structure.
- **Assertion testing** is ideal for:
- Core logic validation.
- Computed value testing.
- Fine-grained tests requiring precise conditions.
By combining snapshot testing for broad, structural checks and assertion testing for specific functionality, you can achieve a well-rounded testing strategy.
## Aria snapshots
In Playwright, aria snapshots provide a YAML representation of the accessibility tree of a page.
These snapshots can be stored and compared later to verify if the page structure remains consistent or meets defined
expectations.
The YAML format describes the hierarchical structure of accessible elements on the page, detailing **roles**, **attributes**, **values**, and **text content**.
The structure follows a tree-like syntax, where each node represents an accessible element, and indentation indicates
nested elements.
Each accessible element in the tree is represented as a YAML node:
```yaml
- role "name" [attribute=value]
```
- **role**: Specifies the ARIA or HTML role of the element (e.g., `heading`, `list`, `listitem`, `button`).
- **"name"**: Accessible name of the element. Quoted strings indicate exact values, `/patterns/` are used for regular expression.
- **[attribute=value]**: Attributes and values, in square brackets, represent specific ARIA attributes, such
as `checked`, `disabled`, `expanded`, `level`, `pressed`, or `selected`.
These values are derived from ARIA attributes or calculated based on HTML semantics. To inspect the accessibility tree
structure of a page, use the [Chrome DevTools Accessibility Pane](https://developer.chrome.com/docs/devtools/accessibility/reference#pane).
## Snapshot matching
The [`method: LocatorAssertions.toMatchAriaSnapshot`] assertion method in Playwright compares the accessible
structure of the locator scope with a predefined aria snapshot template, helping validate the page's state against
testing requirements.
For the following DOM:
```html
<h1>title</h1>
```
You can match it using the following snapshot template:
```js
await expect(page.locator('body')).toMatchAriaSnapshot(`
- heading "title"
`);
```
```python sync
expect(page.locator("body")).to_match_aria_snapshot("""
- heading "title"
""")
```
```python async
await expect(page.locator("body")).to_match_aria_snapshot("""
- heading "title"
""")
```
```java
assertThat(page.locator("body")).matchesAriaSnapshot("""
- heading "title"
""");
```
```csharp
await Expect(page.Locator("body")).ToMatchAriaSnapshotAsync(@"
- heading ""title""
");
```
When matching, the snapshot template is compared to the current accessibility tree of the page:
* If the tree structure matches the template, the test passes; otherwise, it fails, indicating a mismatch between
expected and actual accessibility states.
* The comparison is case-sensitive and collapses whitespace, so indentation and line breaks are ignored.
* The comparison is order-sensitive, meaning the order of elements in the snapshot template must match the order in the
page's accessibility tree.
### Partial matching
You can perform partial matches on nodes by omitting attributes or accessible names, enabling verification of specific
parts of the accessibility tree without requiring exact matches. This flexibility is helpful for dynamic or irrelevant
attributes.
```html
<button>Submit</button>
```
*aria snapshot*
```yaml
- button
```
In this example, the button role is matched, but the accessible name ("Submit") is not specified, allowing the test to
pass regardless of the button's label.
<hr/>
For elements with ARIA attributes like `checked` or `disabled`, omitting these attributes allows partial matching,
focusing solely on role and hierarchy.
```html
<input type="checkbox" checked>
```
*aria snapshot for partial match*
```yaml
- checkbox
```
In this partial match, the `checked` attribute is ignored, so the test will pass regardless of the checkbox state.
<hr/>
Similarly, you can partially match children in lists or groups by omitting specific list items or nested elements.
```html
<ul>
<li>Feature A</li>
<li>Feature B</li>
<li>Feature C</li>
</ul>
```
*aria snapshot for partial match*
```yaml
- list
- listitem: Feature B
```
Partial matches let you create flexible snapshot tests that verify essential page structure without enforcing
specific content or attributes.
### Matching with regular expressions
Regular expressions allow flexible matching for elements with dynamic or variable text. Accessible names and text can
support regex patterns.
```html
<h1>Issues 12</h1>
```
*aria snapshot with regular expression*
```yaml
- heading /Issues \d+/
```
## Generating snapshots
Creating aria snapshots in Playwright helps ensure and maintain your application's structure.
You can generate snapshots in various ways depending on your testing setup and workflow.
### Generating snapshots with the Playwright code generator
If you're using Playwright's [Code Generator](./codegen.md), generating aria snapshots is streamlined with its
interactive interface:
- **"Assert snapshot" Action**: In the code generator, you can use the "Assert snapshot" action to automatically create
a snapshot assertion for the selected elements. This is a quick way to capture the aria snapshot as part of your
recorded test flow.
- **"Aria snapshot" Tab**: The "Aria snapshot" tab within the code generator interface visually represents the
aria snapshot for a selected locator, letting you explore, inspect, and verify element roles, attributes, and
accessible names to aid snapshot creation and review.
### Updating snapshots with `@playwright/test` and the `--update-snapshots` flag
* langs: js
When using the Playwright test runner (`@playwright/test`), you can automatically update snapshots with the `--update-snapshots` flag, `-u` for short.
Running tests with the `--update-snapshots` flag will update snapshots that did not match. Matching snapshots will not be updated.
```bash
npx playwright test --update-snapshots
```
Updating snapshots is useful when application structure changes require new snapshots as a baseline. Note that Playwright will wait for the maximum expect timeout specified in the test runner configuration to ensure the page is settled before taking the snapshot. It might be necessary to adjust the `--timeout` if the test hits the timeout while generating snapshots.
#### Empty template for snapshot generation
Passing an empty string as the template in an assertion generates a snapshot on-the-fly:
```js
await expect(locator).toMatchAriaSnapshot('');
```
Note that Playwright will wait for the maximum expect timeout specified in the test runner configuration to ensure the
page is settled before taking the snapshot. It might be necessary to adjust the `--timeout` if the test hits the timeout
while generating snapshots.
#### Snapshot patch files
When updating snapshots, Playwright creates patch files that capture differences. These patch files can be reviewed,
applied, and committed to source control, allowing teams to track structural changes over time and ensure updates are
consistent with application requirements.
The way source code is updated can be changed using the `--update-source-method` flag. There are several options available:
- **"patch"** (default): Generates a unified diff file that can be applied to the source code using `git apply`.
- **"3way"**: Generates merge conflict markers in your source code, allowing you to choose whether to accept changes.
- **"overwrite"**: Overwrites the source code with the new snapshot values.
```bash
npx playwright test --update-snapshots --update-source-mode=3way
```
#### Snapshots as separate files
To store your snapshots in a separate file, use the `toMatchAriaSnapshot` method with the `name` option, specifying a `.snapshot.yml` file extension.
```js
await expect(page.getByRole('main')).toMatchAriaSnapshot({ name: 'main.snapshot.yml' });
```
By default, snapshots from a test file `example.spec.ts` are placed in the `example.spec.ts-snapshots` directory. As snapshots should be the same across browsers, only one snapshot is saved even if testing with multiple browsers. Should you wish, you can customize the [snapshot path template](./api/class-testconfig#test-config-snapshot-path-template) using the following configuration:
```js
export default defineConfig({
expect: {
toMatchAriaSnapshot: {
pathTemplate: '__snapshots__/{testFilePath}/{arg}{ext}',
},
},
});
```
### Using the `Locator.ariaSnapshot` method
The [`method: Locator.ariaSnapshot`] method allows you to programmatically create a YAML representation of accessible
elements within a locator's scope, especially helpful for generating snapshots dynamically during test execution.
**Example**:
```js
const snapshot = await page.locator('body').ariaSnapshot();
console.log(snapshot);
```
```python sync
snapshot = page.locator("body").aria_snapshot()
print(snapshot)
```
```python async
snapshot = await page.locator("body").aria_snapshot()
print(snapshot)
```
```java
String snapshot = page.locator("body").ariaSnapshot();
System.out.println(snapshot);
```
```csharp
var snapshot = await page.Locator("body").AriaSnapshotAsync();
Console.WriteLine(snapshot);
```
This command outputs the aria snapshot within the specified locator's scope in YAML format, which you can validate
or store as needed.
## Accessibility tree examples
### Headings with level attributes
Headings can include a `level` attribute indicating their heading level.
```html
<h1>Title</h1>
<h2>Subtitle</h2>
```
*aria snapshot*
```yaml
- heading "Title" [level=1]
- heading "Subtitle" [level=2]
```
### Text nodes
Standalone or descriptive text elements appear as text nodes.
```html
<div>Sample accessible name</div>
```
*aria snapshot*
```yaml
- text: Sample accessible name
```
### Inline multiline text
Multiline text, such as paragraphs, is normalized in the aria snapshot.
```html
<p>Line 1<br>Line 2</p>
```
*aria snapshot*
```yaml
- paragraph: Line 1 Line 2
```
### Links
Links display their text or composed content from pseudo-elements.
```html
<a href="#more-info">Read more about Accessibility</a>
```
*aria snapshot*
```yaml
- link "Read more about Accessibility"
```
### Text boxes
Input elements of type `text` show their `value` attribute content.
```html
<input type="text" value="Enter your name">
```
*aria snapshot*
```yaml
- textbox: Enter your name
```
### Lists with items
Ordered and unordered lists include their list items.
```html
<ul aria-label="Main Features">
<li>Feature 1</li>
<li>Feature 2</li>
</ul>
```
*aria snapshot*
```yaml
- list "Main Features":
- listitem: Feature 1
- listitem: Feature 2
```
### Grouped elements
Groups capture nested elements, such as `<details>` elements with summary content.
```html
<details>
<summary>Summary</summary>
<p>Detail content here</p>
</details>
```
*aria snapshot*
```yaml
- group: Summary
```
### Attributes and states
Commonly used ARIA attributes, like `checked`, `disabled`, `expanded`, `level`, `pressed`, and `selected`, represent
control states.
#### Checkbox with `checked` attribute
```html
<input type="checkbox" checked>
```
*aria snapshot*
```yaml
- checkbox [checked]
```
#### Button with `pressed` attribute
```html
<button aria-pressed="true">Toggle</button>
```
*aria snapshot*
```yaml
- button "Toggle" [pressed=true]
```

View file

@ -47,8 +47,9 @@ Create `tests/auth.setup.ts` that will prepare authenticated browser state for a
```js title="tests/auth.setup.ts"
import { test as setup, expect } from '@playwright/test';
import path from 'path';
const authFile = 'playwright/.auth/user.json';
const authFile = path.join(__dirname, '../playwright/.auth/user.json');
setup('authenticate', async ({ page }) => {
// Perform authentication steps. Replace these actions with your own.
@ -113,6 +114,8 @@ test('test', async ({ page }) => {
});
```
Note that you need to delete the stored state when it expires. If you don't need to keep the state between test runs, write the browser state under [`property: TestProject.outputDir`], which is automatically cleaned up before every test run.
### Authenticating in UI mode
* langs: js
@ -229,7 +232,7 @@ await page.goto('https://github.com/login')
# Interact with login form
await page.get_by_label("Username or email address").fill("username")
await page.get_by_label("Password").fill("password")
await page.page.get_by_role("button", name="Sign in").click()
await page.get_by_role("button", name="Sign in").click()
# Continue with the test
```
@ -263,9 +266,9 @@ existing authentication state instead.
Playwright provides a way to reuse the signed-in state in the tests. That way you can log
in only once and then skip the log in step for all of the tests.
Web apps use cookie-based or token-based authentication, where authenticated state is stored as [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) or in [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage). Playwright provides [`method: BrowserContext.storageState`] method that can be used to retrieve storage state from authenticated contexts and then create new contexts with pre-populated state.
Web apps use cookie-based or token-based authentication, where authenticated state is stored as [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies), in [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) or in [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API). Playwright provides [`method: BrowserContext.storageState`] method that can be used to retrieve storage state from authenticated contexts and then create new contexts with prepopulated state.
Cookies and local storage state can be used across different browsers. They depend on your application's authentication model: some apps might require both cookies and local storage.
Cookies, local storage and IndexedDB state can be used across different browsers. They depend on your application's authentication model which may require some combination of cookies, local storage or IndexedDB.
The following code snippet retrieves state from an authenticated context and creates a new context with that state.
@ -580,7 +583,7 @@ test('admin and user', async ({ adminPage, userPage }) => {
### Session storage
Reusing authenticated state covers [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) and [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) based authentication. Rarely, [session storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) is used for storing information associated with the signed-in state. Session storage is specific to a particular domain and is not persisted across page loads. Playwright does not provide API to persist session storage, but the following snippet can be used to save/load session storage.
Reusing authenticated state covers [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies), [local storage](https://developer.mozilla.org/en-US/docs/Web/API/Storage) and [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) based authentication. Rarely, [session storage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage) is used for storing information associated with the signed-in state. Session storage is specific to a particular domain and is not persisted across page loads. Playwright does not provide API to persist session storage, but the following snippet can be used to save/load session storage.
```js
// Get session storage and store as env variable

View file

@ -43,7 +43,7 @@ You can also reuse the signed-in state in the tests with [setup project](./auth.
### Avoid testing third-party dependencies
Only test what you control. Don't try to test links to external sites or third party servers that you do not control. Not only is it time consuming and can slow down your tests but also you can not control the content of the page you are linking to, or if there are cookie banners or overlay pages or anything else that might cause your test to fail.
Only test what you control. Don't try to test links to external sites or third party servers that you do not control. Not only is it time consuming and can slow down your tests but also you cannot control the content of the page you are linking to, or if there are cookie banners or overlay pages or anything else that might cause your test to fail.
Instead, use the [Playwright Network API](/network.md#handle-requests) and guarantee the response needed.
@ -90,7 +90,7 @@ await page
#### Prefer user-facing attributes to XPath or CSS selectors
Your DOM can easily change so having your tests depend on your DOM structure can lead to failing tests. For example consider selecting this button by its CSS classes. Should the designer change something then the class might change breaking your test.
Your DOM can easily change so having your tests depend on your DOM structure can lead to failing tests. For example consider selecting this button by its CSS classes. Should the designer change something then the class might change, thus breaking your test.
```js
@ -112,10 +112,40 @@ Playwright has a [test generator](./codegen.md) that can generate tests and pick
To pick a locator run the `codegen` command followed by the URL that you would like to pick a locator from.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright codegen playwright.dev
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright codegen playwright.dev
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright codegen playwright.dev
```
</TabItem>
</Tabs>
This will open a new browser window as well as the Playwright inspector. To pick a locator first click on the 'Record' button to stop the recording. By default when you run the `codegen` command it will start a new recording. Once you stop the recording the 'Pick Locator' button will be available to click.
You can then hover over any element on your page in the browser window and see the locator highlighted below your cursor. Clicking on an element will add the locator into the Playwright inspector. You can either copy the locator and paste into your test file or continue to explore the locator by editing it in the Playwright Inspector, for example by modifying the text, and seeing the results in the browser window.
@ -170,10 +200,40 @@ You can live debug your test by clicking or editing the locators in your test in
You can also debug your tests with the Playwright inspector by running your tests with the `--debug` flag.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright test --debug
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright test --debug
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright test --debug
```
</TabItem>
</Tabs>
You can then step through your test, view actionability logs and edit the locator live and see it highlighted in the browser window. This will show you which locators match, how many of them there are.
<img width="1350" alt="debugging with the playwright inspector" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212276296-4f5b18e7-2bd7-4766-9aa5-783517bd4aa2.png" />
@ -182,9 +242,39 @@ You can then step through your test, view actionability logs and edit the locato
To debug a specific test add the name of the test file and the line number of the test followed by the `--debug` flag.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright test example.spec.ts:9 --debug
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright test example.spec.ts:9 --debug
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright test example.spec.ts:9 --debug
```
</TabItem>
</Tabs>
#### Debugging on CI
For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of videos and screenshots. The trace viewer gives you a full trace of your tests as a local Progressive Web App (PWA) that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action using dev tools, view network requests and more.
@ -193,18 +283,79 @@ For CI failures, use the Playwright [trace viewer](./trace-viewer.md) instead of
Traces are configured in the Playwright config file and are set to run on CI on the first retry of a failed test. We don't recommend setting this to `on` so that traces are run on every test as it's very performance heavy. However you can run a trace locally when developing with the `--trace` flag.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright test --trace on
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright test --trace on
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright test --trace on
```
</TabItem>
</Tabs>
Once you run this command your traces will be recorded for each test and can be viewed directly from the HTML report.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright show-report
````
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright show-report
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright show-report
```
</TabItem>
</Tabs>
<img width="1516" alt="Playwrights HTML report" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212279022-d929d4c0-2271-486a-a75f-166ac231d25f.png" />
Traces can be opened by clicking on the icon next to the test or by opening each of the test reports and scrolling down to the traces section.
Traces can be opened by clicking on the icon next to the test file name or by opening each of the test reports and scrolling down to the traces section.
<img width="1516" alt="Screenshot 2023-01-13 at 09 58 34" loading="lazy" src="https://user-images.githubusercontent.com/13063165/212279699-c9eb134f-4f4e-4f19-805c-37596d3272a6.png" />
@ -214,8 +365,8 @@ Playwright comes with a range of tooling to help you write tests.
- The [VS Code extension](./getting-started-vscode.md) gives you a great developer experience when writing, running, and debugging tests.
- The [test generator](./codegen.md) can generate tests and pick locators for you.
- The [trace viewer](./trace-viewer.md) gives you a full trace of your tests as a local PWA that can easily be shared. With the trace viewer you can view the timeline, inspect DOM snapshots for each action, view network requests and more.
- The [UI Mode](./test-ui-mode) let's you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test.
- [Typescript](./test-typescript) in Playwright works out of the box and gives you better IDE integrations. Your IDE will show you everything you can do and highlight when you do something wrong. No TypeScript experience is needed and it is not necessary for your code to be in TypeScript, all you need to do is create your tests with a `.ts` extension.
- The [UI Mode](./test-ui-mode) lets you explore, run and debug tests with a time travel experience complete with watch mode. All test files are loaded into the testing sidebar where you can expand each file and describe block to individually run, view, watch and debug each test.
- [TypeScript](./test-typescript) in Playwright works out of the box and gives you better IDE integrations. Your IDE will show you everything you can do and highlight when you do something wrong. No TypeScript experience is needed and it is not necessary for your code to be in TypeScript, all you need to do is create your tests with a `.ts` extension.
### Test across all browsers
@ -246,26 +397,102 @@ export default defineConfig({
By keeping your Playwright version up to date you will be able to test your app on the latest browser versions and catch failures before the latest browser version is released to the public.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npm install -D @playwright/test@latest
```
</TabItem>
<TabItem value="yarn">
```bash
yarn add --dev @playwright/test@latest
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm install --save-dev @playwright/test@latest
```
</TabItem>
</Tabs>
Check the [release notes](./release-notes.md) to see what the latest version is and what changes have been released.
You can see what version of Playwright you have by running the following command.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright --version
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright --version
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright --version
```
</TabItem>
</Tabs>
### Run tests on CI
Setup CI/CD and run your tests frequently. The more often you run your tests the better. Ideally you should run your tests on each commit and pull request. Playwright comes with a [GitHub actions workflow](/ci-intro.md) so that tests will run on CI for you with no setup required. Playwright can also be setup on the [CI environment](/ci.md) of your choice.
Use Linux when running your tests on CI as it is cheaper. Developers can use whatever environment when running locally but use linux on CI.
Use Linux when running your tests on CI as it is cheaper. Developers can use whatever environment when running locally but use linux on CI. Consider setting up [Sharding](./test-sharding.md) to make CI faster.
#### Optimize browser downloads on CI
Only install the browsers that you actually need, especially on CI. For example, if you're only testing with Chromium, install just Chromium.
```bash title=".github/workflows/playwright.yml"
# Instead of installing all browsers
npx playwright install --with-deps
# Install only Chromium
npx playwright install chromium --with-deps
```
This saves both download time and disk space on your CI machines.
### Lint your tests
Linting the tests helps catching errors early. Use [`@typescript-eslint/no-floating-promises`](https://typescript-eslint.io/rules/no-floating-promises/) [ESLint](https://eslint.org) rule to make sure there are no missing awaits before the asynchronous calls to the Playwright API.
We recommend TypeScript and linting with ESLint for your tests to catch errors early. Use [`@typescript-eslint/no-floating-promises`](https://typescript-eslint.io/rules/no-floating-promises/) [ESLint](https://eslint.org) rule to make sure there are no missing awaits before the asynchronous calls to the Playwright API. On your CI you can run `tsc --noEmit` to ensure that functions are called with the right signature.
### Use parallelism and sharding
@ -282,10 +509,40 @@ test('runs in parallel 2', async ({ page }) => { /* ... */ });
Playwright can [shard](./test-parallel.md#shard-tests-between-multiple-machines) a test suite, so that it can be executed on multiple machines.
<Tabs
defaultValue="npm"
values={[
{label: 'npm', value: 'npm'},
{label: 'yarn', value: 'yarn'},
{label: 'pnpm', value: 'pnpm'}
]
}>
<TabItem value="npm">
```bash
npx playwright test --shard=1/3
```
</TabItem>
<TabItem value="yarn">
```bash
yarn playwright test --shard=1/3
```
</TabItem>
<TabItem value="pnpm">
```bash
pnpm exec playwright test --shard=1/3
```
</TabItem>
</Tabs>
## Productivity tips
### Use Soft assertions

View file

@ -230,13 +230,13 @@ Running 1 test using 1 worker
✓ [firefox] example.spec.ts:3:1 basic test (2s)
```
The VS Code test runner runs your tests on the default browser of Chrome. To run on other/multiple browsers click the play button's dropdown from the testing sidebar and choose another profile or modify the default profile by clicking **Select Default Profile** and select the browsers you wish to run your tests on.
With the VS Code extension you can run your tests on different browsers by checking the checkbox next to the browser name in the Playwright sidebar. These names are defined in your Playwright config file under the projects section. The default config when installing Playwright gives you 3 projects, Chromium, Firefox and WebKit. The first project is selected by default.
<img width="1464" alt="selecting browsers" src="https://user-images.githubusercontent.com/13063165/221136731-9d4bc18f-38a4-4adb-997b-5b98c98aec7f.png" />
![Projects section in VS Code extension](https://github.com/microsoft/playwright/assets/13063165/58fedea6-a2b9-4942-b2c7-2f3d482210cf)
Choose a specific profile, various profiles or all profiles to run tests on.
To run tests on multiple projects(browsers), select each project by checking the checkboxes next to the project name.
<img width="1536" alt="choosing default profiles" src="https://user-images.githubusercontent.com/13063165/221669537-e5df8672-f50d-4ff1-96f9-141cd67e12f8.png" />
![Selecting projects to run tests on](https://github.com/microsoft/playwright/assets/13063165/6dc86ef4-6097-481c-9cab-b6e053ec7ea6)
### Run tests on different browsers
* langs: python
@ -338,16 +338,123 @@ dotnet test --settings:webkit.runsettings
For Google Chrome, Microsoft Edge and other Chromium-based browsers, by default, Playwright uses open source Chromium builds. Since the Chromium project is ahead of the branded browsers, when the world is on Google Chrome N, Playwright already supports Chromium N+1 that will be released in Google Chrome and Microsoft Edge a few weeks later.
### Chromium: headless shell
Playwright ships a regular Chromium build for headed operations and a separate [chromium headless shell](https://developer.chrome.com/blog/chrome-headless-shell) for headless mode.
If you are only running tests in headless shell (i.e. the `channel` option is **not** specified), for example on CI, you can avoid downloading the full Chromium browser by passing `--only-shell` during installation.
```bash js
# only running tests headlessly
npx playwright install --with-deps --only-shell
```
```bash java
# only running tests headlessly
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps --only-shell"
```
```bash python
# only running tests headlessly
playwright install --with-deps --only-shell
```
```bash csharp
# only running tests headlessly
pwsh bin/Debug/netX/playwright.ps1 install --with-deps --only-shell
```
### Chromium: new headless mode
You can opt into the new headless mode by using `'chromium'` channel. As [official Chrome documentation puts it](https://developer.chrome.com/blog/chrome-headless-shell):
> New Headless on the other hand is the real Chrome browser, and is thus more authentic, reliable, and offers more features. This makes it more suitable for high-accuracy end-to-end web app testing or browser extension testing.
See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for details.
```js
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'], channel: 'chromium' },
},
],
});
```
```java
import com.microsoft.playwright.*;
public class Example {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().launch(new BrowserType.LaunchOptions().setChannel("chromium"));
Page page = browser.newPage();
// ...
}
}
}
```
```bash python
pytest test_login.py --browser-channel chromium
```
```xml csharp
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<Playwright>
<BrowserName>chromium</BrowserName>
<LaunchOptions>
<Channel>chromium</Channel>
</LaunchOptions>
</Playwright>
</RunSettings>
```
```bash csharp
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=chromium
```
With the new headless mode, you can skip downloading the headless shell during browser installation by using the `--no-shell` option:
```bash js
# only running tests headlessly
npx playwright install --with-deps --no-shell
```
```bash java
# only running tests headlessly
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps --no-shell"
```
```bash python
# only running tests headlessly
playwright install --with-deps --no-shell
```
```bash csharp
# only running tests headlessly
pwsh bin/Debug/netX/playwright.ps1 install --with-deps --no-shell
```
### Google Chrome & Microsoft Edge
While Playwright can download and use the recent Chromium build, it can operate against the branded Google Chrome and Microsoft Edge browsers available on the machine (note that Playwright doesn't install them by default). In particular, the current Playwright version will support Stable and Beta channels of these browsers.
Available channels are `chrome`, `msedge`, `chrome-beta`, `msedge-beta` or `msedge-dev`.
Available channels are `chrome`, `msedge`, `chrome-beta`, `msedge-beta`, `chrome-dev`, `msedge-dev`, `chrome-canary`, `msedge-canary`.
:::warning
Certain Enterprise Browser Policies may impact Playwright's ability to launch and control Google Chrome and Microsoft Edge. Running in an environment with browser policies is outside of the Playwright project's scope.
:::
:::warning
Google Chrome and Microsoft Edge have switched to a [new headless mode](https://developer.chrome.com/docs/chromium/headless) implementation that is closer to a regular headed mode. This differs from [chromium headless shell](https://developer.chrome.com/blog/chrome-headless-shell) that is used in Playwright by default when running headless, so expect different behavior in some cases. See [issue #33566](https://github.com/microsoft/playwright/issues/33566) for details.
:::
```js
import { defineConfig, devices } from '@playwright/test';
@ -401,6 +508,23 @@ pytest test_login.py --browser-channel msedge
dotnet test -- Playwright.BrowserName=chromium Playwright.LaunchOptions.Channel=msedge
```
######
* langs: python
Alternatively when using the library directly, you can specify the browser [`option: BrowserType.launch.channel`] when launching the browser:
```python
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
# Channel can be "chrome", "msedge", "chrome-beta", "msedge-beta" or "msedge-dev".
browser = p.chromium.launch(channel="msedge")
page = browser.new_page()
page.goto("http://playwright.dev")
print(page.title())
browser.close()
```
#### Installing Google Chrome & Microsoft Edge
If Google Chrome or Microsoft Edge is not available on your machine, you can install
@ -459,9 +583,13 @@ Google Chrome and Microsoft Edge respect enterprise policies, which include limi
Playwright's Firefox version matches the recent [Firefox Stable](https://www.mozilla.org/en-US/firefox/new/) build. Playwright doesn't work with the branded version of Firefox since it relies on patches.
Note that availability of certain features, which depend heavily on the underlying platform, may vary between operating systems. For example, available media codecs vary substantially between Linux, macOS and Windows.
### WebKit
Playwright's WebKit version matches the recent WebKit trunk build, before it is used in Apple Safari and other WebKit-based browsers. This gives a lot of lead time to react on the potential browser update issues. Playwright doesn't work with the branded version of Safari since it relies on patches. Instead you can test against the recent WebKit build.
Playwright's WebKit is derived from the latest WebKit main branch sources, often before these updates are incorporated into Apple Safari and other WebKit-based browsers. This gives a lot of lead time to react on the potential browser update issues. Playwright doesn't work with the branded version of Safari since it relies on patches. Instead, you can test using the most recent WebKit build.
Note that availability of certain features, which depend heavily on the underlying platform, may vary between operating systems. For example, available media codecs vary substantially between Linux, macOS and Windows. While running WebKit on Linux CI is usually the most affordable option, for the closest-to-Safari experience you should run WebKit on mac, for example if you do video playback.
## Install behind a firewall or a proxy
@ -763,7 +891,7 @@ pwsh bin/Debug/netX/playwright.ps1 install
Playwright downloads Chromium, WebKit and Firefox browsers into the OS-specific cache folders:
- `%USERPROFILE%\AppData\Local\ms-playwright` on Windows
- `~/Library/Caches/ms-playwright` on MacOS
- `~/Library/Caches/ms-playwright` on macOS
- `~/.cache/ms-playwright` on Linux
These browsers will take a few hundred megabytes of disk space when installed:

View file

@ -9,7 +9,9 @@ title: "Chrome extensions"
Extensions only work in Chrome / Chromium launched with a persistent context. Use custom browser args at your own risk, as some of them may break Playwright functionality.
:::
The following is code for getting a handle to the [background page](https://developer.chrome.com/extensions/background_pages) of a [Manifest v2](https://developer.chrome.com/docs/extensions/mv2/) extension whose source is located in `./my-extension`:
The snippet below retrieves the [background page](https://developer.chrome.com/extensions/background_pages) of a [Manifest v2](https://developer.chrome.com/docs/extensions/mv2/) extension whose source is located in `./my-extension`.
Note the use of the `chromium` channel that allows to run extensions in headless mode. Alternatively, you can launch the browser in headed mode.
```js
const { chromium } = require('playwright');
@ -18,7 +20,7 @@ const { chromium } = require('playwright');
const pathToExtension = require('path').join(__dirname, 'my-extension');
const userDataDir = '/tmp/test-user-data-dir';
const browserContext = await chromium.launchPersistentContext(userDataDir, {
headless: false,
channel: 'chromium',
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`
@ -44,7 +46,7 @@ user_data_dir = "/tmp/test-user-data-dir"
async def run(playwright: Playwright):
context = await playwright.chromium.launch_persistent_context(
user_data_dir,
headless=False,
channel="chromium",
args=[
f"--disable-extensions-except={path_to_extension}",
f"--load-extension={path_to_extension}",
@ -78,7 +80,7 @@ user_data_dir = "/tmp/test-user-data-dir"
def run(playwright: Playwright):
context = playwright.chromium.launch_persistent_context(
user_data_dir,
headless=False,
channel="chromium",
args=[
f"--disable-extensions-except={path_to_extension}",
f"--load-extension={path_to_extension}",
@ -101,6 +103,8 @@ with sync_playwright() as playwright:
To have the extension loaded when running tests you can use a test fixture to set the context. You can also dynamically retrieve the extension id and use it to load and test the popup page for example.
Note the use of the `chromium` channel that allows to run extensions in headless mode. Alternatively, you can launch the browser in headed mode.
First, add fixtures that will load the extension:
```js title="fixtures.ts"
@ -114,7 +118,7 @@ export const test = base.extend<{
context: async ({ }, use) => {
const pathToExtension = path.join(__dirname, 'my-extension');
const context = await chromium.launchPersistentContext('', {
headless: false,
channel: 'chromium',
args: [
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
@ -155,7 +159,7 @@ def context(playwright: Playwright) -> Generator[BrowserContext, None, None]:
path_to_extension = Path(__file__).parent.joinpath("my-extension")
context = playwright.chromium.launch_persistent_context(
"",
headless=False,
channel="chromium",
args=[
f"--disable-extensions-except={path_to_extension}",
f"--load-extension={path_to_extension}",
@ -211,39 +215,3 @@ def test_popup_page(page: Page, extension_id: str) -> None:
page.goto(f"chrome-extension://{extension_id}/popup.html")
expect(page.locator("body")).to_have_text("my-extension popup")
```
## Headless mode
:::danger
`headless=new` mode is not officially supported by Playwright and might result in unexpected behavior.
:::
By default, Chrome's headless mode in Playwright does not support Chrome extensions. To overcome this limitation, you can run Chrome's persistent context with a new headless mode by using the following code:
```js title="fixtures.ts"
// ...
const pathToExtension = path.join(__dirname, 'my-extension');
const context = await chromium.launchPersistentContext('', {
headless: false,
args: [
`--headless=new`,
`--disable-extensions-except=${pathToExtension}`,
`--load-extension=${pathToExtension}`,
],
});
// ...
```
```python title="conftest.py"
path_to_extension = Path(__file__).parent.joinpath("my-extension")
context = playwright.chromium.launch_persistent_context(
"",
headless=False,
args=[
"--headless=new",
f"--disable-extensions-except={path_to_extension}",
f"--load-extension={path_to_extension}",
],
)
```

View file

@ -1,19 +1,17 @@
---
id: ci-intro
title: "CI GitHub Actions"
title: "Setting up CI"
---
## Introduction
* langs: js
Playwright tests can be run on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed [doc on Continuous Integration](./ci.md).
When [installing Playwright](./intro.md) using the [VS Code extension](./getting-started-vscode.md) or with `npm init playwright@latest` you are given the option to add a [GitHub Actions](https://docs.github.com/en/actions) workflow. This creates a `playwright.yml` file inside a `.github/workflows` folder containing everything you need so that your tests run on each push and pull request into the main/master branch.
Playwright tests can be run on any CI provider. This guide covers one way of running tests on GitHub using GitHub actions. If you would like to learn more, or how to configure other CI providers, check out our detailed [doc on Continuous Integration](./ci.md).
#### You will learn
* langs: js
- [How to run tests on push/pull_request](/ci-intro.md#on-pushpull_request)
- [How to set up GitHub Actions](/ci-intro.md#setting-up-github-actions)
- [How to view test logs](/ci-intro.md#viewing-test-logs)
- [How to view the HTML report](/ci-intro.md#viewing-the-html-report)
- [How to view the trace](/ci-intro.md#viewing-the-trace)
@ -23,24 +21,20 @@ When [installing Playwright](./intro.md) using the [VS Code extension](./getting
## Introduction
* langs: python, java, csharp
Playwright tests can be ran on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed doc on Continuous Integration.
To add a [GitHub Actions](https://docs.github.com/en/actions) file first create `.github/workflows` folder and inside it add a `playwright.yml` file containing the example code below so that your tests will run on each push and pull request for the main/master branch.
Playwright tests can be run on any CI provider. In this section we will cover running tests on GitHub using GitHub actions. If you would like to see how to configure other CI providers check out our detailed doc on Continuous Integration.
#### You will learn
* langs: python, java, csharp
- [How to run tests on push/pull_request](/ci-intro.md#on-pushpull_request)
- [How to set up GitHub Actions](/ci-intro.md#setting-up-github-actions)
- [How to view test logs](/ci-intro.md#viewing-test-logs)
- [How to view the trace](/ci-intro.md#viewing-the-trace)
## Setting up GitHub Actions
### On push/pull_request
* langs: js
Tests will run on push or pull request on branches main/master. The [workflow](https://docs.github.com/en/actions/using-workflows/about-workflows) will install all dependencies, install Playwright and then run the tests. It will also create the HTML report.
When [installing Playwright](./intro.md) using the [VS Code extension](./getting-started-vscode.md) or with `npm init playwright@latest` you are given the option to add a [GitHub Actions](https://docs.github.com/en/actions) workflow. This creates a `playwright.yml` file inside a `.github/workflows` folder containing everything you need so that your tests run on each push and pull request into the main/master branch. Here's how that file looks:
```yml js title=".github/workflows/playwright.yml"
name: Playwright Tests
@ -57,7 +51,7 @@ jobs:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
@ -72,10 +66,21 @@ jobs:
retention-days: 30
```
### On push/pull_request
The workflow performs these steps:
1. Clone your repository
2. Install Node.js
3. Install NPM Dependencies
4. Install Playwright Browsers
5. Run Playwright tests
6. Upload HTML report to the GitHub UI
To learn more about this, see ["Understanding GitHub Actions"](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions).
## Setting up GitHub Actions
* langs: python, java, csharp
Tests will run on push or pull request on branches main/master. The [workflow](https://docs.github.com/en/actions/using-workflows/about-workflows) will install all dependencies, install Playwright and then run the tests.
To add a [GitHub Actions](https://docs.github.com/en/actions) file first create `.github/workflows` folder and inside it add a `playwright.yml` file containing the example code below so that your tests will run on each push and pull request for the main/master branch.
```yml python title=".github/workflows/playwright.yml"
name: Playwright Tests
@ -128,7 +133,7 @@ jobs:
java-version: '17'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Install Playwright
- name: Ensure browsers are installed
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
- name: Run tests
run: mvn test
@ -151,238 +156,23 @@ jobs:
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- run: dotnet build
- name: Build & Install
run: dotnet build
- name: Ensure browsers are installed
run: pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps
- name: Run your tests
run: dotnet test
```
### On push/pull_request (sharded)
* langs: js
To learn more about this, see ["Understanding GitHub Actions"](https://docs.github.com/en/actions/learn-github-actions/understanding-github-actions).
GitHub Actions supports [sharding tests between multiple jobs](https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs). Check out our [sharding doc](./test-sharding) to learn more about sharding and to see a [GitHub actions example](./test-sharding.md#github-actions-example) of how to configure a job to run your tests on multiple machines as well as how to merge the HTML reports.
### Via Containers
GitHub Actions support [running jobs in a container](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container) by using the [`jobs.<job_id>.container`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idcontainer) option. This is useful to not pollute the host environment with dependencies and to have a consistent environment for e.g. screenshots/visual regression testing across different operating systems.
```yml js title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Run your tests
run: npx playwright test
env:
HOME: /root
```
```yml python title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r local-requirements.txt
pip install -e .
- name: Run your tests
run: pytest
env:
HOME: /root
```
```yml java title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Run tests
run: mvn test
env:
HOME: /root
```
```yml csharp title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- run: dotnet build
- name: Run your tests
run: dotnet test
env:
HOME: /root
```
### On deployment
This will start the tests after a [GitHub Deployment](https://developer.github.com/v3/repos/deployments/) went into the `success` state.
Services like Vercel use this pattern so you can run your end-to-end tests on their deployed environment.
```yml js title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
env:
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
```yml python title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Ensure browsers are installed
run: python -m playwright install --with-deps
- name: Run tests
run: pytest
env:
# This might depend on your test-runner
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
```yml java title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Install Playwright
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
- name: Run tests
run: mvn test
env:
# This might depend on your test-runner
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
```yml csharp title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- run: dotnet build
- name: Ensure browsers are installed
run: pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps
- name: Run tests
run: dotnet test
env:
# This might depend on your test-runner
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
Looking at the list of steps in `jobs.test.steps`, you can see that the workflow performs these steps:
1. Clone your repository
2. Install language dependencies
3. Install project dependencies and build
4. Install Playwright Browsers
5. Run tests
## Create a Repo and Push to GitHub
@ -532,4 +322,5 @@ This step will not work for pull requests created from a forked repository becau
- [Learn how to perform Actions](./input.md)
- [Learn how to write Assertions](./test-assertions.md)
- [Learn more about the Trace Viewer](/trace-viewer.md)
- [Learn more ways of running tests on GitHub Actions](/ci.md#github-actions)
- [Learn more about running tests on other CI providers](/ci.md)

View file

@ -59,22 +59,406 @@ export default defineConfig({
});
```
## CI configurations
The [Command line tools](./browsers#install-system-dependencies) can be used to install all operating system dependencies on GitHub Actions.
The [Command line tools](./browsers#install-system-dependencies) can be used to install all operating system dependencies in CI.
### GitHub Actions
Check out our [GitHub Actions](ci-intro.md) guide for more information on how to run your tests on GitHub.
#### On push/pull_request
* langs: js
Tests will run on push or pull request on branches main/master. The [workflow](https://docs.github.com/en/actions/using-workflows/about-workflows) will install all dependencies, install Playwright and then run the tests. It will also create the HTML report.
```yml js title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
```
#### On push/pull_request
* langs: python, java, csharp
Tests will run on push or pull request on branches main/master. The [workflow](https://docs.github.com/en/actions/using-workflows/about-workflows) will install all dependencies, install Playwright and then run the tests.
```yml python title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Ensure browsers are installed
run: python -m playwright install --with-deps
- name: Run your tests
run: pytest --tracing=retain-on-failure
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-traces
path: test-results/
```
```yml java title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Ensure browsers are installed
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
- name: Run tests
run: mvn test
```
```yml csharp title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Build & Install
run: dotnet build
- name: Ensure browsers are installed
run: pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps
- name: Run your tests
run: dotnet test
```
#### On push/pull_request (sharded)
* langs: js
GitHub Actions supports [sharding tests between multiple jobs](https://docs.github.com/en/actions/using-jobs/using-a-matrix-for-your-jobs). Check out our [sharding doc](./test-sharding) to learn more about sharding and to see a [GitHub actions example](./test-sharding.md#github-actions-example) of how to configure a job to run your tests on multiple machines as well as how to merge the HTML reports.
#### Via Containers
GitHub Actions support [running jobs in a container](https://docs.github.com/en/actions/using-jobs/running-jobs-in-a-container) by using the [`jobs.<job_id>.container`](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idcontainer) option. This is useful to not pollute the host environment with dependencies and to have a consistent environment for e.g. screenshots/visual regression testing across different operating systems.
```yml js title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
options: --user 1001
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Run your tests
run: npx playwright test
```
```yml python title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/python:v%%VERSION%%-noble
options: --user 1001
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r local-requirements.txt
pip install -e .
- name: Run your tests
run: pytest
```
```yml java title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/java:v%%VERSION%%-noble
options: --user 1001
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Run tests
run: mvn test
```
```yml csharp title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
playwright:
name: 'Playwright Tests'
runs-on: ubuntu-latest
container:
image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble
options: --user 1001
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- run: dotnet build
- name: Run your tests
run: dotnet test
```
#### On deployment
This will start the tests after a [GitHub Deployment](https://developer.github.com/v3/repos/deployments/) went into the `success` state.
Services like Vercel use this pattern so you can run your end-to-end tests on their deployed environment.
```yml js title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright
run: npx playwright install --with-deps
- name: Run Playwright tests
run: npx playwright test
env:
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
```yml python title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Ensure browsers are installed
run: python -m playwright install --with-deps
- name: Run tests
run: pytest
env:
# This might depend on your test-runner
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
```yml java title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '17'
- name: Build & Install
run: mvn -B install -D skipTests --no-transfer-progress
- name: Install Playwright
run: mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="install --with-deps"
- name: Run tests
run: mvn test
env:
# This might depend on your test-runner
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
```yml csharp title=".github/workflows/playwright.yml"
name: Playwright Tests
on:
deployment_status:
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
if: github.event.deployment_status.state == 'success'
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- run: dotnet build
- name: Ensure browsers are installed
run: pwsh bin/Debug/net8.0/playwright.ps1 install --with-deps
- name: Run tests
run: dotnet test
env:
# This might depend on your test-runner
PLAYWRIGHT_TEST_BASE_URL: ${{ github.event.deployment_status.target_url }}
```
#### Fail-Fast
* langs: js
Large test suites can take very long to execute. By executing a preliminary test run with the `--only-changed` flag, you can run test files that are likely to fail first.
This will give you a faster feedback loop and slightly lower CI consumption while working on Pull Requests.
To detect test files affected by your changeset, `--only-changed` analyses your suites' dependency graph. This is a heuristic and might miss tests, so it's important that you always run the full test suite after the preliminary test run.
```yml js title=".github/workflows/playwright.yml" {24-26}
name: Playwright Tests
on:
push:
branches: [ main, master ]
pull_request:
branches: [ main, master ]
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# Force a non-shallow checkout, so that we can reference $GITHUB_BASE_REF.
# See https://github.com/actions/checkout for more details.
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install dependencies
run: npm ci
- name: Install Playwright Browsers
run: npx playwright install --with-deps
- name: Run changed Playwright tests
run: npx playwright test --only-changed=$GITHUB_BASE_REF
if: github.event_name == 'pull_request'
- name: Run Playwright tests
run: npx playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 30
```
### Docker
We have a [pre-built Docker image](./docker.md) which can either be used directly, or as a reference to update your existing Docker definitions.
We have a [pre-built Docker image](./docker.md) which can either be used directly or as a reference to update your existing Docker definitions.
Suggested configuration
1. Using `--ipc=host` is also recommended when using Chromium. Without it Chromium can run out of memory
and crash. Learn more about this option in [Docker docs](https://docs.docker.com/engine/reference/run/#ipc-settings---ipc).
and crash. Learn more about this option in [Docker docs](https://docs.docker.com/reference/cli/docker/container/run/#ipc).
1. Seeing other weird errors when launching Chromium? Try running your container
with `docker run --cap-add=SYS_ADMIN` when developing locally.
1. Using `--init` Docker flag or [dumb-init](https://github.com/Yelp/dumb-init) is recommended to avoid special
@ -82,7 +466,7 @@ Suggested configuration
### Azure Pipelines
For Windows or macOS agents, no additional configuration required, just install Playwright and run your tests.
For Windows or macOS agents, no additional configuration is required, just install Playwright and run your tests.
For Linux agents, you can use [our Docker container](./docker.md) with Azure
Pipelines support [running containerized
@ -296,7 +680,7 @@ trigger:
pool:
vmImage: ubuntu-latest
container: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
container: mcr.microsoft.com/playwright:v%%VERSION%%-noble
steps:
- task: NodeTool@0
@ -318,7 +702,7 @@ trigger:
pool:
vmImage: ubuntu-latest
container: mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy
container: mcr.microsoft.com/playwright/python:v%%VERSION%%-noble
steps:
- task: UsePythonVersion@0
@ -340,7 +724,7 @@ trigger:
pool:
vmImage: ubuntu-latest
container: mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy
container: mcr.microsoft.com/playwright/java:v%%VERSION%%-noble
steps:
- task: JavaToolInstaller@0
@ -361,7 +745,7 @@ trigger:
pool:
vmImage: ubuntu-latest
container: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy
container: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble
steps:
- task: UseDotNet@2
@ -382,30 +766,30 @@ Running Playwright on CircleCI is very similar to running on GitHub Actions. In
```yml js
executors:
pw-jammy-development:
pw-noble-development:
docker:
- image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
- image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
```
```yml python
executors:
pw-jammy-development:
pw-noble-development:
docker:
- image: mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy
- image: mcr.microsoft.com/playwright/python:v%%VERSION%%-noble
```
```yml java
executors:
pw-jammy-development:
pw-noble-development:
docker:
- image: mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy
- image: mcr.microsoft.com/playwright/java:v%%VERSION%%-noble
```
```yml csharp
executors:
pw-jammy-development:
pw-noble-development:
docker:
- image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy
- image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble
```
Note: When using the docker agent definition, you are specifying the resource class of where playwright runs to the 'medium' tier [here](https://circleci.com/docs/configuration-reference?#docker-execution-environment). The default behavior of Playwright is to set the number of workers to the detected core count (2 in the case of the medium tier). Overriding the number of workers to greater than this number will cause unnecessary timeouts and failures.
@ -417,10 +801,10 @@ Sharding in CircleCI is indexed with 0 which means that you will need to overrid
```yml
playwright-job-name:
executor: pw-jammy-development
executor: pw-noble-development
parallelism: 4
steps:
- run: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npx playwright test -- --shard=${SHARD}/${CIRCLE_NODE_TOTAL}
- run: SHARD="$((${CIRCLE_NODE_INDEX}+1))"; npx playwright test --shard=${SHARD}/${CIRCLE_NODE_TOTAL}
```
### Jenkins
@ -430,7 +814,7 @@ to run tests on Jenkins.
```groovy js
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright:v%%VERSION%%-jammy' } }
agent { docker { image 'mcr.microsoft.com/playwright:v%%VERSION%%-noble' } }
stages {
stage('e2e-tests') {
steps {
@ -444,7 +828,7 @@ pipeline {
```groovy python
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy' } }
agent { docker { image 'mcr.microsoft.com/playwright/python:v%%VERSION%%-noble' } }
stages {
stage('e2e-tests') {
steps {
@ -458,7 +842,7 @@ pipeline {
```groovy java
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy' } }
agent { docker { image 'mcr.microsoft.com/playwright/java:v%%VERSION%%-noble' } }
stages {
stage('e2e-tests') {
steps {
@ -472,7 +856,7 @@ pipeline {
```groovy csharp
pipeline {
agent { docker { image 'mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy' } }
agent { docker { image 'mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble' } }
stages {
stage('e2e-tests') {
steps {
@ -489,19 +873,19 @@ pipeline {
Bitbucket Pipelines can use public [Docker images as build environments](https://confluence.atlassian.com/bitbucket/use-docker-images-as-build-environments-792298897.html). To run Playwright tests on Bitbucket, use our public Docker image ([see Dockerfile](./docker.md)).
```yml js
image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
```
```yml python
image: mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright/python:v%%VERSION%%-noble
```
```yml java
image: mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright/java:v%%VERSION%%-noble
```
```yml csharp
image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble
```
### GitLab CI
@ -514,7 +898,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
script:
...
```
@ -525,7 +909,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright/python:v%%VERSION%%-noble
script:
...
```
@ -536,7 +920,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright/java:v%%VERSION%%-noble
script:
...
```
@ -547,7 +931,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble
script:
...
```
@ -563,7 +947,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
parallel: 7
script:
- npm ci
@ -578,7 +962,7 @@ stages:
tests:
stage: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
parallel:
matrix:
- PROJECT: ['chromium', 'webkit']
@ -594,13 +978,30 @@ To run Playwright tests on Google Cloud Build, use our public Docker image ([see
```yml
steps:
- name: mcr.microsoft.com/playwright:v%%VERSION%%-jammy
- name: mcr.microsoft.com/playwright:v%%VERSION%%-noble
script:
...
env:
- 'CI=true'
```
### Drone
* langs: js
To run Playwright tests on Drone, use our public Docker image ([see Dockerfile](./docker.md)).
```yml
kind: pipeline
name: default
type: docker
steps:
- name: test
image: mcr.microsoft.com/playwright:v%%VERSION%%-noble
commands:
- npx playwright test
```
## Caching browsers
Caching browser binaries is not recommended, since the amount of time it takes to restore the cache is comparable to the time it takes to download the binaries. Especially under Linux, [operating system dependencies](./browsers.md#install-system-dependencies) need to be installed, which are not cacheable.
@ -633,7 +1034,7 @@ By default, Playwright launches browsers in headless mode. See in our [Running t
On Linux agents, headed execution requires [Xvfb](https://en.wikipedia.org/wiki/Xvfb) to be installed. Our [Docker image](./docker.md) and GitHub Action have Xvfb pre-installed. To run browsers in headed mode with Xvfb, add `xvfb-run` before the actual command.
```bash js
xvfb-run npx playwrght test
xvfb-run npx playwright test
```
```bash python
xvfb-run pytest

View file

@ -2,11 +2,24 @@
id: clock
title: "Clock"
---
import LiteYouTube from '@site/src/components/LiteYouTube';
## Introduction
Accurately simulating time-dependent behavior is essential for verifying the correctness of applications. Utilizing [Clock] functionality allows developers to manipulate and control time within tests, enabling the precise validation of features such as rendering time, timeouts, scheduled tasks without the delays and variability of real-time execution.
The [Clock] API provides the following methods to control time:
- `setFixedTime`: Sets the fixed time for `Date.now()` and `new Date()`.
- `install`: initializes the clock and allows you to:
- `pauseAt`: Pauses the time at a specific time.
- `fastForward`: Fast forwards the time.
- `runFor`: Runs the time for a specific duration.
- `resume`: Resumes the time.
- `setSystemTime`: Sets the current system time.
The recommended approach is to use `setFixedTime` to set the time to a specific value. If that doesn't work for your use case, you can use `install` which allows you to pause time later on, fast forward it, tick it, etc. `setSystemTime` is only recommended for advanced use cases.
:::note
[`property: Page.clock`] overrides native global classes and functions related to time allowing them to be manually controlled:
- `Date`
- `setTimeout`
@ -18,6 +31,12 @@ Accurately simulating time-dependent behavior is essential for verifying the cor
- `requestIdleCallback`
- `cancelIdleCallback`
- `performance`
- `Event.timeStamp`
:::
:::warning
If you call `install` at any point in your test, the call _MUST_ occur before any other clock related calls (see note above for list). Calling these methods out of order will result in undefined behavior. For example, you cannot call `setInterval`, followed by `install`, then `clearInterval`, as `install` overrides the native definition of the clock functions.
:::
## Test with predefined time
@ -29,7 +48,7 @@ That way the time flows naturally, but `Date.now` always returns a fixed value.
<script>
const renderTime = () => {
document.getElementById('current-time').textContent =
new Date().toLocaleTimeString();
new Date().toLocaleString();
};
setInterval(renderTime, 1000);
</script>
@ -55,7 +74,7 @@ In this case, you can install the clock and fast forward to the time of interest
<script>
const renderTime = () => {
document.getElementById('current-time').textContent =
new Date().toLocaleTimeString();
new Date().toLocaleString();
};
setInterval(renderTime, 1000);
</script>
@ -118,13 +137,14 @@ expect(page.get_by_test_id("current-time")).to_have_text("2/2/2024, 10:30:00 AM"
```java
// Initialize clock with some time before the test time and let the page load
// naturally. `Date.now` will progress as the timers fire.
page.clock().install(new Clock.InstallOptions().setTime(Instant.parse("2024-02-02T08:00:00")));
SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
page.clock().install(new Clock.InstallOptions().setTime(format.parse("2024-02-02T08:00:00")));
page.navigate("http://localhost:3333");
Locator locator = page.getByTestId("current-time");
// Pretend that the user closed the laptop lid and opened it again at 10am.
// Pause the time once reached that point.
page.clock().pauseAt(Instant.parse("2024-02-02T10:00:00"));
page.clock().pauseAt(format.parse("2024-02-02T10:00:00"));
// Assert the page state.
assertThat(locator).hasText("2/2/2024, 10:00:00 AM");
@ -137,9 +157,9 @@ assertThat(locator).hasText("2/2/2024, 10:30:00 AM");
```csharp
// Initialize clock with some time before the test time and let the page load naturally.
// `Date.now` will progress as the timers fire.
await Page.Clock.InstallAsync(new
await Page.Clock.InstallAsync(new()
{
Time = new DateTime(2024, 2, 2, 8, 0, 0)
TimeDate = new DateTime(2024, 2, 2, 8, 0, 0)
});
await Page.GotoAsync("http://localhost:3333");
@ -148,11 +168,11 @@ await Page.GotoAsync("http://localhost:3333");
await Page.Clock.PauseAtAsync(new DateTime(2024, 2, 2, 10, 0, 0));
// Assert the page state.
await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:00:00 AM");
await Expect(Page.GetByTestId("current-time")).ToHaveTextAsync("2/2/2024, 10:00:00 AM");
// Close the laptop lid again and open it at 10:30am.
await Page.Clock.FastForwardAsync("30:00");
await Expect(Page.GetByTestId("current-time")).ToHaveText("2/2/2024, 10:30:00 AM");
await Expect(Page.GetByTestId("current-time")).ToHaveTextAsync("2/2/2024, 10:30:00 AM");
```
## Test inactivity monitoring
@ -161,6 +181,26 @@ Inactivity monitoring is a common feature in web applications that logs out user
Testing this feature can be tricky because you need to wait for a long time to see the effect.
With the help of the clock, you can speed up time and test this feature quickly.
```html
<div id="remaining-time" data-testid="remaining-time"></div>
<script>
const endTime = Date.now() + 5 * 60_000;
const renderTime = () => {
const diffInSeconds = Math.round((endTime - Date.now()) / 1000);
if (diffInSeconds <= 0) {
document.getElementById('remaining-time').textContent =
'You have been logged out due to inactivity.';
} else {
document.getElementById('remaining-time').textContent =
`You will be logged out in ${diffInSeconds} seconds.`;
}
setTimeout(renderTime, 1000);
};
renderTime();
</script>
<button type="button">Interaction</button>
```
```js
// Initial time does not matter for the test, so we can pick current time.
await page.clock.install();
@ -171,7 +211,7 @@ await page.getByRole('button').click();
// Fast forward time 5 minutes as if the user did not do anything.
// Fast forward is like closing the laptop lid and opening it after 5 minutes.
// All the timers due will fire once immediately, as in the real browser.
await page.clock.fastForward('5:00');
await page.clock.fastForward('05:00');
// Check that the user was logged out automatically.
await expect(page.getByText('You have been logged out due to inactivity.')).toBeVisible();
@ -187,7 +227,7 @@ await page.get_by_role("button").click()
# Fast forward time 5 minutes as if the user did not do anything.
# Fast forward is like closing the laptop lid and opening it after 5 minutes.
# All the timers due will fire once immediately, as in the real browser.
await page.clock.fast_forward("5:00")
await page.clock.fast_forward("05:00")
# Check that the user was logged out automatically.
await expect(page.getByText("You have been logged out due to inactivity.")).toBeVisible()
@ -203,7 +243,7 @@ page.get_by_role("button").click()
# Fast forward time 5 minutes as if the user did not do anything.
# Fast forward is like closing the laptop lid and opening it after 5 minutes.
# All the timers due will fire once immediately, as in the real browser.
page.clock.fast_forward("5:00")
page.clock.fast_forward("05:00")
# Check that the user was logged out automatically.
expect(page.get_by_text("You have been logged out due to inactivity.")).to_be_visible()
@ -221,7 +261,7 @@ locator.click();
// Fast forward time 5 minutes as if the user did not do anything.
// Fast forward is like closing the laptop lid and opening it after 5 minutes.
// All the timers due will fire once immediately, as in the real browser.
page.clock().fastForward("5:00");
page.clock().fastForward("05:00");
// Check that the user was logged out automatically.
assertThat(page.getByText("You have been logged out due to inactivity.")).isVisible();
@ -238,7 +278,7 @@ await page.GetByRole("button").ClickAsync();
// Fast forward time 5 minutes as if the user did not do anything.
// Fast forward is like closing the laptop lid and opening it after 5 minutes.
// All the timers due will fire once immediately, as in the real browser.
await Page.Clock.FastForwardAsync("5:00");
await Page.Clock.FastForwardAsync("05:00");
// Check that the user was logged out automatically.
await Expect(Page.GetByText("You have been logged out due to inactivity.")).ToBeVisibleAsync();
@ -254,7 +294,7 @@ animation frames in the process to achieve a fine-grained control over the passa
<script>
const renderTime = () => {
document.getElementById('current-time').textContent =
new Date().toLocaleTimeString();
new Date().toLocaleString();
};
setInterval(renderTime, 1000);
</script>
@ -315,15 +355,16 @@ expect(locator).to_have_text("2/2/2024, 10:00:02 AM")
```
```java
SimpleDateFormat format = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss");
// Initialize clock with a specific time, let the page load naturally.
page.clock().install(new Clock.InstallOptions()
.setTime(Instant.parse("2024-02-02T08:00:00")));
.setTime(format.parse("2024-02-02T08:00:00")));
page.navigate("http://localhost:3333");
Locator locator = page.getByTestId("current-time");
// Pause the time flow, stop the timers, you now have manual control
// over the page time.
page.clock().pauseAt(Instant.parse("2024-02-02T10:00:00"));
page.clock().pauseAt(format.parse("2024-02-02T10:00:00"));
assertThat(locator).hasText("2/2/2024, 10:00:00 AM");
// Tick through time manually, firing all timers in the process.
@ -334,9 +375,9 @@ assertThat(locator).hasText("2/2/2024, 10:00:02 AM");
```csharp
// Initialize clock with a specific time, let the page load naturally.
await Page.Clock.InstallAsync(new
await Page.Clock.InstallAsync(new()
{
Time = new DateTime(2024, 2, 2, 8, 0, 0, DateTimeKind.Pst)
TimeDate = new DateTime(2024, 2, 2, 8, 0, 0, DateTimeKind.Pst)
});
await page.GotoAsync("http://localhost:3333");
var locator = page.GetByTestId("current-time");
@ -351,3 +392,10 @@ await Expect(locator).ToHaveTextAsync("2/2/2024, 10:00:00 AM");
await Page.Clock.RunForAsync(2000);
await Expect(locator).ToHaveTextAsync("2/2/2024, 10:00:02 AM");
```
## Related Videos
<LiteYouTube
id="54_aC-rVKHg"
title="Playwright 1.45"
/>

View file

@ -21,7 +21,7 @@ Install the VS Code extension and generate tests directly from VS Code. The exte
### Record a New Test
To record a test click on the **Record new** button from the Testing sidebar. This will create a `test-1.spec.ts` file as well as open up a browser window.
To record a test click on the **Record new** button from the Testing sidebar. This will create a `test-1.spec.ts` file as well as open up a browser window.
<img width="1385" alt="record new in vs code" src="https://user-images.githubusercontent.com/13063165/220961665-615d0ab8-3f0b-439c-ad0b-0424d9aa154b.png" />
@ -58,16 +58,16 @@ In the test file in VS Code you will see your new generated actions added to you
### Generating locators
You can generate locators with the test generator.
- Click on the **Pick locator** button form the testing sidebar and then hover over elements in the browser window to see the [locator](./locators.md) highlighted underneath each element.
- Click the element you require and it will now show up in the **Pick locator** box in VS Code.
You can generate locators with the test generator.
- Click on the **Pick locator** button form the testing sidebar and then hover over elements in the browser window to see the [locator](./locators.md) highlighted underneath each element.
- Click the element you require and it will now show up in the **Pick locator** box in VS Code.
- Press <kbd>Enter</kbd> on your keyboard to copy the locator into the clipboard and then paste anywhere in your code. Or press 'escape' if you want to cancel.
<img width="1641" alt="Pick locators in VS code" src="https://user-images.githubusercontent.com/13063165/220958368-95b03620-3c9b-40a8-be74-01c96ba03cad.png" />
## Generate tests with the Playwright Inspector
When running the `codegen` command two windows will be opened, a browser window where you interact with the website you wish to test and the Playwright Inspector window where you can record your tests and then copy them into your editor.
When running the `codegen` command two windows will be opened, a browser window where you interact with the website you wish to test and the Playwright Inspector window where you can record your tests and then copy them into your editor.
### Running Codegen
@ -125,14 +125,14 @@ With the test generator you can record:
When you have finished interacting with the page, press the **record** button to stop the recording and use the **copy** button to copy the generated code to your editor.
Use the **clear** button to clear the code to start recording again. Once finished close the Playwright inspector window or stop the terminal command.
Use the **clear** button to clear the code to start recording again. Once finished, close the Playwright inspector window or stop the terminal command.
### Generating locators
You can generate [locators](/locators.md) with the test generator.
You can generate [locators](/locators.md) with the test generator.
* Press the `'Record'` button to stop the recording and the `'Pick Locator'` button will appear.
* Click on the `'Pick Locator'` button and then hover over elements in the browser window to see the locator highlighted underneath each element.
* To choose a locator click on the element you would like to locate and the code for that locator will appear in the field next to the Pick Locator button.
* Click on the `'Pick Locator'` button and then hover over elements in the browser window to see the locator highlighted underneath each element.
* To choose a locator, click on the element you would like to locate and the code for that locator will appear in the field next to the Pick Locator button.
* You can then edit the locator in this field to fine tune it or use the copy button to copy it and paste it into your code.
######
@ -164,19 +164,19 @@ You can use the test generator to generate tests using emulation so as to genera
Playwright opens a browser window with its viewport set to a specific width and height and is not responsive as tests need to be run under the same conditions. Use the `--viewport` option to generate tests with a different viewport size.
```bash js
npx playwright codegen --viewport-size=800,600 playwright.dev
npx playwright codegen --viewport-size="800,600" playwright.dev
```
```bash java
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="codegen --viewport-size=800,600 playwright.dev"
mvn exec:java -e -D exec.mainClass=com.microsoft.playwright.CLI -D exec.args="codegen --viewport-size='800,600' playwright.dev"
```
```bash python
playwright codegen --viewport-size=800,600 playwright.dev
playwright codegen --viewport-size="800,600" playwright.dev
```
```bash csharp
pwsh bin/Debug/netX/playwright.ps1 codegen --viewport-size=800,600 playwright.dev
pwsh bin/Debug/netX/playwright.ps1 codegen --viewport-size="800,600" playwright.dev
```
######
* langs: js
@ -284,7 +284,7 @@ pwsh bin/Debug/netX/playwright.ps1 codegen --color-scheme=dark playwright.dev
Record scripts and tests while emulating timezone, language & location using the `--timezone`, `--geolocation` and `--lang` options. Once the page opens:
1. Accept the cookies
1. On the top right click on the locate me button to see geolocation in action.
1. On the top right, click on the locate me button to see geolocation in action.
```bash js
npx playwright codegen --timezone="Europe/Rome" --geolocation="41.890221,12.492348" --lang="it-IT" bing.com/maps
@ -325,7 +325,7 @@ pwsh bin/Debug/netX/playwright.ps1 codegen --timezone="Europe/Rome" --geolocatio
### Preserve authenticated state
Run `codegen` with `--save-storage` to save [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) and [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) at the end of the session. This is useful to separately record an authentication step and reuse it later when recording more tests.
Run `codegen` with `--save-storage` to save [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies), [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) and [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) data at the end of the session. This is useful to separately record an authentication step and reuse it later when recording more tests.
```bash js
npx playwright codegen github.com/microsoft/playwright --save-storage=auth.json
@ -367,7 +367,7 @@ pwsh bin/Debug/netX/playwright.ps1 codegen github.com/microsoft/playwright --sav
#### Login
After performing authentication and closing the browser, `auth.json` will contain the storage state which you can then reuse in your tests.
After performing authentication and closing the browser, `auth.json` will contain the storage state which you can then reuse in your tests.
<img width="1394" alt="login to GitHub screen" src="https://user-images.githubusercontent.com/13063165/220561688-04b2b984-4ba6-4446-8b0a-8058876e2a02.png" />
@ -375,7 +375,7 @@ Make sure you only use the `auth.json` locally as it contains sensitive informat
#### Load authenticated state
Run with `--load-storage` to consume the previously loaded storage from the `auth.json`. This way, all [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies) and [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) will be restored, bringing most web apps to the authenticated state without the need to login again. This means you can can continue generating tests from the logged in state.
Run with `--load-storage` to consume the previously loaded storage from the `auth.json`. This way, all [cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies), [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) and [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) data will be restored, bringing most web apps to the authenticated state without the need to login again. This means you can continue generating tests from the logged in state.
```bash js
npx playwright codegen --load-storage=auth.json github.com/microsoft/playwright

View file

@ -46,7 +46,7 @@ A browser window will open and the test will run and pause at where the breakpoi
### Debug in different Browsers
By default debugging is done using the Chromium profile. You can debug your tests on different browsers by right clicking on the debug icon in the testing sidebar and clicking on the 'Select Default Profile' option from the dropdown.
By default, debugging is done using the Chromium profile. You can debug your tests on different browsers by right clicking on the debug icon in the testing sidebar and clicking on the 'Select Default Profile' option from the dropdown.
<img width="1312" alt="debugging on specific profile" src="https://user-images.githubusercontent.com/13063165/212879469-436f8130-c62a-49e1-9d67-c1903b478d5f.png" />
@ -80,7 +80,7 @@ npx playwright test --debug
```
#### Debug one test on all browsers
To debug one test on a specific line run the test command followed by the name of the test file and the line number of the test you want to debug, followed by the `--debug` flag. This will run a single test in each browser configured in your [`playwright.config`](./test-projects.md#configure-projects-for-multiple-browsers) and open the inspector.
To debug one test on a specific line, run the test command followed by the name of the test file and the line number of the test you want to debug, followed by the `--debug` flag. This will run a single test in each browser configured in your [`playwright.config`](./test-projects.md#configure-projects-for-multiple-browsers) and open the inspector.
```bash
npx playwright test example.spec.ts:10 --debug
@ -207,7 +207,7 @@ While running in debug mode you can live edit the locators. Next to the 'Pick Lo
### Picking locators
While debugging you might need to choose a more resilient locator. You can do this by clicking on the **Pick Locator** button and hovering over any element in the browser window. While hovering over an element you will see the code needed to locate this element highlighted below. Clicking an element in the browser will add the locator into the field where you can then either tweak it or copy it into your code.
While debugging, you might need to choose a more resilient locator. You can do this by clicking on the **Pick Locator** button and hovering over any element in the browser window. While hovering over an element you will see the code needed to locate this element highlighted below. Clicking an element in the browser will add the locator into the field where you can then either tweak it or copy it into your code.
<img width="1392" alt="Picking locators" src="https://user-images.githubusercontent.com/13063165/212968640-ce82a027-9277-4bdf-b0a9-6282fb2becb7.png" />
@ -242,7 +242,7 @@ This will also set the default timeouts of Playwright to 0 (= no timeout).
<img width="1399" alt="Browser Developer Tools with Playwright object" src="https://user-images.githubusercontent.com/13063165/219128002-898f604d-9697-4b7f-95b5-a6a8260b7282.png" />
To debug your tests using the browser developer tools start by setting a breakpoint in your test to pause the execution using the [`method: Page.pause`] method.
To debug your tests using the browser developer tools, start by setting a breakpoint in your test to pause the execution using the [`method: Page.pause`] method.
```js
await page.pause();
@ -264,7 +264,7 @@ page.pause()
await page.PauseAsync();
```
Once you have set a breakpoint in your test you can then run your test with `PWDEBUG=console`.
Once you have set a breakpoint in your test, you can then run your test with `PWDEBUG=console`.
```bash tab=bash-bash lang=js
PWDEBUG=console npx playwright test
@ -327,7 +327,7 @@ $env:PWDEBUG=console
dotnet test
```
Once Playwright launches the browser window you can open the developer tools.
Once Playwright launches the browser window, you can open the developer tools.
The `playwright` object will be available in the console panel.
#### playwright.$(selector)
@ -451,7 +451,7 @@ will reset pre-configured user agent and device emulation.
Playwright runs browsers in headless mode by default. To change this behavior,
use `headless: false` as a launch option.
You can also use the [`option: slowMo`] option
You can also use the [`option: BrowserType.launch.slowMo`] option
to slow down execution (by N milliseconds per operation) and follow along while debugging.
```js

View file

@ -5,7 +5,7 @@ title: "Dialogs"
## Introduction
Playwright can interact with the web page dialogs such as [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert), [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm), [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) as well as [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event) confirmation.
Playwright can interact with the web page dialogs such as [`alert`](https://developer.mozilla.org/en-US/docs/Web/API/Window/alert), [`confirm`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm), [`prompt`](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) as well as [`beforeunload`](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event) confirmation. For print dialogs, see [Print](#print-dialogs).
## alert(), confirm(), prompt() dialogs
@ -80,7 +80,7 @@ If there is no listener for [`event: Page.dialog`], all dialogs are automaticall
## beforeunload dialog
When [`method: Page.close`] is invoked with the truthy [`option: runBeforeUnload`] value, the page runs its unload handlers. This is the only case when [`method: Page.close`] does not wait for the page to actually close, because it might be that the page stays open in the end of the operation.
When [`method: Page.close`] is invoked with the truthy [`option: Page.close.runBeforeUnload`] value, the page runs its unload handlers. This is the only case when [`method: Page.close`] does not wait for the page to actually close, because it might be that the page stays open in the end of the operation.
You can register a dialog handler to handle the `beforeunload` dialog yourself:
@ -126,3 +126,55 @@ Page.Dialog += async (_, dialog) =>
};
await Page.CloseAsync(new() { RunBeforeUnload = true });
```
## Print dialogs
In order to assert that a print dialog via [`window.print`](https://developer.mozilla.org/en-US/docs/Web/API/Window/print) was triggered, you can use the following snippet:
```js
await page.goto('<url>');
await page.evaluate('(() => {window.waitForPrintDialog = new Promise(f => window.print = f);})()');
await page.getByText('Print it!').click();
await page.waitForFunction('window.waitForPrintDialog');
```
```java
page.navigate("<url>");
page.evaluate("(() => {window.waitForPrintDialog = new Promise(f => window.print = f);})()");
page.getByText("Print it!").click();
page.waitForFunction("window.waitForPrintDialog");
```
```python async
await page.goto("<url>")
await page.evaluate("(() => {window.waitForPrintDialog = new Promise(f => window.print = f);})()")
await page.get_by_text("Print it!").click()
await page.wait_for_function("window.waitForPrintDialog")
```
```python sync
page.goto("<url>")
page.evaluate("(() => {window.waitForPrintDialog = new Promise(f => window.print = f);})()")
page.get_by_text("Print it!").click()
page.wait_for_function("window.waitForPrintDialog")
```
```csharp
await Page.GotoAsync("<url>");
await Page.EvaluateAsync("(() => {window.waitForPrintDialog = new Promise(f => window.print = f);})()");
await Page.GetByText("Print it!").ClickAsync();
await Page.WaitForFunctionAsync("window.waitForPrintDialog");
```
This will wait for the print dialog to be opened after the button is clicked.
Make sure to evaluate the script before clicking the button / after the page is loaded.

View file

@ -5,7 +5,7 @@ title: "Docker"
## Introduction
[Dockerfile.jammy] can be used to run Playwright scripts in Docker environment. These image includes the [Playwright browsers](./browsers.md#install-browsers) and [browser system dependencies](./browsers.md#install-system-dependencies). The Playwright package/dependency is not included in the image and should be installed separately.
[Dockerfile.noble] can be used to run Playwright scripts in Docker environment. This image includes the [Playwright browsers](./browsers.md#install-browsers) and [browser system dependencies](./browsers.md#install-system-dependencies). The Playwright package/dependency is not included in the image and should be installed separately.
## Usage
@ -18,19 +18,19 @@ This Docker image is intended to be used for testing and development purposes on
### Pull the image
```bash js
docker pull mcr.microsoft.com/playwright:v%%VERSION%%-jammy
docker pull mcr.microsoft.com/playwright:v%%VERSION%%-noble
```
```bash python
docker pull mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy
docker pull mcr.microsoft.com/playwright/python:v%%VERSION%%-noble
```
```bash csharp
docker pull mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy
docker pull mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble
```
```bash java
docker pull mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy
docker pull mcr.microsoft.com/playwright/java:v%%VERSION%%-noble
```
### Run the image
@ -42,19 +42,19 @@ By default, the Docker image will use the `root` user to run the browsers. This
On trusted websites, you can avoid creating a separate user and use root for it since you trust the code which will run on the browsers.
```bash js
docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host mcr.microsoft.com/playwright:v%%VERSION%%-noble /bin/bash
```
```bash python
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/python:v%%VERSION%%-noble /bin/bash
```
```bash csharp
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble /bin/bash
```
```bash java
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v%%VERSION%%-noble /bin/bash
```
#### Crawling and scraping
@ -62,19 +62,19 @@ docker run -it --rm --ipc=host mcr.microsoft.com/playwright/java:v%%VERSION%%-ja
On untrusted websites, it's recommended to use a separate user for launching the browsers in combination with the seccomp profile. Inside the container or if you are using the Docker image as a base image you have to use `adduser` for it.
```bash js
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright:v%%VERSION%%-noble /bin/bash
```
```bash python
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/python:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/python:v%%VERSION%%-noble /bin/bash
```
```bash csharp
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/dotnet:v%%VERSION%%-noble /bin/bash
```
```bash java
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/java:v%%VERSION%%-jammy /bin/bash
docker run -it --rm --ipc=host --user pwuser --security-opt seccomp=seccomp_profile.json mcr.microsoft.com/playwright/java:v%%VERSION%%-noble /bin/bash
```
[`seccomp_profile.json`](https://github.com/microsoft/playwright/blob/main/utils/docker/seccomp_profile.json) is needed to run Chromium with sandbox. This is a [default Docker seccomp profile](https://github.com/docker/engine/blob/d0d99b04cf6e00ed3fc27e81fc3d94e7eda70af3/profiles/seccomp/default.json) with extra user namespace cloning permissions:
@ -103,17 +103,96 @@ Using `--ipc=host` is recommended when using Chrome ([Docker docs](https://docs.
See our [Continuous Integration guides](./ci.md) for sample configs.
### Remote Connection
You can run Playwright Server in Docker while keeping your tests running on the host system or another machine. This is useful for running tests on unsupported Linux distributions or remote execution scenarios.
#### Running the Playwright Server
Start the Playwright Server in Docker:
```bash
docker run -p 3000:3000 --rm --init -it --workdir /home/pwuser --user pwuser mcr.microsoft.com/playwright:v%%VERSION%%-noble /bin/sh -c "npx -y playwright@%%VERSION%% run-server --port 3000 --host 0.0.0.0"
```
#### Connecting to the Server
* langs: js
There are two ways to connect to the remote Playwright server:
1. Using environment variable with `@playwright/test`:
```bash
PW_TEST_CONNECT_WS_ENDPOINT=ws://127.0.0.1:3000/ npx playwright test
```
2. Using the [`method: BrowserType.connect`] API for other applications:
```js
const browser = await playwright['chromium'].connect('ws://127.0.0.1:3000/');
```
#### Connecting to the Server
* langs: python, csharp, java
```python sync
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.connect("ws://127.0.0.1:3000/")
```
```python async
from playwright.async_api import async_playwright
async with async_playwright() as p:
browser = await p.chromium.connect("ws://127.0.0.1:3000/")
```
```csharp
using Microsoft.Playwright;
using var playwright = await Playwright.CreateAsync();
await using var browser = await playwright.Chromium.ConnectAsync("ws://127.0.0.1:3000/");
```
```java
package org.example;
import com.microsoft.playwright.*;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
try (Playwright playwright = Playwright.create()) {
Browser browser = playwright.chromium().connect("ws://127.0.0.1:3000/");
}
}
}
```
#### Network Configuration
If you need to access local servers from within the Docker container:
```bash
docker run --add-host=hostmachine:host-gateway -p 3000:3000 --rm --init -it --workdir /home/pwuser --user pwuser mcr.microsoft.com/playwright:v%%VERSION%%-noble /bin/sh -c "npx -y playwright@%%VERSION%% run-server --port 3000 --host 0.0.0.0"
```
This makes `hostmachine` point to the host's localhost. Your tests should use `hostmachine` instead of `localhost` when accessing local servers.
:::note
When running tests remotely, ensure the Playwright version in your tests matches the version running in the Docker container.
:::
## Image tags
See [all available image tags].
We currently publish images with the following tags:
- `:next` - tip-of-tree image version based on Ubuntu 22.04 LTS (Jammy Jellyfish).
- `:next-jammy` - tip-of-tree image version based on Ubuntu 22.04 LTS (Jammy Jellyfish).
- `:v%%VERSION%%` - Playwright v%%VERSION%% release docker image based on Ubuntu 22.04 LTS (Jammy Jellyfish).
- `:v%%VERSION%%` - Playwright v%%VERSION%% release docker image based on Ubuntu 24.04 LTS (Noble Numbat).
- `:v%%VERSION%%-noble` - Playwright v%%VERSION%% release docker image based on Ubuntu 24.04 LTS (Noble Numbat).
- `:v%%VERSION%%-jammy` - Playwright v%%VERSION%% release docker image based on Ubuntu 22.04 LTS (Jammy Jellyfish).
- `:v%%VERSION%%-focal` - Playwright v%%VERSION%% release docker image based on Ubuntu 20.04 LTS (Focal Fossa).
:::note
It is recommended to always pin your Docker image to a specific version if possible. If the Playwright version in your Docker image does not match the version in your project/tests, Playwright will be unable to locate browser executables.
@ -124,7 +203,6 @@ It is recommended to always pin your Docker image to a specific version if possi
We currently publish images based on the following [Ubuntu](https://hub.docker.com/_/ubuntu) versions:
- **Ubuntu 24.04 LTS** (Noble Numbat), image tags include `noble`
- **Ubuntu 22.04 LTS** (Jammy Jellyfish), image tags include `jammy`
- **Ubuntu 20.04 LTS** (Focal Fossa), image tags include `focal`
#### Alpine
@ -136,7 +214,7 @@ Browser builds for Firefox and WebKit are built for the [glibc](https://en.wikip
You can use the [.NET install script](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script) in order to install different SDK versions:
```bash
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --install-dir /usr/share/dotnet --channel 6.0
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --install-dir /usr/share/dotnet --channel 9.0
```
## Build your own image

View file

@ -7,7 +7,7 @@ title: "Downloads"
For every attachment downloaded by the page, [`event: Page.download`] event is emitted. All these attachments are downloaded into a temporary folder. You can obtain the download url, file name and payload stream using the [Download] object from the event.
You can specify where to persist downloaded files using the [`option: downloadsPath`] option in [`method: BrowserType.launch`].
You can specify where to persist downloaded files using the [`option: BrowserType.launch.downloadsPath`] option in [`method: BrowserType.launch`].
:::note
Downloaded files are deleted when the browser context that produced them is closed.

View file

@ -188,7 +188,7 @@ page.setViewportSize(1600, 1200);
// Emulate high-DPI
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setViewportSize(2560, 1440)
.setDeviceScaleFactor(2);
.setDeviceScaleFactor(2));
```
```python async
@ -378,7 +378,7 @@ const context = await browser.newContext({
```java
BrowserContext context = browser.newContext(new Browser.NewContextOptions()
.setPermissions(Arrays.asList("notifications"));
.setPermissions(Arrays.asList("notifications")));
```
```python async
@ -558,7 +558,7 @@ await context.SetGeolocationAsync(new Geolocation() { Longitude = 48.858455, Lat
**Note** you can only change geolocation for all pages in the context.
## Color Scheme and Media
Emulate the users `"colorScheme"`. Supported values are 'light', 'dark', 'no-preference'. You can also emulate the media type with [`method: Page.emulateMedia`].
Emulate the users `"colorScheme"`. Supported values are 'light' and 'dark'. You can also emulate the media type with [`method: Page.emulateMedia`].
```js title="playwright.config.ts"
import { defineConfig } from '@playwright/test';

Some files were not shown because too many files have changed in this diff Show more