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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -7
  3. data/documentation/docs/api/browser_context.md +26 -0
  4. data/documentation/docs/api/browser_type.md +3 -2
  5. data/documentation/docs/api/console_message.md +9 -0
  6. data/documentation/docs/api/frame.md +2 -2
  7. data/documentation/docs/api/frame_locator.md +2 -2
  8. data/documentation/docs/api/locator.md +17 -4
  9. data/documentation/docs/api/locator_assertions.md +1 -1
  10. data/documentation/docs/api/page.md +68 -5
  11. data/documentation/docs/api/request.md +13 -0
  12. data/documentation/docs/api/response.md +9 -0
  13. data/documentation/docs/api/route.md +4 -1
  14. data/documentation/docs/api/tracing.md +1 -0
  15. data/documentation/docs/article/getting_started.md +1 -1
  16. data/documentation/docs/article/guides/inspector.md +1 -1
  17. data/documentation/docs/article/guides/launch_browser.md +5 -5
  18. data/documentation/docs/article/guides/rails_integration.md +3 -3
  19. data/documentation/docs/article/guides/rails_integration_with_null_driver.md +46 -0
  20. data/documentation/docs/article/guides/recording_video.md +2 -2
  21. data/documentation/docs/article/guides/semi_automation.md +1 -1
  22. data/documentation/docs/include/api_coverage.md +16 -0
  23. data/lib/playwright/channel_owners/api_request_context.rb +24 -2
  24. data/lib/playwright/channel_owners/binding_call.rb +37 -3
  25. data/lib/playwright/channel_owners/browser_context.rb +24 -4
  26. data/lib/playwright/channel_owners/browser_type.rb +2 -1
  27. data/lib/playwright/channel_owners/debugger.rb +4 -0
  28. data/lib/playwright/channel_owners/dialog.rb +3 -1
  29. data/lib/playwright/channel_owners/disposable.rb +9 -0
  30. data/lib/playwright/channel_owners/overlay.rb +4 -0
  31. data/lib/playwright/channel_owners/page.rb +58 -32
  32. data/lib/playwright/channel_owners/request.rb +8 -0
  33. data/lib/playwright/channel_owners/response.rb +5 -0
  34. data/lib/playwright/channel_owners/stream.rb +4 -0
  35. data/lib/playwright/channel_owners/tracing.rb +17 -7
  36. data/lib/playwright/channel_owners/web_socket.rb +14 -0
  37. data/lib/playwright/connection.rb +25 -20
  38. data/lib/playwright/console_message_impl.rb +4 -0
  39. data/lib/playwright/disposable.rb +11 -0
  40. data/lib/playwright/har_router.rb +16 -1
  41. data/lib/playwright/javascript/value_serializer.rb +2 -1
  42. data/lib/playwright/locator_assertions_impl.rb +1 -1
  43. data/lib/playwright/locator_impl.rb +19 -3
  44. data/lib/playwright/page_assertions_impl.rb +1 -1
  45. data/lib/playwright/screencast.rb +91 -0
  46. data/lib/playwright/utils.rb +19 -0
  47. data/lib/playwright/version.rb +2 -2
  48. data/lib/playwright/video.rb +6 -4
  49. data/lib/playwright/waiter.rb +24 -6
  50. data/lib/playwright.rb +2 -0
  51. data/lib/playwright_api/android.rb +7 -7
  52. data/lib/playwright_api/android_device.rb +8 -8
  53. data/lib/playwright_api/api_request_context.rb +6 -6
  54. data/lib/playwright_api/browser.rb +18 -6
  55. data/lib/playwright_api/browser_context.rb +32 -6
  56. data/lib/playwright_api/browser_type.rb +13 -12
  57. data/lib/playwright_api/cdp_session.rb +6 -6
  58. data/lib/playwright_api/console_message.rb +6 -0
  59. data/lib/playwright_api/dialog.rb +6 -6
  60. data/lib/playwright_api/element_handle.rb +6 -6
  61. data/lib/playwright_api/frame.rb +8 -8
  62. data/lib/playwright_api/frame_locator.rb +2 -2
  63. data/lib/playwright_api/js_handle.rb +6 -6
  64. data/lib/playwright_api/locator.rb +19 -9
  65. data/lib/playwright_api/locator_assertions.rb +1 -1
  66. data/lib/playwright_api/page.rb +72 -23
  67. data/lib/playwright_api/playwright.rb +6 -6
  68. data/lib/playwright_api/request.rb +28 -6
  69. data/lib/playwright_api/response.rb +12 -6
  70. data/lib/playwright_api/route.rb +10 -7
  71. data/lib/playwright_api/tracing.rb +8 -7
  72. data/lib/playwright_api/web_socket.rb +6 -6
  73. data/lib/playwright_api/worker.rb +6 -6
  74. data/playwright.gemspec +9 -1
  75. data/sig/playwright.rbs +30 -17
  76. metadata +35 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 430aa6a1bab67d9edca2cce8f72c76578402ec3aab93f296366335d23894d3dd
4
- data.tar.gz: 0efe7aba9e4c2e45f6374c957dad31630e66157124f4b1b5dc2589815d39e6fc
3
+ metadata.gz: 959a33f7494fd33763cd54ddcf1e1c17fa0d9d37c89643aef2198f0dd452bbc9
4
+ data.tar.gz: ce343d14b0541fdf0ba0892b2e79456eea0ea5340b9f651f77b50c4e9a835cf6
5
5
  SHA512:
6
- metadata.gz: 5d19738002e6edef932c3eba936a99ffc3b54d805640a806cb3e255542d56b72be7526cf69c6752ed409c1337899f9c132494335c76b0231601c5cd7a596a677
7
- data.tar.gz: 5864d506cb7f6cfc4d0a35a65900241ca7a686f2b5e59716f16e4d4f588e832153bcff19bf71fae82bda9b91e55a7c9ee1f974e33d1541ad1a49e78a51e4b341
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
- Playwright.connect_to_playwright_server('ws://127.0.0.1:8080/ws?browser=chromium') do |playwright|
178
- playwright.chromium.launch do |browser|
179
- page = browser.new_page
180
- page.goto('https://github.com/YusukeIwaki')
181
- page.screenshot(path: './YusukeIwaki.png')
182
- end
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.connect_to_playwright_server` is used, playwright_cli_executable_path is not required.
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,
@@ -67,6 +67,15 @@ def text
67
67
 
68
68
  The text of the console message.
69
69
 
70
+ ## timestamp
71
+
72
+ ```
73
+ def timestamp
74
+ ```
75
+
76
+
77
+ The timestamp of the console message in milliseconds since the Unix epoch.
78
+
70
79
  ## type
71
80
 
72
81
  ```
@@ -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 it's implicit role:
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 it's test id:
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 it's implicit role:
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 it's test id:
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. Prefer `Locator.toString()` for a human-readable representation, as it uses the description when available.
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 it's implicit role:
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 it's test id:
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", "Text 4"])
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 it's implicit role:
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 it's test id:
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**: The `Cookie` header cannot be overridden using this method. If a value is provided, it will be ignored, and the cookie will be loaded from the browser's cookie store. To set custom cookies, use [BrowserContext#add_cookies](./browser_context#add_cookies).
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
 
@@ -26,6 +26,7 @@ end
26
26
 
27
27
  ```
28
28
  def start(
29
+ live: nil,
29
30
  name: nil,
30
31
  screenshots: nil,
31
32
  snapshots: nil,
@@ -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 is also available. See the detail in [Download Playwright driver](./guides/download_playwright_driver)
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
 
@@ -4,7 +4,7 @@ sidebar_position: 30
4
4
 
5
5
  # Playwright inspector
6
6
 
7
- Playwright provides an useful inspector.
7
+ Playwright provides a useful inspector.
8
8
  https://playwright.dev/docs/inspector/
9
9
 
10
10
  ## Overview
@@ -8,7 +8,7 @@ sidebar_position: 2
8
8
 
9
9
  ## Create Playwright session
10
10
 
11
- In oder to launch browser, it is required to create Playwright session.
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 of method for creating the session.
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 is described repetedly, this is the recommended way for creating Playwright session. Even when any exception happens, Playwright session is safely ended on leaving the block.
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 separated start/end definition. `playwright-ruby-client` also allows it.
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 appers in.
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.56.1-noble
46
+ image: mcr.microsoft.com/playwright:v1.57.0-noble
47
47
  command: >
48
- /bin/sh -c "npx -y playwright@1.56.1 run-server --port 3000 --host 0.0.0.0 --path /ws"
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
- ![sceenrecord](https://user-images.githubusercontent.com/11763113/121126629-71b5f600-c863-11eb-8f88-7924ab669946.gif)
220
+ ![screenrecord](https://user-images.githubusercontent.com/11763113/121126629-71b5f600-c863-11eb-8f88-7924ab669946.gif)
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 temprary directory. Also we simply specify a relative or absolute path like `./my_videos/` or `/path/to/videos`.
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 case, we have to store the video path in advance, and handle the saved video after BrowserContext is closed, as is shown the previous example code.
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 allow us to intermediate into automation, for example
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