playwright-ruby-client 1.57.0 → 1.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -7
- data/documentation/docs/api/browser_context.md +26 -0
- data/documentation/docs/api/browser_type.md +3 -2
- data/documentation/docs/api/console_message.md +9 -0
- data/documentation/docs/api/frame.md +2 -2
- data/documentation/docs/api/frame_locator.md +2 -2
- data/documentation/docs/api/locator.md +17 -4
- data/documentation/docs/api/locator_assertions.md +1 -1
- data/documentation/docs/api/page.md +68 -5
- data/documentation/docs/api/request.md +13 -0
- data/documentation/docs/api/response.md +9 -0
- data/documentation/docs/api/route.md +4 -1
- data/documentation/docs/api/tracing.md +1 -0
- data/documentation/docs/article/getting_started.md +1 -1
- data/documentation/docs/article/guides/inspector.md +1 -1
- data/documentation/docs/article/guides/launch_browser.md +5 -5
- data/documentation/docs/article/guides/rails_integration.md +3 -3
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +46 -0
- data/documentation/docs/article/guides/recording_video.md +2 -2
- data/documentation/docs/article/guides/semi_automation.md +1 -1
- data/documentation/docs/include/api_coverage.md +16 -0
- data/lib/playwright/channel_owners/api_request_context.rb +24 -2
- data/lib/playwright/channel_owners/binding_call.rb +37 -3
- data/lib/playwright/channel_owners/browser_context.rb +24 -4
- data/lib/playwright/channel_owners/browser_type.rb +2 -1
- data/lib/playwright/channel_owners/debugger.rb +4 -0
- data/lib/playwright/channel_owners/dialog.rb +3 -1
- data/lib/playwright/channel_owners/disposable.rb +9 -0
- data/lib/playwright/channel_owners/overlay.rb +4 -0
- data/lib/playwright/channel_owners/page.rb +58 -32
- data/lib/playwright/channel_owners/request.rb +8 -0
- data/lib/playwright/channel_owners/response.rb +5 -0
- data/lib/playwright/channel_owners/stream.rb +4 -0
- data/lib/playwright/channel_owners/tracing.rb +17 -7
- data/lib/playwright/channel_owners/web_socket.rb +14 -0
- data/lib/playwright/connection.rb +25 -20
- data/lib/playwright/console_message_impl.rb +4 -0
- data/lib/playwright/disposable.rb +11 -0
- data/lib/playwright/har_router.rb +16 -1
- data/lib/playwright/javascript/value_serializer.rb +2 -1
- data/lib/playwright/locator_assertions_impl.rb +1 -1
- data/lib/playwright/locator_impl.rb +19 -3
- data/lib/playwright/page_assertions_impl.rb +1 -1
- data/lib/playwright/screencast.rb +91 -0
- data/lib/playwright/utils.rb +19 -0
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/video.rb +6 -4
- data/lib/playwright/waiter.rb +24 -6
- data/lib/playwright.rb +2 -0
- data/lib/playwright_api/android.rb +7 -7
- data/lib/playwright_api/android_device.rb +8 -8
- data/lib/playwright_api/api_request_context.rb +6 -6
- data/lib/playwright_api/browser.rb +18 -6
- data/lib/playwright_api/browser_context.rb +32 -6
- data/lib/playwright_api/browser_type.rb +13 -12
- data/lib/playwright_api/cdp_session.rb +6 -6
- data/lib/playwright_api/console_message.rb +6 -0
- data/lib/playwright_api/dialog.rb +6 -6
- data/lib/playwright_api/element_handle.rb +6 -6
- data/lib/playwright_api/frame.rb +8 -8
- data/lib/playwright_api/frame_locator.rb +2 -2
- data/lib/playwright_api/js_handle.rb +6 -6
- data/lib/playwright_api/locator.rb +19 -9
- data/lib/playwright_api/locator_assertions.rb +1 -1
- data/lib/playwright_api/page.rb +72 -23
- data/lib/playwright_api/playwright.rb +6 -6
- data/lib/playwright_api/request.rb +28 -6
- data/lib/playwright_api/response.rb +12 -6
- data/lib/playwright_api/route.rb +10 -7
- data/lib/playwright_api/tracing.rb +8 -7
- data/lib/playwright_api/web_socket.rb +6 -6
- data/lib/playwright_api/worker.rb +6 -6
- data/playwright.gemspec +9 -1
- data/sig/playwright.rbs +30 -17
- metadata +35 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 959a33f7494fd33763cd54ddcf1e1c17fa0d9d37c89643aef2198f0dd452bbc9
|
|
4
|
+
data.tar.gz: ce343d14b0541fdf0ba0892b2e79456eea0ea5340b9f651f77b50c4e9a835cf6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: bab8717bee2ff89d4735682f4e4b68b545a9812b01143fe082028aded03dcac856e63db430de66ac87cbcbfd397c16ddd1f5a774d6c33e951272e8c701b0149c
|
|
7
|
+
data.tar.gz: bba6fa2ebc246f538ccd074630c59f57c206d2942e299514c3d42b4717ae859943e42e4e2c4bc9b8a84e3680b2559f94ec1d7a0c34e7c56c7740468483ebf93e
|
data/README.md
CHANGED
|
@@ -174,16 +174,16 @@ npx playwright install && npx playwright run-server --port 8080 --path /ws
|
|
|
174
174
|
and we can connect to the server with the code like this:
|
|
175
175
|
|
|
176
176
|
```ruby
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
177
|
+
require 'playwright'
|
|
178
|
+
|
|
179
|
+
Playwright.connect_to_browser_server('wss://example.com:8888/ws') do |browser|
|
|
180
|
+
page = browser.new_page
|
|
181
|
+
page.goto('https://github.com/YusukeIwaki')
|
|
182
|
+
page.screenshot(path: './YusukeIwaki.png')
|
|
183
183
|
end
|
|
184
184
|
```
|
|
185
185
|
|
|
186
|
-
When `Playwright.
|
|
186
|
+
When `Playwright.connect_to_browser_server` is used, playwright_cli_executable_path is not required.
|
|
187
187
|
|
|
188
188
|
For more detailed instraction, refer this article: https://playwright-ruby-client.vercel.app/docs/article/guides/playwright_on_alpine_linux
|
|
189
189
|
|
|
@@ -238,6 +238,15 @@ def grant_permissions(permissions, origin: nil)
|
|
|
238
238
|
Grants specified permissions to the browser context. Only grants corresponding permissions to the given origin if
|
|
239
239
|
specified.
|
|
240
240
|
|
|
241
|
+
## closed?
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
def closed?
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
Indicates that the browser context is in the process of closing or has already been closed.
|
|
249
|
+
|
|
241
250
|
## new_cdp_session
|
|
242
251
|
|
|
243
252
|
```
|
|
@@ -431,6 +440,23 @@ def storage_state(indexedDB: nil, path: nil)
|
|
|
431
440
|
|
|
432
441
|
Returns storage state for this browser context, contains current cookies, local storage snapshot and IndexedDB snapshot.
|
|
433
442
|
|
|
443
|
+
## set_storage_state
|
|
444
|
+
|
|
445
|
+
```
|
|
446
|
+
def set_storage_state(storageState)
|
|
447
|
+
```
|
|
448
|
+
alias: `storage_state=`
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
Clears the existing cookies, local storage and IndexedDB entries for all origins and sets the new storage state.
|
|
452
|
+
|
|
453
|
+
**Usage**
|
|
454
|
+
|
|
455
|
+
```ruby
|
|
456
|
+
# Load storage state from a file and apply it to the context.
|
|
457
|
+
context.set_storage_state("state.json")
|
|
458
|
+
```
|
|
459
|
+
|
|
434
460
|
## unroute_all
|
|
435
461
|
|
|
436
462
|
```
|
|
@@ -25,6 +25,7 @@ end
|
|
|
25
25
|
def connect_over_cdp(
|
|
26
26
|
endpointURL,
|
|
27
27
|
headers: nil,
|
|
28
|
+
isLocal: nil,
|
|
28
29
|
slowMo: nil,
|
|
29
30
|
timeout: nil,
|
|
30
31
|
&block)
|
|
@@ -61,9 +62,9 @@ A path where Playwright expects to find a bundled browser executable.
|
|
|
61
62
|
```
|
|
62
63
|
def launch(
|
|
63
64
|
args: nil,
|
|
65
|
+
artifactsDir: nil,
|
|
64
66
|
channel: nil,
|
|
65
67
|
chromiumSandbox: nil,
|
|
66
|
-
devtools: nil,
|
|
67
68
|
downloadsPath: nil,
|
|
68
69
|
env: nil,
|
|
69
70
|
executablePath: nil,
|
|
@@ -118,6 +119,7 @@ def launch_persistent_context(
|
|
|
118
119
|
userDataDir,
|
|
119
120
|
acceptDownloads: nil,
|
|
120
121
|
args: nil,
|
|
122
|
+
artifactsDir: nil,
|
|
121
123
|
baseURL: nil,
|
|
122
124
|
bypassCSP: nil,
|
|
123
125
|
channel: nil,
|
|
@@ -126,7 +128,6 @@ def launch_persistent_context(
|
|
|
126
128
|
colorScheme: nil,
|
|
127
129
|
contrast: nil,
|
|
128
130
|
deviceScaleFactor: nil,
|
|
129
|
-
devtools: nil,
|
|
130
131
|
downloadsPath: nil,
|
|
131
132
|
env: nil,
|
|
132
133
|
executablePath: nil,
|
|
@@ -512,7 +512,7 @@ Consider the following DOM structure.
|
|
|
512
512
|
<button>Submit</button>
|
|
513
513
|
```
|
|
514
514
|
|
|
515
|
-
You can locate each element by
|
|
515
|
+
You can locate each element by its implicit role:
|
|
516
516
|
|
|
517
517
|
```ruby
|
|
518
518
|
page.get_by_role("heading", name: "Sign up").visible? # => true
|
|
@@ -544,7 +544,7 @@ Consider the following DOM structure.
|
|
|
544
544
|
<button data-testid="directions">Itinéraire</button>
|
|
545
545
|
```
|
|
546
546
|
|
|
547
|
-
You can locate the element by
|
|
547
|
+
You can locate the element by its test id:
|
|
548
548
|
|
|
549
549
|
```ruby
|
|
550
550
|
page.get_by_test_id("directions").click
|
|
@@ -157,7 +157,7 @@ Consider the following DOM structure.
|
|
|
157
157
|
<button>Submit</button>
|
|
158
158
|
```
|
|
159
159
|
|
|
160
|
-
You can locate each element by
|
|
160
|
+
You can locate each element by its implicit role:
|
|
161
161
|
|
|
162
162
|
```ruby
|
|
163
163
|
page.get_by_role("heading", name: "Sign up").visible? # => true
|
|
@@ -189,7 +189,7 @@ Consider the following DOM structure.
|
|
|
189
189
|
<button data-testid="directions">Itinéraire</button>
|
|
190
190
|
```
|
|
191
191
|
|
|
192
|
-
You can locate the element by
|
|
192
|
+
You can locate the element by its test id:
|
|
193
193
|
|
|
194
194
|
```ruby
|
|
195
195
|
page.get_by_test_id("directions").click
|
|
@@ -87,7 +87,7 @@ button = page.get_by_role("button").and(page.get_by_title("Subscribe"))
|
|
|
87
87
|
## aria_snapshot
|
|
88
88
|
|
|
89
89
|
```
|
|
90
|
-
def aria_snapshot(timeout: nil)
|
|
90
|
+
def aria_snapshot(depth: nil, mode: nil, timeout: nil)
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
|
|
@@ -127,6 +127,9 @@ Below is the HTML markup and the respective ARIA snapshot:
|
|
|
127
127
|
- link "About"
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
+
An AI-optimized snapshot, controlled by `mode`, is different from a default snapshot:
|
|
131
|
+
1. Includes element references `[ref=e2]`. 2. Does not wait for an element matching the locator, and throws when no elements match. 3. Includes snapshots of `<iframe>`s inside the target.
|
|
132
|
+
|
|
130
133
|
## blur
|
|
131
134
|
|
|
132
135
|
```
|
|
@@ -343,7 +346,7 @@ def description
|
|
|
343
346
|
```
|
|
344
347
|
|
|
345
348
|
|
|
346
|
-
Returns locator description previously set with [Locator#describe](./locator#describe). Returns `null` if no custom description has been set.
|
|
349
|
+
Returns locator description previously set with [Locator#describe](./locator#describe). Returns `null` if no custom description has been set.
|
|
347
350
|
|
|
348
351
|
**Usage**
|
|
349
352
|
|
|
@@ -744,7 +747,7 @@ Consider the following DOM structure.
|
|
|
744
747
|
<button>Submit</button>
|
|
745
748
|
```
|
|
746
749
|
|
|
747
|
-
You can locate each element by
|
|
750
|
+
You can locate each element by its implicit role:
|
|
748
751
|
|
|
749
752
|
```ruby
|
|
750
753
|
page.get_by_role("heading", name: "Sign up").visible? # => true
|
|
@@ -776,7 +779,7 @@ Consider the following DOM structure.
|
|
|
776
779
|
<button data-testid="directions">Itinéraire</button>
|
|
777
780
|
```
|
|
778
781
|
|
|
779
|
-
You can locate the element by
|
|
782
|
+
You can locate the element by its test id:
|
|
780
783
|
|
|
781
784
|
```ruby
|
|
782
785
|
page.get_by_test_id("directions").click
|
|
@@ -1082,6 +1085,16 @@ The method finds an element matching the specified selector in the locator's sub
|
|
|
1082
1085
|
|
|
1083
1086
|
[Learn more about locators](https://playwright.dev/python/docs/locators).
|
|
1084
1087
|
|
|
1088
|
+
## normalize
|
|
1089
|
+
|
|
1090
|
+
```
|
|
1091
|
+
def normalize
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
|
|
1095
|
+
Returns a new locator that uses best practices for referencing the matched element, prioritizing test ids,
|
|
1096
|
+
aria roles, and other user-facing attributes over CSS selectors. This is useful for converting implementation-detail selectors into more resilient, human-readable locators.
|
|
1097
|
+
|
|
1085
1098
|
## nth
|
|
1086
1099
|
|
|
1087
1100
|
```
|
|
@@ -524,7 +524,7 @@ Let's see how we can use the assertion:
|
|
|
524
524
|
|
|
525
525
|
```ruby
|
|
526
526
|
# ✓ Contains the right items in the right order
|
|
527
|
-
expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"
|
|
527
|
+
expect(page.locator("ul > li")).to contain_text(["Text 1", "Text 3"])
|
|
528
528
|
|
|
529
529
|
# ✖ Wrong order
|
|
530
530
|
expect(page.locator("ul > li")).to contain_text(["Text 3", "Text 2"])
|
|
@@ -94,6 +94,16 @@ def bring_to_front
|
|
|
94
94
|
|
|
95
95
|
Brings page to front (activates tab).
|
|
96
96
|
|
|
97
|
+
## cancel_pick_locator
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
def cancel_pick_locator
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
Cancels an ongoing [Page#pick_locator](./page#pick_locator) call by deactivating pick locator mode.
|
|
105
|
+
If no pick locator mode is active, this method is a no-op.
|
|
106
|
+
|
|
97
107
|
## check
|
|
98
108
|
|
|
99
109
|
```
|
|
@@ -706,7 +716,7 @@ Consider the following DOM structure.
|
|
|
706
716
|
<button>Submit</button>
|
|
707
717
|
```
|
|
708
718
|
|
|
709
|
-
You can locate each element by
|
|
719
|
+
You can locate each element by its implicit role:
|
|
710
720
|
|
|
711
721
|
```ruby
|
|
712
722
|
page.get_by_role("heading", name: "Sign up").visible? # => true
|
|
@@ -738,7 +748,7 @@ Consider the following DOM structure.
|
|
|
738
748
|
<button data-testid="directions">Itinéraire</button>
|
|
739
749
|
```
|
|
740
750
|
|
|
741
|
-
You can locate the element by
|
|
751
|
+
You can locate the element by its test id:
|
|
742
752
|
|
|
743
753
|
```ruby
|
|
744
754
|
page.get_by_test_id("directions").click
|
|
@@ -995,10 +1005,28 @@ def visible?(selector, strict: nil, timeout: nil)
|
|
|
995
1005
|
|
|
996
1006
|
Returns whether the element is [visible](https://playwright.dev/python/docs/actionability#visible). `selector` that does not match any elements is considered not visible.
|
|
997
1007
|
|
|
1008
|
+
## clear_console_messages
|
|
1009
|
+
|
|
1010
|
+
```
|
|
1011
|
+
def clear_console_messages
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
|
|
1015
|
+
Clears all stored console messages from this page. Subsequent calls to [Page#console_messages](./page#console_messages) will only return messages logged after the clear.
|
|
1016
|
+
|
|
1017
|
+
## clear_page_errors
|
|
1018
|
+
|
|
1019
|
+
```
|
|
1020
|
+
def clear_page_errors
|
|
1021
|
+
```
|
|
1022
|
+
|
|
1023
|
+
|
|
1024
|
+
Clears all stored page errors from this page. Subsequent calls to [Page#page_errors](./page#page_errors) will only return errors thrown after the clear.
|
|
1025
|
+
|
|
998
1026
|
## console_messages
|
|
999
1027
|
|
|
1000
1028
|
```
|
|
1001
|
-
def console_messages
|
|
1029
|
+
def console_messages(filter: nil)
|
|
1002
1030
|
```
|
|
1003
1031
|
|
|
1004
1032
|
|
|
@@ -1007,7 +1035,7 @@ Returns up to (currently) 200 last console messages from this page. See [`event:
|
|
|
1007
1035
|
## page_errors
|
|
1008
1036
|
|
|
1009
1037
|
```
|
|
1010
|
-
def page_errors
|
|
1038
|
+
def page_errors(filter: nil)
|
|
1011
1039
|
```
|
|
1012
1040
|
|
|
1013
1041
|
|
|
@@ -1132,6 +1160,23 @@ The `format` options are:
|
|
|
1132
1160
|
**NOTE**: `headerTemplate` and `footerTemplate` markup have the following limitations: > 1. Script tags inside
|
|
1133
1161
|
templates are not evaluated. > 2. Page styles are not visible inside templates.
|
|
1134
1162
|
|
|
1163
|
+
## pick_locator
|
|
1164
|
+
|
|
1165
|
+
```
|
|
1166
|
+
def pick_locator
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
|
|
1170
|
+
Enters pick locator mode where hovering over page elements highlights them and shows the corresponding locator.
|
|
1171
|
+
Once the user clicks an element, the mode is deactivated and the [Locator](./locator) for the picked element is returned.
|
|
1172
|
+
|
|
1173
|
+
**Usage**
|
|
1174
|
+
|
|
1175
|
+
```ruby
|
|
1176
|
+
locator = page.pick_locator
|
|
1177
|
+
puts locator
|
|
1178
|
+
```
|
|
1179
|
+
|
|
1135
1180
|
## press
|
|
1136
1181
|
|
|
1137
1182
|
```
|
|
@@ -1269,6 +1314,8 @@ end
|
|
|
1269
1314
|
page.route("/api/**", method(:handle_route))
|
|
1270
1315
|
```
|
|
1271
1316
|
|
|
1317
|
+
If a request matches multiple registered routes, the most recently registered route takes precedence.
|
|
1318
|
+
|
|
1272
1319
|
Page routes take precedence over browser context routes (set up with [BrowserContext#route](./browser_context#route)) when request
|
|
1273
1320
|
matches both handlers.
|
|
1274
1321
|
|
|
@@ -1471,6 +1518,15 @@ page.viewport_size = { width: 640, height: 480 }
|
|
|
1471
1518
|
page.goto("https://example.com")
|
|
1472
1519
|
```
|
|
1473
1520
|
|
|
1521
|
+
## aria_snapshot
|
|
1522
|
+
|
|
1523
|
+
```
|
|
1524
|
+
def aria_snapshot(depth: nil, mode: nil, timeout: nil)
|
|
1525
|
+
```
|
|
1526
|
+
|
|
1527
|
+
|
|
1528
|
+
Captures the aria snapshot of the page. Read more about [aria snapshots](https://playwright.dev/python/docs/aria-snapshots).
|
|
1529
|
+
|
|
1474
1530
|
## tap_point
|
|
1475
1531
|
|
|
1476
1532
|
```
|
|
@@ -1600,7 +1656,7 @@ def video
|
|
|
1600
1656
|
```
|
|
1601
1657
|
|
|
1602
1658
|
|
|
1603
|
-
Video object associated with this page.
|
|
1659
|
+
Video object associated with this page. Can be used to access the video file when using the `recordVideo` context option.
|
|
1604
1660
|
|
|
1605
1661
|
## viewport_size
|
|
1606
1662
|
|
|
@@ -1943,4 +1999,11 @@ Playwright has ability to mock clock and passage of time.
|
|
|
1943
1999
|
API testing helper associated with this page. This method returns the same instance as
|
|
1944
2000
|
[BrowserContext#request](./browser_context#request) on the page's context. See [BrowserContext#request](./browser_context#request) for more details.
|
|
1945
2001
|
|
|
2002
|
+
## screencast
|
|
2003
|
+
|
|
2004
|
+
|
|
2005
|
+
`Screencast` object associated with this page.
|
|
2006
|
+
|
|
2007
|
+
**Usage**
|
|
2008
|
+
|
|
1946
2009
|
## touchscreen
|
|
@@ -216,6 +216,19 @@ def response
|
|
|
216
216
|
|
|
217
217
|
Returns the matching [Response](./response) object, or `null` if the response was not received due to error.
|
|
218
218
|
|
|
219
|
+
## existing_response
|
|
220
|
+
|
|
221
|
+
```
|
|
222
|
+
def existing_response
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
Returns the [Response](./response) object if the response has already been received, `null` otherwise.
|
|
227
|
+
|
|
228
|
+
Unlike [Request#response](./request#response), this method does not wait for the response to arrive. It returns
|
|
229
|
+
immediately with the response object if the response has been received, or `null` if the response
|
|
230
|
+
has not been received yet.
|
|
231
|
+
|
|
219
232
|
## sizes
|
|
220
233
|
|
|
221
234
|
```
|
|
@@ -92,6 +92,15 @@ def header_values(name)
|
|
|
92
92
|
|
|
93
93
|
Returns all values of the headers matching the name, for example `set-cookie`. The name is case-insensitive.
|
|
94
94
|
|
|
95
|
+
## http_version
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
def http_version
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
Returns the http version used by the response.
|
|
103
|
+
|
|
95
104
|
## json
|
|
96
105
|
|
|
97
106
|
```
|
|
@@ -49,7 +49,10 @@ The `headers` option applies to both the routed request and any redirects it ini
|
|
|
49
49
|
|
|
50
50
|
[Route#continue](./route#continue) will immediately send the request to the network, other matching handlers won't be invoked. Use [Route#fallback](./route#fallback) If you want next matching handler in the chain to be invoked.
|
|
51
51
|
|
|
52
|
-
**NOTE**:
|
|
52
|
+
**NOTE**: Some request headers are **forbidden** and cannot be overridden (for example, `Cookie`, `Host`, `Content-Length` and others, see [this MDN page](https://developer.mozilla.org/en-US/docs/Glossary/Forbidden_request_header) for full list).
|
|
53
|
+
If an override is provided for a forbidden header, it will be ignored and the original request header will be used.
|
|
54
|
+
|
|
55
|
+
To set custom cookies, use [BrowserContext#add_cookies](./browser_context#add_cookies).
|
|
53
56
|
|
|
54
57
|
## fallback
|
|
55
58
|
|
|
@@ -19,7 +19,7 @@ $ npx playwright install
|
|
|
19
19
|
|
|
20
20
|
and then set `playwright_cli_executable_path: "npx playwright"` into `Playwright.create`.
|
|
21
21
|
|
|
22
|
-
Other methods of installation
|
|
22
|
+
Other methods of installation are also available. See the detail in [Download Playwright driver](./guides/download_playwright_driver)
|
|
23
23
|
|
|
24
24
|
## Enjoy with examples
|
|
25
25
|
|
|
@@ -8,7 +8,7 @@ sidebar_position: 2
|
|
|
8
8
|
|
|
9
9
|
## Create Playwright session
|
|
10
10
|
|
|
11
|
-
In
|
|
11
|
+
In order to launch browser, it is required to create Playwright session.
|
|
12
12
|
|
|
13
13
|
In previous examples,
|
|
14
14
|
|
|
@@ -18,7 +18,7 @@ Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwrig
|
|
|
18
18
|
end
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
this is the exact procedure for creating Playwright session. Choose either
|
|
21
|
+
this is the exact procedure for creating Playwright session. Choose either method for creating the session.
|
|
22
22
|
|
|
23
23
|
### Define scoped Playwright session with block
|
|
24
24
|
|
|
@@ -28,13 +28,13 @@ Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwrig
|
|
|
28
28
|
end
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
As
|
|
31
|
+
As described repeatedly, this is the recommended way for creating a Playwright session. Even when any exception happens, Playwright session is safely ended on leaving the block.
|
|
32
32
|
|
|
33
33
|
Internally `playwright run-driver` session is alive during the block.
|
|
34
34
|
|
|
35
35
|
### Define start/end of the Playwright session separately without block.
|
|
36
36
|
|
|
37
|
-
Sometimes we have to define
|
|
37
|
+
Sometimes we have to define separate start/end definitions. `playwright-ruby-client` also allows it.
|
|
38
38
|
|
|
39
39
|
```rb
|
|
40
40
|
class SomeClass
|
|
@@ -103,7 +103,7 @@ Also we can use `Browser#new_page` to create a new window and new tab at once.
|
|
|
103
103
|
|
|
104
104
|
```rb
|
|
105
105
|
Playwright.create(playwright_cli_executable_path: 'npx playwright') do |playwright|
|
|
106
|
-
playwright.chromium.launch(headless: false) do |browser| # Chromium task icon
|
|
106
|
+
playwright.chromium.launch(headless: false) do |browser| # Chromium task icon appears.
|
|
107
107
|
context = browser.new_context # Prepare new window.
|
|
108
108
|
page = context.new_page # Open new window and new tab here. (about:blank)
|
|
109
109
|
page.goto('https://example.com') # Navigate to a site.
|
|
@@ -43,9 +43,9 @@ If Playwright is running in an independent container, with docker-compose.yaml c
|
|
|
43
43
|
|
|
44
44
|
```
|
|
45
45
|
playwright: # this is our PLAYWRIGHT_HOST value
|
|
46
|
-
image: mcr.microsoft.com/playwright:v1.
|
|
46
|
+
image: mcr.microsoft.com/playwright:v1.57.0-noble
|
|
47
47
|
command: >
|
|
48
|
-
/bin/sh -c "npx -y playwright@1.
|
|
48
|
+
/bin/sh -c "npx -y playwright@1.57.0 run-server --port 3000 --host 0.0.0.0 --path /ws"
|
|
49
49
|
init: true
|
|
50
50
|
restart: unless-stopped
|
|
51
51
|
```
|
|
@@ -217,7 +217,7 @@ before do |example|
|
|
|
217
217
|
end
|
|
218
218
|
```
|
|
219
219
|
|
|
220
|
-

|
|
221
221
|
|
|
222
222
|
For more details, refer [Recording video](./recording_video.md#using-screen-recording-from-capybara-driver)
|
|
223
223
|
|
|
@@ -85,6 +85,52 @@ describe 'example', driver: :null do
|
|
|
85
85
|
end
|
|
86
86
|
```
|
|
87
87
|
|
|
88
|
+
## Share one browser across all tests
|
|
89
|
+
|
|
90
|
+
Launching a new browser for every test is slow. A better approach is to launch the browser once for the entire suite and give each test its own `BrowserContext` for isolation (fresh cookies, localStorage, and session state).
|
|
91
|
+
|
|
92
|
+
The challenge is that `Playwright.create` and `playwright.chromium.launch` are block-scoped APIs — the browser shuts down when the block exits. RSpec has `before(:suite)` and `after(:suite)` but no `around(:suite)`. A `Fiber` bridges the gap: `start!` resumes the fiber until it yields the browser back, and `stop!` resumes it again so both blocks exit cleanly.
|
|
93
|
+
|
|
94
|
+
```rb
|
|
95
|
+
module PlaywrightBrowser
|
|
96
|
+
class << self
|
|
97
|
+
attr_reader :browser
|
|
98
|
+
|
|
99
|
+
def start!
|
|
100
|
+
@fiber = Fiber.new do
|
|
101
|
+
Playwright.create(playwright_cli_executable_path: './node_modules/.bin/playwright') do |playwright|
|
|
102
|
+
playwright.chromium.launch(headless: false) do |browser|
|
|
103
|
+
Fiber.yield(browser)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
@browser = @fiber.resume
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def stop!
|
|
111
|
+
@fiber.resume
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
RSpec.configure do |config|
|
|
117
|
+
config.before(:suite) { PlaywrightBrowser.start! }
|
|
118
|
+
config.after(:suite) { PlaywrightBrowser.stop! }
|
|
119
|
+
|
|
120
|
+
config.around(driver: :null) do |example|
|
|
121
|
+
Capybara.current_driver = :null
|
|
122
|
+
base_url = Capybara.current_session.server.base_url
|
|
123
|
+
|
|
124
|
+
PlaywrightBrowser.browser.new_context(baseURL: base_url) do |browser_context|
|
|
125
|
+
@playwright_page = browser_context.new_page
|
|
126
|
+
example.run
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Each test gets a fresh `BrowserContext` (equivalent to a new incognito window), so cookies and storage never leak between tests. The block form of `new_context` ensures the context is always closed — even if the test raises an exception.
|
|
133
|
+
|
|
88
134
|
## Minitest Usage
|
|
89
135
|
|
|
90
136
|
We can do something similar with the default Rails setup using Minitest. Here's the same example written with Minitest:
|
|
@@ -33,7 +33,7 @@ playwright.chromium.launch do |browser|
|
|
|
33
33
|
|
|
34
34
|
Playwright puts videos on the directory specified at `record_video_dir`.
|
|
35
35
|
|
|
36
|
-
The previous example uses [Dir#mktmpdir](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html) for storing videos into a
|
|
36
|
+
The previous example uses [Dir#mktmpdir](https://docs.ruby-lang.org/ja/latest/method/Dir/s/mktmpdir.html) for storing videos into a temporary directory. Also we simply specify a relative or absolute path like `./my_videos/` or `/path/to/videos`.
|
|
37
37
|
|
|
38
38
|
## Getting video path and recorded video
|
|
39
39
|
|
|
@@ -42,7 +42,7 @@ This is really confusing for beginners, but in Playwright
|
|
|
42
42
|
* We can get the video path **only when page is alive (before calling BrowserContext#close or Page#close)**
|
|
43
43
|
* We can acquire the completely saved video **only after calling BrowserContext#close**
|
|
44
44
|
|
|
45
|
-
So in most
|
|
45
|
+
So in most cases, we have to store the video path in advance, and handle the saved video after BrowserContext is closed, as shown in the previous example code.
|
|
46
46
|
|
|
47
47
|
### Using `video#save_as(path)`
|
|
48
48
|
|
|
@@ -5,7 +5,7 @@ sidebar_position: 20
|
|
|
5
5
|
# Semi-automation
|
|
6
6
|
|
|
7
7
|
Playwright Browser context is isolated and not persisted by default. But we can also use persistent browser context using [BrowserType#launch_persistent_context](/docs/api/browser_type#launch_persistent_context).
|
|
8
|
-
This
|
|
8
|
+
This allows us to intervene in automation, for example
|
|
9
9
|
|
|
10
10
|
* Authenticate with OAuth2 manually before automation
|
|
11
11
|
* Testing a page after some chrome extensions are installed manually
|