playwright-ruby-client 1.22.0 → 1.23.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/documentation/docs/api/browser.md +16 -0
  3. data/documentation/docs/api/browser_context.md +15 -2
  4. data/documentation/docs/api/browser_type.md +4 -0
  5. data/documentation/docs/api/element_handle.md +0 -5
  6. data/documentation/docs/api/experimental/android_device.md +4 -0
  7. data/documentation/docs/api/locator.md +13 -6
  8. data/documentation/docs/api/page.md +14 -1
  9. data/documentation/docs/api/request.md +3 -1
  10. data/documentation/docs/api/response.md +12 -1
  11. data/documentation/docs/api/route.md +65 -0
  12. data/documentation/docs/include/api_coverage.md +5 -3
  13. data/lib/playwright/channel.rb +1 -3
  14. data/lib/playwright/channel_owners/browser.rb +13 -0
  15. data/lib/playwright/channel_owners/browser_context.rb +81 -13
  16. data/lib/playwright/channel_owners/browser_type.rb +4 -0
  17. data/lib/playwright/channel_owners/frame.rb +16 -2
  18. data/lib/playwright/channel_owners/local_utils.rb +29 -0
  19. data/lib/playwright/channel_owners/page.rb +43 -15
  20. data/lib/playwright/channel_owners/request.rb +31 -6
  21. data/lib/playwright/channel_owners/response.rb +6 -0
  22. data/lib/playwright/channel_owners/route.rb +104 -45
  23. data/lib/playwright/connection.rb +6 -1
  24. data/lib/playwright/har_router.rb +82 -0
  25. data/lib/playwright/http_headers.rb +1 -1
  26. data/lib/playwright/javascript/regex.rb +23 -0
  27. data/lib/playwright/javascript/value_serializer.rb +3 -4
  28. data/lib/playwright/javascript.rb +1 -0
  29. data/lib/playwright/locator_impl.rb +3 -5
  30. data/lib/playwright/route_handler.rb +2 -6
  31. data/lib/playwright/utils.rb +31 -6
  32. data/lib/playwright/version.rb +2 -2
  33. data/lib/playwright.rb +2 -0
  34. data/lib/playwright_api/android_device.rb +5 -1
  35. data/lib/playwright_api/browser.rb +15 -2
  36. data/lib/playwright_api/browser_context.rb +16 -6
  37. data/lib/playwright_api/browser_type.rb +5 -1
  38. data/lib/playwright_api/element_handle.rb +0 -11
  39. data/lib/playwright_api/locator.rb +11 -12
  40. data/lib/playwright_api/page.rb +16 -6
  41. data/lib/playwright_api/request.rb +8 -1
  42. data/lib/playwright_api/response.rb +14 -1
  43. data/lib/playwright_api/route.rb +61 -2
  44. data/lib/playwright_api/worker.rb +4 -4
  45. metadata +5 -4
  46. data/lib/playwright_api/local_utils.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 82040f41eb8c972a8e3415aac148c27218e9fcbb00d7e09832bd75da506d2367
4
- data.tar.gz: a42be0ab4e00bb0ef36516474cca8220147d8c635e44c581c799ee65e396721f
3
+ metadata.gz: 5d8cc3ad6fb1bd9c8a42f249085e91f92dbed26ebcbbd310559810299b60ea31
4
+ data.tar.gz: 6fb3450345d6f7bcbcbb19e3206244739f8aecf0813a94216e58df03674fb8e1
5
5
  SHA512:
6
- metadata.gz: 615d15f014ca5f175d9da7504583693903d0ebd4c3d47522bf2f5c0add5aa01f26551300834b86cd944a2eacb2ef38062c341ec14f1177b7f517a16dab6e90fe
7
- data.tar.gz: 97de038214b07abfbeb9eece923c0b031793b8939107df5f7b37268dbb4598c188dc88c4870766cf31d0bf28416610f46c996518a2f37fc8c73d5b672f713005
6
+ metadata.gz: b4e12e990b3a9df4532154ad62d6064c343664b75d8f29d088e6c28c00b5f22608d3de49c3568af2e2ac8689e9d9769e478e36571e7921d928c21eb3a18d9a56
7
+ data.tar.gz: 49f939af824f3affd9bbb011eb389238d5484a3f320fed6ad170bfb8c011ac351f6dba239f4e685d6b9058f4b72461fd5d1b5aee98835e34948eeef90b535dbc
@@ -21,6 +21,14 @@ end
21
21
 
22
22
 
23
23
 
24
+ ## browser_type
25
+
26
+ ```
27
+ def browser_type
28
+ ```
29
+
30
+ Get the browser type (chromium, firefox or webkit) that the browser belongs to.
31
+
24
32
  ## close
25
33
 
26
34
  ```
@@ -93,12 +101,16 @@ def new_context(
93
101
  offline: nil,
94
102
  permissions: nil,
95
103
  proxy: nil,
104
+ record_har_content: nil,
105
+ record_har_mode: nil,
96
106
  record_har_omit_content: nil,
97
107
  record_har_path: nil,
108
+ record_har_url_filter: nil,
98
109
  record_video_dir: nil,
99
110
  record_video_size: nil,
100
111
  reducedMotion: nil,
101
112
  screen: nil,
113
+ serviceWorkers: nil,
102
114
  storageState: nil,
103
115
  strictSelectors: nil,
104
116
  timezoneId: nil,
@@ -144,12 +156,16 @@ def new_page(
144
156
  offline: nil,
145
157
  permissions: nil,
146
158
  proxy: nil,
159
+ record_har_content: nil,
160
+ record_har_mode: nil,
147
161
  record_har_omit_content: nil,
148
162
  record_har_path: nil,
163
+ record_har_url_filter: nil,
149
164
  record_video_dir: nil,
150
165
  record_video_size: nil,
151
166
  reducedMotion: nil,
152
167
  screen: nil,
168
+ serviceWorkers: nil,
153
169
  storageState: nil,
154
170
  strictSelectors: nil,
155
171
  timezoneId: nil,
@@ -271,9 +271,9 @@ def route(url, handler, times: nil)
271
271
  Routing provides the capability to modify network requests that are made by any page in the browser context. Once route
272
272
  is enabled, every request matching the url pattern will stall unless it's continued, fulfilled or aborted.
273
273
 
274
- > NOTE: [Page#route](./page#route) will not intercept requests intercepted by Service Worker. See
274
+ > NOTE: [BrowserContext#route](./browser_context#route) will not intercept requests intercepted by Service Worker. See
275
275
  [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using
276
- request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);`
276
+ request interception by setting `Browser.newContext.serviceWorkers` to `'block'`.
277
277
 
278
278
  An example of a naive handler that aborts all image requests:
279
279
 
@@ -315,6 +315,19 @@ To remove a route with its handler you can use [BrowserContext#unroute](./browse
315
315
 
316
316
  > NOTE: Enabling routing disables http cache.
317
317
 
318
+ ## route_from_har
319
+
320
+ ```
321
+ def route_from_har(har, notFound: nil, update: nil, url: nil)
322
+ ```
323
+
324
+ If specified the network requests that are made in the context will be served from the HAR file. Read more about
325
+ [Replaying from HAR](https://playwright.dev/python/docs/network).
326
+
327
+ Playwright will not serve requests intercepted by Service Worker from the HAR file. See
328
+ [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using
329
+ request interception by setting `Browser.newContext.serviceWorkers` to `'block'`.
330
+
318
331
  ## service_workers
319
332
 
320
333
  ```
@@ -131,12 +131,16 @@ def launch_persistent_context(
131
131
  offline: nil,
132
132
  permissions: nil,
133
133
  proxy: nil,
134
+ record_har_content: nil,
135
+ record_har_mode: nil,
134
136
  record_har_omit_content: nil,
135
137
  record_har_path: nil,
138
+ record_har_url_filter: nil,
136
139
  record_video_dir: nil,
137
140
  record_video_size: nil,
138
141
  reducedMotion: nil,
139
142
  screen: nil,
143
+ serviceWorkers: nil,
140
144
  slowMo: nil,
141
145
  strictSelectors: nil,
142
146
  timeout: nil,
@@ -504,11 +504,6 @@ element_handle.select_option(label: "blue")
504
504
  element_handle.select_option(value: ["red", "green", "blue"])
505
505
  ```
506
506
 
507
- ```ruby
508
- # multiple selection for blue, red and second option
509
- element_handle.select_option(value: "blue", index: 2, label: "red")
510
- ```
511
-
512
507
 
513
508
 
514
509
  ## select_text
@@ -45,12 +45,16 @@ def launch_browser(
45
45
  noViewport: nil,
46
46
  offline: nil,
47
47
  permissions: nil,
48
+ record_har_content: nil,
49
+ record_har_mode: nil,
48
50
  record_har_omit_content: nil,
49
51
  record_har_path: nil,
52
+ record_har_url_filter: nil,
50
53
  record_video_dir: nil,
51
54
  record_video_size: nil,
52
55
  reducedMotion: nil,
53
56
  screen: nil,
57
+ serviceWorkers: nil,
54
58
  strictSelectors: nil,
55
59
  timezoneId: nil,
56
60
  userAgent: nil,
@@ -291,7 +291,19 @@ To send fine-grained keyboard events, use [Locator#type](./locator#type).
291
291
  def filter(has: nil, hasText: nil)
292
292
  ```
293
293
 
294
- This method narrows existing locator according to the options, for example filters by text.
294
+ This method narrows existing locator according to the options, for example filters by text. It can be chained to filter
295
+ multiple times.
296
+
297
+ ```ruby
298
+ row_locator = page.locator("tr")
299
+ # ...
300
+ row_locator.
301
+ filter(has_text="text in column 1").
302
+ filter(has=page.locator("tr", has_text="column 2 button")).
303
+ screenshot
304
+ ```
305
+
306
+
295
307
 
296
308
  ## first
297
309
 
@@ -564,11 +576,6 @@ element.select_option(label: "blue")
564
576
  element.select_option(value: ["red", "green", "blue"])
565
577
  ```
566
578
 
567
- ```ruby
568
- # multiple selection for blue, red and second option
569
- element.select_option(value: "blue", index: 2, label: "red")
570
- ```
571
-
572
579
 
573
580
 
574
581
  ## select_text
@@ -975,7 +975,7 @@ Once routing is enabled, every request matching the url pattern will stall unles
975
975
  > NOTE: The handler will only be called for the first url if the response is a redirect.
976
976
  > NOTE: [Page#route](./page#route) will not intercept requests intercepted by Service Worker. See
977
977
  [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using
978
- request interception. Via `await context.addInitScript(() => delete window.navigator.serviceWorker);`
978
+ request interception by setting `Browser.newContext.serviceWorkers` to `'block'`.
979
979
 
980
980
  An example of a naive handler that aborts all image requests:
981
981
 
@@ -1013,6 +1013,19 @@ To remove a route with its handler you can use [Page#unroute](./page#unroute).
1013
1013
 
1014
1014
  > NOTE: Enabling routing disables http cache.
1015
1015
 
1016
+ ## route_from_har
1017
+
1018
+ ```
1019
+ def route_from_har(har, notFound: nil, update: nil, url: nil)
1020
+ ```
1021
+
1022
+ If specified the network requests that are made in the page will be served from the HAR file. Read more about
1023
+ [Replaying from HAR](https://playwright.dev/python/docs/network).
1024
+
1025
+ Playwright will not serve requests intercepted by Service Worker from the HAR file. See
1026
+ [this](https://github.com/microsoft/playwright/issues/1090) issue. We recommend disabling Service Workers when using
1027
+ request interception by setting `Browser.newContext.serviceWorkers` to `'block'`.
1028
+
1016
1029
  ## screenshot
1017
1030
 
1018
1031
  ```
@@ -56,7 +56,9 @@ Returns the [Frame](./frame) that initiated this request.
56
56
  def headers
57
57
  ```
58
58
 
59
- **DEPRECATED** Incomplete list of headers as seen by the rendering engine. Use [Request#all_headers](./request#all_headers) instead.
59
+ An object with the request HTTP headers. The header names are lower-cased. Note that this method does not return
60
+ security-related headers, including cookie-related ones. You can use [Request#all_headers](./request#all_headers) for complete list of
61
+ headers that include `cookie` information.
60
62
 
61
63
  ## headers_array
62
64
 
@@ -38,13 +38,24 @@ def frame
38
38
 
39
39
  Returns the [Frame](./frame) that initiated this response.
40
40
 
41
+ ## from_service_worker
42
+
43
+ ```
44
+ def from_service_worker
45
+ ```
46
+
47
+ Indicates whether this Response was fullfilled by a Service Worker's Fetch Handler (i.e. via
48
+ [FetchEvent.respondWith](https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent/respondWith)).
49
+
41
50
  ## headers
42
51
 
43
52
  ```
44
53
  def headers
45
54
  ```
46
55
 
47
- **DEPRECATED** Incomplete list of headers as seen by the rendering engine. Use [Response#all_headers](./response#all_headers) instead.
56
+ An object with the response HTTP headers. The header names are lower-cased. Note that this method does not return
57
+ security-related headers, including cookie-related ones. You can use [Response#all_headers](./response#all_headers) for complete list
58
+ of headers that include `cookie` information.
48
59
 
49
60
  ## headers_array
50
61
 
@@ -31,6 +31,7 @@ def handle(route, request)
31
31
  headers = request.headers
32
32
  headers['foo'] = 'bar' # set "foo" header
33
33
  headers['user-agent'] = 'Unknown Browser' # modify user-agent
34
+ headers.delete('bar') # remove "bar" header
34
35
 
35
36
  route.continue(headers: headers)
36
37
  end
@@ -39,6 +40,70 @@ page.route("**/*", method(:handle))
39
40
 
40
41
 
41
42
 
43
+ ## fallback
44
+
45
+ ```
46
+ def fallback(headers: nil, method: nil, postData: nil, url: nil)
47
+ ```
48
+
49
+ When several routes match the given pattern, they run in the order opposite to their registration. That way the last
50
+ registered route can always override all the previos ones. In the example below, request will be handled by the
51
+ bottom-most handler first, then it'll fall back to the previous one and in the end will be aborted by the first
52
+ registered route.
53
+
54
+ ```ruby
55
+ page.route("**/*", -> (route,_) { route.abort }) # Runs last.
56
+ page.route("**/*", -> (route,_) { route.fallback }) # Runs second.
57
+ page.route("**/*", -> (route,_) { route.fallback }) # Runs first.
58
+ ```
59
+
60
+ Registering multiple routes is useful when you want separate handlers to handle different kinds of requests, for example
61
+ API calls vs page resources or GET requests vs POST requests as in the example below.
62
+
63
+ ```ruby
64
+ # Handle GET requests.
65
+ def handle_post(route, request)
66
+ if request.method != "GET"
67
+ route.fallback
68
+ return
69
+ end
70
+
71
+ # Handling GET only.
72
+ # ...
73
+ end
74
+
75
+ # Handle POST requests.
76
+ def handle_post(route)
77
+ if request.method != "POST"
78
+ route.fallback
79
+ return
80
+ end
81
+
82
+ # Handling POST only.
83
+ # ...
84
+ end
85
+
86
+ page.route("**/*", handle_get)
87
+ page.route("**/*", handle_post)
88
+ ```
89
+
90
+ One can also modify request while falling back to the subsequent handler, that way intermediate route handler can modify
91
+ url, method, headers and postData of the request.
92
+
93
+ ```ruby
94
+ def handle(route, request)
95
+ # override headers
96
+ headers = request.headers
97
+ headers['foo'] = 'bar' # set "foo" header
98
+ headers['user-agent'] = 'Unknown Browser' # modify user-agent
99
+ headers.delete('bar') # remove "bar" header
100
+
101
+ route.fallback(headers: headers)
102
+ end
103
+ ```
104
+
105
+
106
+
42
107
  ## fulfill
43
108
 
44
109
  ```
@@ -27,6 +27,7 @@
27
27
  * body
28
28
  * finished
29
29
  * frame
30
+ * from_service_worker
30
31
  * headers
31
32
  * headers_array
32
33
  * header_value
@@ -45,6 +46,7 @@
45
46
 
46
47
  * abort
47
48
  * continue
49
+ * fallback
48
50
  * fulfill
49
51
  * request
50
52
 
@@ -280,6 +282,7 @@
280
282
  * query_selector_all
281
283
  * reload
282
284
  * route
285
+ * route_from_har
283
286
  * screenshot
284
287
  * select_option
285
288
  * set_checked
@@ -339,6 +342,7 @@
339
342
  * new_page
340
343
  * pages
341
344
  * route
345
+ * route_from_har
342
346
  * service_workers
343
347
  * set_default_navigation_timeout
344
348
  * set_default_timeout
@@ -360,6 +364,7 @@
360
364
 
361
365
  ## Browser
362
366
 
367
+ * browser_type
363
368
  * close
364
369
  * contexts
365
370
  * connected?
@@ -454,9 +459,6 @@
454
459
  * locator
455
460
  * nth
456
461
 
457
- ## LocalUtils
458
-
459
-
460
462
  ## APIResponse
461
463
 
462
464
  * body
@@ -37,13 +37,11 @@ module Playwright
37
37
 
38
38
  # @param method [String]
39
39
  # @param params [Hash]
40
- # @returns nil
40
+ # @returns [Concurrent::Promises::Future]
41
41
  def async_send_message_to_server(method, params = {})
42
42
  with_logging do |metadata|
43
43
  @connection.async_send_message_to_server(@guid, method, params, metadata: metadata)
44
44
  end
45
-
46
- nil
47
45
  end
48
46
 
49
47
  private def with_logging(&block)
@@ -5,6 +5,7 @@ module Playwright
5
5
  include Utils::PrepareBrowserContextOptions
6
6
 
7
7
  private def after_initialize
8
+ @browser_type = @parent
8
9
  @connected = true
9
10
  @closed_or_closing = false
10
11
  @should_close_connection_on_close = false
@@ -17,6 +18,10 @@ module Playwright
17
18
  @contexts.to_a
18
19
  end
19
20
 
21
+ def browser_type
22
+ @browser_type
23
+ end
24
+
20
25
  def connected?
21
26
  @connected
22
27
  end
@@ -30,6 +35,7 @@ module Playwright
30
35
  @contexts << context
31
36
  context.browser = self
32
37
  context.options = params
38
+ context.send(:update_browser_type, @browser_type)
33
39
  return context unless block
34
40
 
35
41
  begin
@@ -54,6 +60,13 @@ module Playwright
54
60
  end
55
61
  end
56
62
 
63
+ private def update_browser_type(browser_type)
64
+ @browser_type = browser_type
65
+ @contexts.each do |context|
66
+ context.send(:update_browser_type, browser_type)
67
+ end
68
+ end
69
+
57
70
  def close
58
71
  return if @closed_or_closing
59
72
  @closed_or_closing = true
@@ -2,6 +2,8 @@ module Playwright
2
2
  # @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser_context.py
3
3
  define_channel_owner :BrowserContext do
4
4
  include Utils::Errors::SafeCloseError
5
+ include Utils::PrepareBrowserContextOptions
6
+
5
7
  attr_accessor :browser
6
8
  attr_writer :owner_page, :options
7
9
  attr_reader :tracing, :request
@@ -17,12 +19,17 @@ module Playwright
17
19
 
18
20
  @tracing = ChannelOwners::Tracing.from(@initializer['tracing'])
19
21
  @request = ChannelOwners::APIRequestContext.from(@initializer['APIRequestContext'])
22
+ @har_recorders = {}
20
23
 
21
24
  @channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
22
25
  @channel.once('close', ->(_) { on_close })
23
26
  @channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
24
27
  @channel.on('route', ->(params) {
25
- on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
28
+ Concurrent::Promises.future {
29
+ on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
30
+ }.rescue do |err|
31
+ puts err, err.backtrace
32
+ end
26
33
  })
27
34
  @channel.on('backgroundPage', ->(params) {
28
35
  on_background_page(ChannelOwners::Page.from(params['page']))
@@ -55,6 +62,16 @@ module Playwright
55
62
  @closed_promise = Concurrent::Promises.resolvable_future
56
63
  end
57
64
 
65
+ private def update_browser_type(browser_type)
66
+ @browser_type = browser_type
67
+ if @options[:recordHar]
68
+ @har_recorders[''] = {
69
+ path: @options[:recordHar][:path],
70
+ content: @options[:recordHar][:content]
71
+ }
72
+ end
73
+ end
74
+
58
75
  private def on_page(page)
59
76
  @pages << page
60
77
  emit(Events::BrowserContext::Page, page)
@@ -73,19 +90,29 @@ module Playwright
73
90
  wrapped_route = PlaywrightApi.wrap(route)
74
91
  wrapped_request = PlaywrightApi.wrap(request)
75
92
 
76
- handler_entry = @routes.find do |entry|
77
- entry.match?(request.url)
93
+ handled = @routes.any? do |handler_entry|
94
+ next false unless handler_entry.match?(request.url)
95
+
96
+ promise = Concurrent::Promises.resolvable_future
97
+ route.send(:set_handling_future, promise)
98
+
99
+ promise_handled = Concurrent::Promises.zip(
100
+ promise,
101
+ handler_entry.async_handle(wrapped_route, wrapped_request)
102
+ ).value!.first
103
+
104
+ promise_handled
78
105
  end
79
106
 
80
- if handler_entry
81
- handler_entry.async_handle(wrapped_route, wrapped_request)
107
+ @routes.reject!(&:expired?)
108
+ if @routes.count == 0
109
+ @channel.async_send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
110
+ end
82
111
 
83
- @routes.reject!(&:expired?)
84
- if @routes.count == 0
85
- @channel.async_send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
112
+ unless handled
113
+ route.send(:async_continue_route).rescue do |err|
114
+ puts err, err.backtrace
86
115
  end
87
- else
88
- route.continue
89
116
  end
90
117
  end
91
118
 
@@ -266,6 +293,37 @@ module Playwright
266
293
  end
267
294
  end
268
295
 
296
+ private def record_into_har(har, page, notFound:, url:)
297
+ params = {
298
+ options: prepare_record_har_options(
299
+ record_har_path: har,
300
+ record_har_content: "attach",
301
+ record_har_mode: "minimal",
302
+ record_har_url_filter: url,
303
+ )
304
+ }
305
+ if page
306
+ params[:page] = page.channel
307
+ end
308
+ har_id = @channel.send_message_to_server('harStart', params)
309
+ @har_recorders[har_id] = { path: har, content: 'attach' }
310
+ end
311
+
312
+ def route_from_har(har, notFound: nil, update: nil, url: nil)
313
+ if update
314
+ record_into_har(har, nil, notFound: notFound, url: url)
315
+ return
316
+ end
317
+
318
+ router = HarRouter.create(
319
+ @connection.local_utils,
320
+ har.to_s,
321
+ notFound || "abort",
322
+ url_match: url,
323
+ )
324
+ router.add_context_route(self)
325
+ end
326
+
269
327
  def expect_event(event, predicate: nil, timeout: nil, &block)
270
328
  wait_helper = WaitHelper.new
271
329
  wait_helper.reject_on_timeout(timeout || @timeout_settings.timeout, "Timeout while waiting for event \"#{event}\"")
@@ -283,9 +341,19 @@ module Playwright
283
341
  end
284
342
 
285
343
  def close
286
- if @options && @options.key?(:recordHar)
287
- har = ChannelOwners::Artifact.from(@channel.send_message_to_server('harExport'))
288
- har.save_as(@options[:recordHar][:path])
344
+ @har_recorders.each do |har_id, params|
345
+ har = ChannelOwners::Artifact.from(@channel.send_message_to_server('harExport', harId: har_id))
346
+ # Server side will compress artifact if content is attach or if file is .zip.
347
+ compressed = params[:content] == "attach" || params[:path].end_with?('.zip')
348
+ need_comppressed = params[:path].end_with?('.zip')
349
+ if compressed && !need_comppressed
350
+ tmp_path = "#{params[:path]}.tmp"
351
+ har.save_as(tmp_path)
352
+ @connection.local_utils.har_unzip(tmp_path, params[:path])
353
+ else
354
+ har.save_as(params[:path])
355
+ end
356
+
289
357
  har.delete
290
358
  end
291
359
  @channel.send_message_to_server('close')
@@ -13,6 +13,7 @@ module Playwright
13
13
  def launch(options, &block)
14
14
  resp = @channel.send_message_to_server('launch', options.compact)
15
15
  browser = ChannelOwners::Browser.from(resp)
16
+ browser.send(:update_browser_type, self)
16
17
  return browser unless block
17
18
 
18
19
  begin
@@ -29,6 +30,8 @@ module Playwright
29
30
 
30
31
  resp = @channel.send_message_to_server('launchPersistentContext', params.compact)
31
32
  context = ChannelOwners::Browser.from(resp)
33
+ context.options = params
34
+ context.send(:update_browser_type, self)
32
35
  return context unless block
33
36
 
34
37
  begin
@@ -54,6 +57,7 @@ module Playwright
54
57
 
55
58
  result = @channel.send_message_to_server_result('connectOverCDP', params)
56
59
  browser = ChannelOwners::Browser.from(result['browser'])
60
+ browser.send(:update_browser_type, self)
57
61
 
58
62
  if result['defaultContext']
59
63
  context = ChannelOwners::BrowserContext.from(result['defaultContext'])
@@ -25,11 +25,25 @@ module Playwright
25
25
  private def on_load_state(add:, remove:)
26
26
  if add
27
27
  @load_states << add
28
- @event_emitter.emit('loadstate', add)
28
+
29
+ # Original JS version of Playwright emit event here.
30
+ # @event_emitter.emit('loadstate', add)
29
31
  end
30
32
  if remove
31
33
  @load_states.delete(remove)
32
34
  end
35
+ unless @parent_frame
36
+ if add == 'load'
37
+ @page&.emit(Events::Page::Load, @page)
38
+ elsif add == 'domcontentloaded'
39
+ @page&.emit(Events::Page::DOMContentLoaded, @page)
40
+ end
41
+ end
42
+
43
+ # emit to waitForLoadState(load) listeners explicitly after waitForEvent(load) listeners
44
+ if add
45
+ @event_emitter.emit('loadstate', add)
46
+ end
33
47
  end
34
48
 
35
49
  private def on_frame_navigated(event)
@@ -38,7 +52,7 @@ module Playwright
38
52
  @event_emitter.emit('navigated', event)
39
53
 
40
54
  unless event['error']
41
- @page&.emit('framenavigated', self)
55
+ @page&.emit(Events::Page::FrameNavigated, self)
42
56
  end
43
57
  end
44
58
 
@@ -10,5 +10,34 @@ module Playwright
10
10
  @channel.send_message_to_server('zip', params)
11
11
  nil
12
12
  end
13
+
14
+
15
+ # @param file [String]
16
+ # @return [String] har ID
17
+ def har_open(file)
18
+ @channel.send_message_to_server('harOpen', file: file)
19
+ end
20
+
21
+ def har_lookup(har_id:, url:, method:, headers:, is_navigation_request:, post_data: nil)
22
+ params = {
23
+ harId: har_id,
24
+ url: url,
25
+ method: method,
26
+ headers: headers,
27
+ postData: post_data,
28
+ isNavigationRequest: is_navigation_request,
29
+ }.compact
30
+
31
+ @channel.send_message_to_server_result('harLookup', params)
32
+ end
33
+
34
+ # @param har_id [String]
35
+ def async_har_close(har_id)
36
+ @channel.async_send_message_to_server('harClose', harId: har_id)
37
+ end
38
+
39
+ def har_unzip(zip_file, har_file)
40
+ @channel.send_message_to_server('harUnzip', zipFile: zip_file, harFile: har_file)
41
+ end
13
42
  end
14
43
  end