playwright-ruby-client 1.22.0 → 1.23.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/documentation/docs/api/browser.md +16 -0
- data/documentation/docs/api/browser_context.md +15 -2
- data/documentation/docs/api/browser_type.md +4 -0
- data/documentation/docs/api/element_handle.md +0 -5
- data/documentation/docs/api/experimental/android_device.md +4 -0
- data/documentation/docs/api/locator.md +13 -6
- data/documentation/docs/api/page.md +14 -1
- data/documentation/docs/api/request.md +3 -1
- data/documentation/docs/api/response.md +12 -1
- data/documentation/docs/api/route.md +65 -0
- data/documentation/docs/include/api_coverage.md +5 -3
- data/lib/playwright/channel.rb +1 -3
- data/lib/playwright/channel_owners/browser.rb +13 -0
- data/lib/playwright/channel_owners/browser_context.rb +81 -13
- data/lib/playwright/channel_owners/browser_type.rb +4 -0
- data/lib/playwright/channel_owners/frame.rb +16 -2
- data/lib/playwright/channel_owners/local_utils.rb +29 -0
- data/lib/playwright/channel_owners/page.rb +43 -15
- data/lib/playwright/channel_owners/request.rb +31 -6
- data/lib/playwright/channel_owners/response.rb +6 -0
- data/lib/playwright/channel_owners/route.rb +104 -45
- data/lib/playwright/connection.rb +6 -1
- data/lib/playwright/har_router.rb +82 -0
- data/lib/playwright/http_headers.rb +1 -1
- data/lib/playwright/javascript/regex.rb +23 -0
- data/lib/playwright/javascript/value_serializer.rb +3 -4
- data/lib/playwright/javascript.rb +1 -0
- data/lib/playwright/locator_impl.rb +3 -5
- data/lib/playwright/route_handler.rb +2 -6
- data/lib/playwright/utils.rb +31 -6
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright.rb +2 -0
- data/lib/playwright_api/android_device.rb +5 -1
- data/lib/playwright_api/browser.rb +15 -2
- data/lib/playwright_api/browser_context.rb +16 -6
- data/lib/playwright_api/browser_type.rb +5 -1
- data/lib/playwright_api/element_handle.rb +0 -11
- data/lib/playwright_api/locator.rb +11 -12
- data/lib/playwright_api/page.rb +16 -6
- data/lib/playwright_api/request.rb +8 -1
- data/lib/playwright_api/response.rb +14 -1
- data/lib/playwright_api/route.rb +61 -2
- data/lib/playwright_api/worker.rb +4 -4
- metadata +5 -4
- data/lib/playwright_api/local_utils.rb +0 -9
@@ -39,7 +39,6 @@ module Playwright
|
|
39
39
|
})
|
40
40
|
@channel.on('crash', ->(_) { emit(Events::Page::Crash) })
|
41
41
|
@channel.on('dialog', method(:on_dialog))
|
42
|
-
@channel.on('domcontentloaded', ->(_) { emit(Events::Page::DOMContentLoaded) })
|
43
42
|
@channel.on('download', method(:on_download))
|
44
43
|
@channel.on('fileChooser', ->(params) {
|
45
44
|
chooser = FileChooserImpl.new(
|
@@ -54,12 +53,15 @@ module Playwright
|
|
54
53
|
@channel.on('frameDetached', ->(params) {
|
55
54
|
on_frame_detached(ChannelOwners::Frame.from(params['frame']))
|
56
55
|
})
|
57
|
-
@channel.on('load', ->(_) { emit(Events::Page::Load) })
|
58
56
|
@channel.on('pageError', ->(params) {
|
59
57
|
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
60
58
|
})
|
61
59
|
@channel.on('route', ->(params) {
|
62
|
-
|
60
|
+
Concurrent::Promises.future {
|
61
|
+
on_route(ChannelOwners::Route.from(params['route']), ChannelOwners::Request.from(params['request']))
|
62
|
+
}.rescue do |err|
|
63
|
+
puts err, err.backtrace
|
64
|
+
end
|
63
65
|
})
|
64
66
|
@channel.on('video', method(:on_video))
|
65
67
|
@channel.on('webSocket', ->(params) {
|
@@ -98,18 +100,26 @@ module Playwright
|
|
98
100
|
wrapped_route = PlaywrightApi.wrap(route)
|
99
101
|
wrapped_request = PlaywrightApi.wrap(request)
|
100
102
|
|
101
|
-
|
102
|
-
|
103
|
+
handled = @routes.any? do |handler_entry|
|
104
|
+
next false unless handler_entry.match?(request.url)
|
105
|
+
|
106
|
+
promise = Concurrent::Promises.resolvable_future
|
107
|
+
route.send(:set_handling_future, promise)
|
108
|
+
|
109
|
+
promise_handled = Concurrent::Promises.zip(
|
110
|
+
promise,
|
111
|
+
handler_entry.async_handle(wrapped_route, wrapped_request)
|
112
|
+
).value!.first
|
113
|
+
|
114
|
+
promise_handled
|
103
115
|
end
|
104
116
|
|
105
|
-
|
106
|
-
|
117
|
+
@routes.reject!(&:expired?)
|
118
|
+
if @routes.count == 0
|
119
|
+
@channel.async_send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
120
|
+
end
|
107
121
|
|
108
|
-
|
109
|
-
if @routes.count == 0
|
110
|
-
@channel.async_send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
111
|
-
end
|
112
|
-
else
|
122
|
+
unless handled
|
113
123
|
@browser_context.send(:on_route, route, request)
|
114
124
|
end
|
115
125
|
end
|
@@ -407,6 +417,21 @@ module Playwright
|
|
407
417
|
end
|
408
418
|
end
|
409
419
|
|
420
|
+
def route_from_har(har, notFound: nil, update: nil, url: nil)
|
421
|
+
if update
|
422
|
+
@browser_context.send(:record_into_har, har, self, notFound: notFound, url: url)
|
423
|
+
return
|
424
|
+
end
|
425
|
+
|
426
|
+
router = HarRouter.create(
|
427
|
+
@connection.local_utils,
|
428
|
+
har.to_s,
|
429
|
+
notFound || "abort",
|
430
|
+
url_match: url,
|
431
|
+
)
|
432
|
+
router.add_page_route(self)
|
433
|
+
end
|
434
|
+
|
410
435
|
def screenshot(
|
411
436
|
animations: nil,
|
412
437
|
caret: nil,
|
@@ -451,9 +476,12 @@ module Playwright
|
|
451
476
|
end
|
452
477
|
|
453
478
|
def close(runBeforeUnload: nil)
|
454
|
-
|
455
|
-
|
456
|
-
|
479
|
+
if @owned_context
|
480
|
+
@owned_context.close
|
481
|
+
else
|
482
|
+
options = { runBeforeUnload: runBeforeUnload }.compact
|
483
|
+
@channel.send_message_to_server('close', options)
|
484
|
+
end
|
457
485
|
nil
|
458
486
|
rescue => err
|
459
487
|
raise unless safe_close_error?(err)
|
@@ -18,10 +18,24 @@ module Playwright
|
|
18
18
|
responseStart: -1,
|
19
19
|
responseEnd: -1,
|
20
20
|
}
|
21
|
+
@fallback_overrides = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
private def fallback_overrides
|
25
|
+
@fallback_overrides
|
26
|
+
end
|
27
|
+
|
28
|
+
def apply_fallback_overrides(overrides)
|
29
|
+
allowed_key = %i[url method headers postData]
|
30
|
+
overrides.each do |key, value|
|
31
|
+
raise ArgumentError.new("invalid key: #{key}") unless allowed_key.include?(key)
|
32
|
+
@fallback_overrides[key] = value
|
33
|
+
end
|
34
|
+
@fallback_overrides
|
21
35
|
end
|
22
36
|
|
23
37
|
def url
|
24
|
-
@initializer['url']
|
38
|
+
@fallback_overrides[:url] || @initializer['url']
|
25
39
|
end
|
26
40
|
|
27
41
|
def resource_type
|
@@ -29,7 +43,7 @@ module Playwright
|
|
29
43
|
end
|
30
44
|
|
31
45
|
def method
|
32
|
-
@initializer['method']
|
46
|
+
@fallback_overrides[:method] || @initializer['method']
|
33
47
|
end
|
34
48
|
|
35
49
|
def post_data
|
@@ -51,8 +65,11 @@ module Playwright
|
|
51
65
|
end
|
52
66
|
|
53
67
|
def post_data_buffer
|
54
|
-
|
55
|
-
|
68
|
+
if (override = @fallback_overrides[:postData])
|
69
|
+
return override
|
70
|
+
end
|
71
|
+
|
72
|
+
if (base64_content = @initializer['postData'])
|
56
73
|
Base64.strict_decode64(base64_content)
|
57
74
|
else
|
58
75
|
nil
|
@@ -79,12 +96,20 @@ module Playwright
|
|
79
96
|
attr_reader :redirected_from, :redirected_to, :timing
|
80
97
|
|
81
98
|
def headers
|
82
|
-
@
|
99
|
+
if (override = @fallback_overrides[:headers])
|
100
|
+
RawHeaders.new(HttpHeaders.new(override).as_serialized).headers
|
101
|
+
else
|
102
|
+
@provisional_headers.headers
|
103
|
+
end
|
83
104
|
end
|
84
105
|
|
85
106
|
# @return [RawHeaders|nil]
|
86
107
|
private def actual_headers
|
87
|
-
|
108
|
+
if (override = @fallback_overrides[:headers])
|
109
|
+
RawHeaders.new(HttpHeaders.new(override).as_serialized)
|
110
|
+
else
|
111
|
+
@actual_headers ||= raw_request_headers
|
112
|
+
end
|
88
113
|
end
|
89
114
|
|
90
115
|
private def raw_request_headers
|
@@ -52,6 +52,12 @@ module Playwright
|
|
52
52
|
RawHeaders.new(@channel.send_message_to_server('rawResponseHeaders'))
|
53
53
|
end
|
54
54
|
|
55
|
+
def from_service_worker
|
56
|
+
@initializer['fromServiceWorker']
|
57
|
+
end
|
58
|
+
|
59
|
+
alias_method :from_service_worker?, :from_service_worker
|
60
|
+
|
55
61
|
def all_headers
|
56
62
|
actual_headers.headers
|
57
63
|
end
|
@@ -3,13 +3,28 @@ require 'mime/types'
|
|
3
3
|
|
4
4
|
module Playwright
|
5
5
|
define_channel_owner :Route do
|
6
|
+
private def set_handling_future(future)
|
7
|
+
@handling_future = future
|
8
|
+
end
|
9
|
+
|
10
|
+
private def handling_with_result(done, &block)
|
11
|
+
chain = @handling_future
|
12
|
+
raise 'Route is already handled!' unless chain
|
13
|
+
block.call
|
14
|
+
@handling_future = nil
|
15
|
+
chain.fulfill(done)
|
16
|
+
end
|
17
|
+
|
6
18
|
def request
|
7
19
|
ChannelOwners::Request.from(@initializer['request'])
|
8
20
|
end
|
9
21
|
|
10
22
|
def abort(errorCode: nil)
|
11
|
-
|
12
|
-
|
23
|
+
handling_with_result(true) do
|
24
|
+
params = { errorCode: errorCode }.compact
|
25
|
+
# TODO _race_with_page_close
|
26
|
+
@channel.async_send_message_to_server('abort', params)
|
27
|
+
end
|
13
28
|
end
|
14
29
|
|
15
30
|
def fulfill(
|
@@ -19,69 +34,113 @@ module Playwright
|
|
19
34
|
path: nil,
|
20
35
|
status: nil,
|
21
36
|
response: nil)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
handling_with_result(true) do
|
38
|
+
params = {
|
39
|
+
contentType: contentType,
|
40
|
+
status: status,
|
41
|
+
}.compact
|
42
|
+
option_body = body
|
27
43
|
|
28
|
-
|
29
|
-
|
30
|
-
|
44
|
+
if response
|
45
|
+
params[:status] ||= response.status
|
46
|
+
params[:headers] ||= response.headers
|
31
47
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
48
|
+
if !body && !path && response.is_a?(APIResponse)
|
49
|
+
if response.send(:_request).send(:same_connection?, self)
|
50
|
+
params[:fetchResponseUid] = response.send(:fetch_uid)
|
51
|
+
else
|
52
|
+
option_body = response.body
|
53
|
+
end
|
37
54
|
end
|
38
55
|
end
|
39
|
-
end
|
40
56
|
|
41
|
-
|
42
|
-
|
43
|
-
|
57
|
+
content =
|
58
|
+
if option_body
|
59
|
+
option_body
|
60
|
+
elsif path
|
61
|
+
File.read(path)
|
62
|
+
else
|
63
|
+
nil
|
64
|
+
end
|
65
|
+
|
66
|
+
param_headers = headers || {}
|
67
|
+
if contentType
|
68
|
+
param_headers['content-type'] = contentType
|
44
69
|
elsif path
|
45
|
-
|
46
|
-
else
|
47
|
-
nil
|
70
|
+
param_headers['content-type'] = mime_type_for(path)
|
48
71
|
end
|
49
72
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
params[:body] = content
|
60
|
-
params[:isBase64] = false
|
61
|
-
else
|
62
|
-
params[:body] = Base64.strict_encode64(content)
|
63
|
-
params[:isBase64] = true
|
73
|
+
if content
|
74
|
+
if content.is_a?(String)
|
75
|
+
params[:body] = content
|
76
|
+
params[:isBase64] = false
|
77
|
+
else
|
78
|
+
params[:body] = Base64.strict_encode64(content)
|
79
|
+
params[:isBase64] = true
|
80
|
+
end
|
81
|
+
param_headers['content-length'] ||= content.length.to_s
|
64
82
|
end
|
65
|
-
|
83
|
+
|
84
|
+
params[:headers] = HttpHeaders.new(param_headers).as_serialized
|
85
|
+
|
86
|
+
@channel.async_send_message_to_server('fulfill', params)
|
66
87
|
end
|
88
|
+
end
|
67
89
|
|
68
|
-
|
90
|
+
def fallback(headers: nil, method: nil, postData: nil, url: nil)
|
91
|
+
overrides = {
|
92
|
+
headers: headers,
|
93
|
+
method: method,
|
94
|
+
postData: postData,
|
95
|
+
url: url,
|
96
|
+
}.compact
|
69
97
|
|
70
|
-
|
98
|
+
handling_with_result(false) do
|
99
|
+
request.apply_fallback_overrides(overrides)
|
100
|
+
end
|
71
101
|
end
|
72
102
|
|
73
103
|
def continue(headers: nil, method: nil, postData: nil, url: nil)
|
74
|
-
overrides = {
|
104
|
+
overrides = {
|
105
|
+
headers: headers,
|
106
|
+
method: method,
|
107
|
+
postData: postData,
|
108
|
+
url: url,
|
109
|
+
}.compact
|
75
110
|
|
76
|
-
|
77
|
-
|
111
|
+
handling_with_result(true) do
|
112
|
+
request.apply_fallback_overrides(overrides)
|
113
|
+
async_continue_route
|
78
114
|
end
|
115
|
+
end
|
79
116
|
|
80
|
-
|
81
|
-
|
117
|
+
private def async_continue_route
|
118
|
+
post_data_for_wire =
|
119
|
+
if (post_data_from_overrides = request.send(:fallback_overrides)[:postData])
|
120
|
+
post_data_for_wire = Base64.strict_encode64(post_data_from_overrides)
|
121
|
+
else
|
122
|
+
nil
|
123
|
+
end
|
124
|
+
|
125
|
+
params = request.send(:fallback_overrides).dup
|
126
|
+
|
127
|
+
if params[:headers]
|
128
|
+
params[:headers] = HttpHeaders.new(params[:headers]).as_serialized
|
129
|
+
end
|
130
|
+
|
131
|
+
if post_data_for_wire
|
132
|
+
params[:postData] = post_data_for_wire
|
82
133
|
end
|
83
134
|
|
84
|
-
|
135
|
+
# TODO _race_with_page_close
|
136
|
+
@channel.async_send_message_to_server('continue', params)
|
137
|
+
end
|
138
|
+
|
139
|
+
def redirect_navigation_request(url)
|
140
|
+
handling_with_result(true) do
|
141
|
+
# TODO _race_with_page_close
|
142
|
+
@channel.send_message_to_server('redirectNavigationRequest', { url: url })
|
143
|
+
end
|
85
144
|
end
|
86
145
|
|
87
146
|
private def mime_type_for(filepath)
|
@@ -24,6 +24,8 @@ module Playwright
|
|
24
24
|
@remote = false
|
25
25
|
end
|
26
26
|
|
27
|
+
attr_reader :local_utils
|
28
|
+
|
27
29
|
def mark_as_remote
|
28
30
|
@remote = true
|
29
31
|
end
|
@@ -127,12 +129,15 @@ module Playwright
|
|
127
129
|
params = msg['params']
|
128
130
|
|
129
131
|
if method == "__create__"
|
130
|
-
create_remote_object(
|
132
|
+
remote_object = create_remote_object(
|
131
133
|
parent_guid: guid,
|
132
134
|
type: params["type"],
|
133
135
|
guid: params["guid"],
|
134
136
|
initializer: params["initializer"],
|
135
137
|
)
|
138
|
+
if remote_object.is_a?(ChannelOwners::LocalUtils)
|
139
|
+
@local_utils = remote_object
|
140
|
+
end
|
136
141
|
return
|
137
142
|
end
|
138
143
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Playwright
|
2
|
+
class HarRouter
|
3
|
+
# @param local_utils [LocalUtils]
|
4
|
+
# @param file [String]
|
5
|
+
# @param not_found_action [String] 'abort' or 'fallback'
|
6
|
+
# @param url_match [String||Regexp|nil]
|
7
|
+
def self.create(local_utils, file, not_found_action, url_match: nil)
|
8
|
+
har_id = local_utils.har_open(file)
|
9
|
+
|
10
|
+
new(
|
11
|
+
local_utils: local_utils,
|
12
|
+
har_id: har_id,
|
13
|
+
not_found_action: not_found_action,
|
14
|
+
url_match: url_match,
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param local_utils [LocalUtils]
|
19
|
+
# @param har_id [String]
|
20
|
+
# @param not_found_action [String] 'abort' or 'fallback'
|
21
|
+
# @param url_match [String||Regexp|nil]
|
22
|
+
def initialize(local_utils:, har_id:, not_found_action:, url_match: nil)
|
23
|
+
unless ['abort', 'fallback'].include?(not_found_action)
|
24
|
+
raise ArgumentError.new("not_found_action must be either 'abort' or 'fallback'. '#{not_found_action}' is specified.")
|
25
|
+
end
|
26
|
+
|
27
|
+
@local_utils = local_utils
|
28
|
+
@har_id = har_id
|
29
|
+
@not_found_action = not_found_action
|
30
|
+
@url_match = url_match || '**/*'
|
31
|
+
@debug = ENV['DEBUG'].to_s == 'true' || ENV['DEBUG'].to_s == '1'
|
32
|
+
end
|
33
|
+
|
34
|
+
private def handle(route, request)
|
35
|
+
response = @local_utils.har_lookup(
|
36
|
+
har_id: @har_id,
|
37
|
+
url: request.url,
|
38
|
+
method: request.method,
|
39
|
+
headers: request.headers_array,
|
40
|
+
post_data: request.post_data_buffer,
|
41
|
+
is_navigation_request: request.navigation_request?,
|
42
|
+
)
|
43
|
+
case response['action']
|
44
|
+
when 'redirect'
|
45
|
+
redirect_url = response['redirectURL']
|
46
|
+
puts "pw:api HAR: #{request.url} redirected to #{redirect_url}" if @debug
|
47
|
+
route.redirect_navigation_request(redirect_url)
|
48
|
+
when 'fulfill'
|
49
|
+
route.fulfill(
|
50
|
+
status: response['status'],
|
51
|
+
headers: response['headers'].map { |header| [header['name'], header['value']] }.to_h,
|
52
|
+
body: Base64.strict_decode64(response['body']),
|
53
|
+
)
|
54
|
+
else
|
55
|
+
# Report the error, but fall through to the default handler.
|
56
|
+
if response['action'] == 'error'
|
57
|
+
puts "pw:api HAR: #{response['message']} redirected to #{redirect_url}" if @debug
|
58
|
+
end
|
59
|
+
|
60
|
+
if @not_found_action == 'abort'
|
61
|
+
route.abort
|
62
|
+
else
|
63
|
+
route.fallback
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_context_route(context)
|
69
|
+
context.route(@url_match, method(:handle))
|
70
|
+
context.once(Events::BrowserContext::Close, method(:dispose))
|
71
|
+
end
|
72
|
+
|
73
|
+
def add_page_route(page)
|
74
|
+
page.route(@url_match, method(:handle))
|
75
|
+
page.once(Events::Page::Close, method(:dispose))
|
76
|
+
end
|
77
|
+
|
78
|
+
def dispose
|
79
|
+
@local_utils.async_har_close(@har_id)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Playwright
|
2
|
+
module JavaScript
|
3
|
+
class Regex
|
4
|
+
def initialize(regexp)
|
5
|
+
unless regexp.is_a?(Regexp)
|
6
|
+
raise ArgumentError("Argument must be a Regexp: #{regexp} (#{regexp.class})")
|
7
|
+
end
|
8
|
+
|
9
|
+
@source = regexp.source
|
10
|
+
@flag = flag_for(regexp)
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :source, :flag
|
14
|
+
|
15
|
+
private def flag_for(regexp)
|
16
|
+
flags = []
|
17
|
+
flags << 'ms' if (regexp.options & Regexp::MULTILINE) != 0
|
18
|
+
flags << 'i' if (regexp.options & Regexp::IGNORECASE) != 0
|
19
|
+
flags.join('')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require_relative './visitor_info'
|
2
|
+
require_relative './regex'
|
2
3
|
|
3
4
|
module Playwright
|
4
5
|
module JavaScript
|
@@ -40,10 +41,8 @@ module Playwright
|
|
40
41
|
require 'time'
|
41
42
|
{ d: value.utc.iso8601 }
|
42
43
|
when Regexp
|
43
|
-
|
44
|
-
|
45
|
-
flags << 'i' if (value.options & Regexp::IGNORECASE) != 0
|
46
|
-
{ r: { p: value.source, f: flags.join('') } }
|
44
|
+
regex_value = Regex.new(value)
|
45
|
+
{ r: { p: regex_value.source, f: regex_value.flag } }
|
47
46
|
when -> (value) { @visited.ref(value) }
|
48
47
|
{ ref: @visited.ref(value) }
|
49
48
|
when Array
|
@@ -31,11 +31,9 @@ module Playwright
|
|
31
31
|
|
32
32
|
case hasText
|
33
33
|
when Regexp
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
flags << 'i' if (hasText.options & Regexp::IGNORECASE) != 0
|
38
|
-
selector_scopes << ":scope:text-matches(#{source}, \"#{flags.join('')}\")"
|
34
|
+
regex = JavaScript::Regex.new(hasText)
|
35
|
+
source = EscapeWithQuotes.new(regex.source, '"')
|
36
|
+
selector_scopes << ":scope:text-matches(#{source}, \"#{regex.flag}\")"
|
39
37
|
when String
|
40
38
|
text = EscapeWithQuotes.new(hasText, '"')
|
41
39
|
selector_scopes << ":scope:has-text(#{text})"
|
@@ -50,12 +50,8 @@ module Playwright
|
|
50
50
|
def async_handle(route, request)
|
51
51
|
@counter.increment
|
52
52
|
|
53
|
-
Concurrent::Promises.future do
|
54
|
-
|
55
|
-
@handler.call(route, request)
|
56
|
-
rescue => err
|
57
|
-
puts err, err.backtrace
|
58
|
-
end
|
53
|
+
Concurrent::Promises.future { @handler.call(route, request) }.rescue do |err|
|
54
|
+
puts err, err.backtrace
|
59
55
|
end
|
60
56
|
end
|
61
57
|
|
data/lib/playwright/utils.rb
CHANGED
@@ -1,6 +1,36 @@
|
|
1
1
|
module Playwright
|
2
2
|
module Utils
|
3
3
|
module PrepareBrowserContextOptions
|
4
|
+
private def prepare_record_har_options(params)
|
5
|
+
out_params = {
|
6
|
+
path: params.delete(:record_har_path)
|
7
|
+
}
|
8
|
+
if params[:record_har_url_filter]
|
9
|
+
opt = params.delete(:record_har_url_filter)
|
10
|
+
if opt.is_a?(Regexp)
|
11
|
+
regex = ::Playwright::JavaScript::Regex.new(opt)
|
12
|
+
out_params[:urlRegexSource] = regex.source
|
13
|
+
out_params[:urlRegexFlags] = regex.flag
|
14
|
+
elsif opt.is_a?(String)
|
15
|
+
out_params[:urlGlob] = opt
|
16
|
+
end
|
17
|
+
end
|
18
|
+
if params[:record_har_mode]
|
19
|
+
out_params[:mode] = params.delete(:record_har_mode)
|
20
|
+
end
|
21
|
+
if params[:record_har_content]
|
22
|
+
out_params[:content] = params.delete(:record_har_content)
|
23
|
+
end
|
24
|
+
if params[:record_har_omit_content]
|
25
|
+
old_api_omit_content = params.delete(:record_har_omit_content)
|
26
|
+
if old_api_omit_content
|
27
|
+
out_params[:content] ||= 'omit'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
out_params
|
32
|
+
end
|
33
|
+
|
4
34
|
# @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
|
5
35
|
private def prepare_browser_context_options(params)
|
6
36
|
if params[:noViewport] == 0
|
@@ -11,12 +41,7 @@ module Playwright
|
|
11
41
|
params[:extraHTTPHeaders] = ::Playwright::HttpHeaders.new(params[:extraHTTPHeaders]).as_serialized
|
12
42
|
end
|
13
43
|
if params[:record_har_path]
|
14
|
-
params[:recordHar] =
|
15
|
-
path: params.delete(:record_har_path)
|
16
|
-
}
|
17
|
-
if params[:record_har_omit_content]
|
18
|
-
params[:recordHar][:omitContent] = params.delete(:record_har_omit_content)
|
19
|
-
end
|
44
|
+
params[:recordHar] = prepare_record_har_options(params)
|
20
45
|
end
|
21
46
|
if params[:record_video_dir]
|
22
47
|
params[:recordVideo] = {
|
data/lib/playwright/version.rb
CHANGED
data/lib/playwright.rb
CHANGED
@@ -20,6 +20,7 @@ require 'playwright/channel_owner'
|
|
20
20
|
require 'playwright/http_headers'
|
21
21
|
require 'playwright/input_files'
|
22
22
|
require 'playwright/connection'
|
23
|
+
require 'playwright/har_router'
|
23
24
|
require 'playwright/raw_headers'
|
24
25
|
require 'playwright/route_handler'
|
25
26
|
require 'playwright/select_option_values'
|
@@ -143,6 +144,7 @@ module Playwright
|
|
143
144
|
playwright = connection.initialize_playwright
|
144
145
|
browser = playwright.send(:pre_launched_browser)
|
145
146
|
browser.should_close_connection_on_close!
|
147
|
+
browser.send(:update_browser_type, browser.browser_type)
|
146
148
|
Execution.new(connection, PlaywrightApi.wrap(playwright), PlaywrightApi.wrap(browser))
|
147
149
|
rescue
|
148
150
|
connection.stop
|
@@ -57,18 +57,22 @@ module Playwright
|
|
57
57
|
noViewport: nil,
|
58
58
|
offline: nil,
|
59
59
|
permissions: nil,
|
60
|
+
record_har_content: nil,
|
61
|
+
record_har_mode: nil,
|
60
62
|
record_har_omit_content: nil,
|
61
63
|
record_har_path: nil,
|
64
|
+
record_har_url_filter: nil,
|
62
65
|
record_video_dir: nil,
|
63
66
|
record_video_size: nil,
|
64
67
|
reducedMotion: nil,
|
65
68
|
screen: nil,
|
69
|
+
serviceWorkers: nil,
|
66
70
|
strictSelectors: nil,
|
67
71
|
timezoneId: nil,
|
68
72
|
userAgent: nil,
|
69
73
|
viewport: nil,
|
70
74
|
&block)
|
71
|
-
wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), command: unwrap_impl(command), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), forcedColors: unwrap_impl(forcedColors), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), strictSelectors: unwrap_impl(strictSelectors), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
|
75
|
+
wrap_impl(@impl.launch_browser(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), colorScheme: unwrap_impl(colorScheme), command: unwrap_impl(command), deviceScaleFactor: unwrap_impl(deviceScaleFactor), extraHTTPHeaders: unwrap_impl(extraHTTPHeaders), forcedColors: unwrap_impl(forcedColors), geolocation: unwrap_impl(geolocation), hasTouch: unwrap_impl(hasTouch), httpCredentials: unwrap_impl(httpCredentials), ignoreHTTPSErrors: unwrap_impl(ignoreHTTPSErrors), isMobile: unwrap_impl(isMobile), javaScriptEnabled: unwrap_impl(javaScriptEnabled), locale: unwrap_impl(locale), noViewport: unwrap_impl(noViewport), offline: unwrap_impl(offline), permissions: unwrap_impl(permissions), record_har_content: unwrap_impl(record_har_content), record_har_mode: unwrap_impl(record_har_mode), record_har_omit_content: unwrap_impl(record_har_omit_content), record_har_path: unwrap_impl(record_har_path), record_har_url_filter: unwrap_impl(record_har_url_filter), record_video_dir: unwrap_impl(record_video_dir), record_video_size: unwrap_impl(record_video_size), reducedMotion: unwrap_impl(reducedMotion), screen: unwrap_impl(screen), serviceWorkers: unwrap_impl(serviceWorkers), strictSelectors: unwrap_impl(strictSelectors), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
|
72
76
|
end
|
73
77
|
|
74
78
|
# Performs a long tap on the widget defined by `selector`.
|