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
|
@@ -11,9 +11,8 @@ module Playwright
|
|
|
11
11
|
dispatch(message)
|
|
12
12
|
end
|
|
13
13
|
@transport.on_driver_crashed do
|
|
14
|
-
@callbacks.
|
|
15
|
-
|
|
16
|
-
end
|
|
14
|
+
callbacks = @callbacks_mutex.synchronize { @callbacks.values }
|
|
15
|
+
callbacks.each { |callback| callback.reject(::Playwright::DriverCrashedError.new) }
|
|
17
16
|
raise ::Playwright::DriverCrashedError.new
|
|
18
17
|
end
|
|
19
18
|
@transport.on_driver_closed do
|
|
@@ -21,8 +20,10 @@ module Playwright
|
|
|
21
20
|
end
|
|
22
21
|
|
|
23
22
|
@objects = {} # Hash[ guid => ChannelOwner ]
|
|
23
|
+
@objects_mutex = Mutex.new
|
|
24
24
|
@waiting_for_object = {} # Hash[ guid => Promise<ChannelOwner> ]
|
|
25
25
|
@callbacks = {} # Hash [ guid => Promise<ChannelOwner> ]
|
|
26
|
+
@callbacks_mutex = Mutex.new
|
|
26
27
|
@root_object = RootChannelOwner.new(self)
|
|
27
28
|
@remote = false
|
|
28
29
|
@tracing_count = 0
|
|
@@ -50,10 +51,10 @@ module Playwright
|
|
|
50
51
|
|
|
51
52
|
def cleanup(cause: nil)
|
|
52
53
|
@closed_error = TargetClosedError.new(message: cause)
|
|
53
|
-
@
|
|
54
|
-
|
|
54
|
+
callbacks = @callbacks_mutex.synchronize do
|
|
55
|
+
@callbacks.values.tap { @callbacks.clear }
|
|
55
56
|
end
|
|
56
|
-
|
|
57
|
+
callbacks.each { |callback| callback.reject(@closed_error) }
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
def initialize_playwright
|
|
@@ -80,7 +81,7 @@ module Playwright
|
|
|
80
81
|
with_generated_id do |id|
|
|
81
82
|
# register callback promise object first.
|
|
82
83
|
# @see https://github.com/YusukeIwaki/puppeteer-ruby/pull/34
|
|
83
|
-
@callbacks[id] = callback
|
|
84
|
+
@callbacks_mutex.synchronize { @callbacks[id] = callback }
|
|
84
85
|
|
|
85
86
|
_metadata = {}
|
|
86
87
|
frames = []
|
|
@@ -107,12 +108,12 @@ module Playwright
|
|
|
107
108
|
begin
|
|
108
109
|
@transport.send_message(message)
|
|
109
110
|
rescue => err
|
|
110
|
-
@callbacks.delete(id)
|
|
111
|
+
@callbacks_mutex.synchronize { @callbacks.delete(id) }
|
|
111
112
|
callback.reject(err)
|
|
112
113
|
raise unless err.is_a?(Transport::AlreadyDisconnectedError)
|
|
113
114
|
end
|
|
114
115
|
|
|
115
|
-
if @tracing_count > 0 && !frames.empty? && guid != 'localUtils'
|
|
116
|
+
if @tracing_count > 0 && !frames.empty? && guid != 'localUtils' && !remote?
|
|
116
117
|
@local_utils.add_stack_to_tracing_no_reply(id, frames)
|
|
117
118
|
end
|
|
118
119
|
end
|
|
@@ -132,21 +133,24 @@ module Playwright
|
|
|
132
133
|
# end
|
|
133
134
|
# ````
|
|
134
135
|
def with_generated_id(&block)
|
|
135
|
-
@
|
|
136
|
-
|
|
136
|
+
id = @callbacks_mutex.synchronize do
|
|
137
|
+
@last_id ||= 0
|
|
138
|
+
@last_id += 1
|
|
139
|
+
end
|
|
140
|
+
block.call(id)
|
|
137
141
|
end
|
|
138
142
|
|
|
139
143
|
# @param guid [String]
|
|
140
144
|
# @param parent [Playwright::ChannelOwner]
|
|
141
145
|
# @note This method should be used internally. Accessed via .send method from Playwright::ChannelOwner, so keep private!
|
|
142
146
|
def update_object_from_channel_owner(guid, parent)
|
|
143
|
-
@objects[guid] = parent
|
|
147
|
+
@objects_mutex.synchronize { @objects[guid] = parent }
|
|
144
148
|
end
|
|
145
149
|
|
|
146
150
|
# @param guid [String]
|
|
147
151
|
# @note This method should be used internally. Accessed via .send method from Playwright::ChannelOwner, so keep private!
|
|
148
152
|
def delete_object_from_channel_owner(guid)
|
|
149
|
-
@objects.delete(guid)
|
|
153
|
+
@objects_mutex.synchronize { @objects.delete(guid) }
|
|
150
154
|
end
|
|
151
155
|
|
|
152
156
|
def dispatch(msg)
|
|
@@ -154,7 +158,7 @@ module Playwright
|
|
|
154
158
|
|
|
155
159
|
id = msg['id']
|
|
156
160
|
if id
|
|
157
|
-
callback = @callbacks.delete(id)
|
|
161
|
+
callback = @callbacks_mutex.synchronize { @callbacks.delete(id) }
|
|
158
162
|
|
|
159
163
|
unless callback
|
|
160
164
|
raise "Cannot find command to respond: #{id}"
|
|
@@ -190,13 +194,13 @@ module Playwright
|
|
|
190
194
|
return
|
|
191
195
|
end
|
|
192
196
|
|
|
193
|
-
object = @objects[guid]
|
|
197
|
+
object = @objects_mutex.synchronize { @objects[guid] }
|
|
194
198
|
unless object
|
|
195
199
|
raise "Cannot find object to \"#{method}\": #{guid}"
|
|
196
200
|
end
|
|
197
201
|
|
|
198
202
|
if method == "__adopt__"
|
|
199
|
-
child = @objects[params["guid"]]
|
|
203
|
+
child = @objects_mutex.synchronize { @objects[params["guid"]] }
|
|
200
204
|
unless child
|
|
201
205
|
raise "Unknown new child: #{params['guid']}"
|
|
202
206
|
end
|
|
@@ -243,8 +247,9 @@ module Playwright
|
|
|
243
247
|
|
|
244
248
|
if payload.is_a?(Hash)
|
|
245
249
|
guid = payload['guid']
|
|
246
|
-
if guid
|
|
247
|
-
|
|
250
|
+
if guid
|
|
251
|
+
object = @objects_mutex.synchronize { @objects[guid] }
|
|
252
|
+
return object.channel if object
|
|
248
253
|
end
|
|
249
254
|
|
|
250
255
|
return payload.map { |k, v| [k, replace_guids_with_channels(v)] }.to_h
|
|
@@ -255,7 +260,7 @@ module Playwright
|
|
|
255
260
|
|
|
256
261
|
# @return [Playwright::ChannelOwner|nil]
|
|
257
262
|
def create_remote_object(parent_guid:, type:, guid:, initializer:)
|
|
258
|
-
parent = @objects[parent_guid]
|
|
263
|
+
parent = @objects_mutex.synchronize { @objects[parent_guid] }
|
|
259
264
|
unless parent
|
|
260
265
|
raise "Cannot find parent object #{parent_guid} to create #{guid}"
|
|
261
266
|
end
|
|
@@ -273,7 +278,7 @@ module Playwright
|
|
|
273
278
|
raise "Missing type #{type}"
|
|
274
279
|
end
|
|
275
280
|
|
|
276
|
-
callback = @waiting_for_object.delete(guid)
|
|
281
|
+
callback = @objects_mutex.synchronize { @waiting_for_object.delete(guid) }
|
|
277
282
|
callback&.fulfill(result)
|
|
278
283
|
|
|
279
284
|
result
|
|
@@ -53,9 +53,10 @@ module Playwright
|
|
|
53
53
|
# test when HAR was recorded but we'd abort it immediately.
|
|
54
54
|
return if response['status'] == -1
|
|
55
55
|
|
|
56
|
+
headers = merge_har_response_headers(response['headers'])
|
|
56
57
|
route.fulfill(
|
|
57
58
|
status: response['status'],
|
|
58
|
-
headers:
|
|
59
|
+
headers: headers,
|
|
59
60
|
body: Base64.strict_decode64(response['body']),
|
|
60
61
|
)
|
|
61
62
|
else
|
|
@@ -82,6 +83,20 @@ module Playwright
|
|
|
82
83
|
page.once(Events::Page::Close, method(:dispose))
|
|
83
84
|
end
|
|
84
85
|
|
|
86
|
+
private def merge_har_response_headers(headers)
|
|
87
|
+
headers.each_with_object({}) do |header, merged|
|
|
88
|
+
name = header['name']
|
|
89
|
+
value = header['value']
|
|
90
|
+
|
|
91
|
+
if name.casecmp('set-cookie').zero?
|
|
92
|
+
key = merged.keys.find { |existing| existing.casecmp('set-cookie').zero? } || name
|
|
93
|
+
merged[key] = merged[key] ? "#{merged[key]}\n#{value}" : value
|
|
94
|
+
else
|
|
95
|
+
merged[name] = value
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
85
100
|
def dispose
|
|
86
101
|
@local_utils.async_har_close(@har_id)
|
|
87
102
|
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require_relative './visitor_info'
|
|
2
2
|
require_relative './regex'
|
|
3
|
+
require 'uri'
|
|
3
4
|
|
|
4
5
|
module Playwright
|
|
5
6
|
module JavaScript
|
|
@@ -60,7 +61,7 @@ module Playwright
|
|
|
60
61
|
when Time
|
|
61
62
|
require 'time'
|
|
62
63
|
{ d: value.utc.iso8601 }
|
|
63
|
-
when URI
|
|
64
|
+
when ::URI
|
|
64
65
|
{ u: value.to_s }
|
|
65
66
|
when Regexp
|
|
66
67
|
regex_value = Regex.new(value)
|
|
@@ -21,7 +21,7 @@ module Playwright
|
|
|
21
21
|
private def expect_impl(expression, expect_options, expected, message, title)
|
|
22
22
|
expect_options[:timeout] ||= @default_expect_timeout
|
|
23
23
|
expect_options[:isNot] = @is_not
|
|
24
|
-
message.gsub
|
|
24
|
+
message = message.gsub("expected to", "not expected to") if @is_not
|
|
25
25
|
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
|
26
26
|
|
|
27
27
|
result = @locator.expect(expression, expect_options, title)
|
|
@@ -426,11 +426,27 @@ module Playwright
|
|
|
426
426
|
end
|
|
427
427
|
end
|
|
428
428
|
|
|
429
|
-
def aria_snapshot(timeout: nil)
|
|
430
|
-
|
|
429
|
+
def aria_snapshot(depth: nil, mode: nil, timeout: nil, _track: nil)
|
|
430
|
+
params = {
|
|
431
431
|
selector: @selector,
|
|
432
432
|
timeout: _timeout(timeout),
|
|
433
|
-
}
|
|
433
|
+
}
|
|
434
|
+
params[:depth] = depth if depth
|
|
435
|
+
params[:mode] = mode if mode
|
|
436
|
+
if _track
|
|
437
|
+
params.delete(:selector)
|
|
438
|
+
params[:track] = _track
|
|
439
|
+
end
|
|
440
|
+
result = @frame.channel.send_message_to_server_result('ariaSnapshot', params.compact)
|
|
441
|
+
result['snapshot']
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
def normalize
|
|
445
|
+
resolved_selector = @frame.channel.send_message_to_server('resolveSelector', { selector: @selector })
|
|
446
|
+
LocatorImpl.new(
|
|
447
|
+
frame: @frame,
|
|
448
|
+
selector: resolved_selector,
|
|
449
|
+
)
|
|
434
450
|
end
|
|
435
451
|
|
|
436
452
|
def scroll_into_view_if_needed(timeout: nil)
|
|
@@ -22,7 +22,7 @@ module Playwright
|
|
|
22
22
|
private def expect_impl(expression, expect_options, expected, message, title)
|
|
23
23
|
expect_options[:timeout] ||= @default_expect_timeout
|
|
24
24
|
expect_options[:isNot] = @is_not
|
|
25
|
-
message.gsub
|
|
25
|
+
message = message.gsub("expected to", "not expected to") if @is_not
|
|
26
26
|
expect_options.delete(:useInnerText) if expect_options.key?(:useInnerText) && expect_options[:useInnerText].nil?
|
|
27
27
|
|
|
28
28
|
result = @frame.expect(nil, expression, expect_options, title)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
|
|
3
|
+
module Playwright
|
|
4
|
+
class Screencast
|
|
5
|
+
def initialize(page)
|
|
6
|
+
@page = page
|
|
7
|
+
@started = false
|
|
8
|
+
@save_path = nil
|
|
9
|
+
@artifact = nil
|
|
10
|
+
@on_frame = nil
|
|
11
|
+
@page.send(:channel).on('screencastFrame', method(:handle_screencast_frame))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def start(path: nil, size: nil, quality: nil, &on_frame)
|
|
15
|
+
raise 'Screencast is already started' if @started
|
|
16
|
+
|
|
17
|
+
@started = true
|
|
18
|
+
@on_frame = on_frame if on_frame
|
|
19
|
+
|
|
20
|
+
params = {}
|
|
21
|
+
params[:record] = true if path
|
|
22
|
+
params[:size] = size if size
|
|
23
|
+
params[:quality] = quality if quality
|
|
24
|
+
params[:sendFrames] = true if on_frame
|
|
25
|
+
|
|
26
|
+
result = @page.send(:channel).send_message_to_server_result('screencastStart', params)
|
|
27
|
+
if result.is_a?(Hash) && result['artifact']
|
|
28
|
+
@artifact = ChannelOwners::Artifact.from(result['artifact'])
|
|
29
|
+
@save_path = path
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
DisposableStub.new { stop }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def stop
|
|
36
|
+
return unless @started
|
|
37
|
+
|
|
38
|
+
@started = false
|
|
39
|
+
@on_frame = nil
|
|
40
|
+
@page.send(:channel).send_message_to_server('screencastStop')
|
|
41
|
+
|
|
42
|
+
if @save_path && @artifact
|
|
43
|
+
@artifact.save_as(@save_path)
|
|
44
|
+
end
|
|
45
|
+
@artifact = nil
|
|
46
|
+
@save_path = nil
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def show_overlay(html, duration: nil)
|
|
50
|
+
params = { html: html }
|
|
51
|
+
params[:duration] = duration if duration
|
|
52
|
+
result = @page.send(:channel).send_message_to_server_result('screencastShowOverlay', params)
|
|
53
|
+
overlay_id = result['id'] if result.is_a?(Hash)
|
|
54
|
+
DisposableStub.new {
|
|
55
|
+
@page.send(:channel).send_message_to_server('screencastRemoveOverlay', id: overlay_id) if overlay_id
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def show_chapter(title, description: nil, duration: nil)
|
|
60
|
+
params = { title: title }
|
|
61
|
+
params[:description] = description if description
|
|
62
|
+
params[:duration] = duration if duration
|
|
63
|
+
@page.send(:channel).send_message_to_server('screencastChapter', params)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def show_actions(duration: nil, fontSize: nil, position: nil)
|
|
67
|
+
params = {}
|
|
68
|
+
params[:duration] = duration if duration
|
|
69
|
+
params[:fontSize] = fontSize if fontSize
|
|
70
|
+
params[:position] = position if position
|
|
71
|
+
@page.send(:channel).send_message_to_server('screencastShowActions', params)
|
|
72
|
+
DisposableStub.new { hide_actions }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def hide_actions
|
|
76
|
+
@page.send(:channel).send_message_to_server('screencastHideActions')
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def show_overlays
|
|
80
|
+
@page.send(:channel).send_message_to_server('screencastSetOverlayVisible', visible: true)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def hide_overlays
|
|
84
|
+
@page.send(:channel).send_message_to_server('screencastSetOverlayVisible', visible: false)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
private def handle_screencast_frame(event)
|
|
88
|
+
@on_frame&.call(Base64.strict_decode64(event['data']))
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
data/lib/playwright/utils.rb
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
require 'base64'
|
|
2
2
|
|
|
3
3
|
module Playwright
|
|
4
|
+
class DisposableStub
|
|
5
|
+
def initialize(&block)
|
|
6
|
+
@block = block
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def dispose
|
|
10
|
+
return unless @block
|
|
11
|
+
|
|
12
|
+
block = @block
|
|
13
|
+
@block = nil
|
|
14
|
+
block.call
|
|
15
|
+
rescue TargetClosedError
|
|
16
|
+
nil
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
4
20
|
module Utils
|
|
5
21
|
module PrepareBrowserContextOptions
|
|
6
22
|
# @see https://github.com/microsoft/playwright/blob/5a2cfdbd47ed3c3deff77bb73e5fac34241f649d/src/client/browserContext.ts#L265
|
|
@@ -19,6 +35,9 @@ module Playwright
|
|
|
19
35
|
if params[:record_video_size]
|
|
20
36
|
params[:recordVideo][:size] = params.delete(:record_video_size)
|
|
21
37
|
end
|
|
38
|
+
if params[:record_video_show_actions]
|
|
39
|
+
params[:recordVideo][:showActions] = params.delete(:record_video_show_actions)
|
|
40
|
+
end
|
|
22
41
|
end
|
|
23
42
|
if params[:storageState].is_a?(String)
|
|
24
43
|
params[:storageState] = JSON.parse(File.read(params[:storageState]))
|
data/lib/playwright/version.rb
CHANGED
data/lib/playwright/video.rb
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
module Playwright
|
|
2
2
|
class Video
|
|
3
|
-
def initialize(page)
|
|
3
|
+
def initialize(page, artifact: nil)
|
|
4
4
|
@page = page
|
|
5
5
|
@artifact = Concurrent::Promises.resolvable_future
|
|
6
|
-
if
|
|
6
|
+
if artifact
|
|
7
|
+
@artifact.fulfill(artifact)
|
|
8
|
+
elsif @page.closed?
|
|
7
9
|
on_page_closed
|
|
8
10
|
else
|
|
9
11
|
page.once('close', -> { on_page_closed })
|
|
@@ -16,9 +18,9 @@ module Playwright
|
|
|
16
18
|
end
|
|
17
19
|
end
|
|
18
20
|
|
|
19
|
-
# called only from Page
|
|
21
|
+
# called only from Page with send(:set_artifact, artifact)
|
|
20
22
|
private def set_artifact(artifact)
|
|
21
|
-
@artifact.fulfill(artifact)
|
|
23
|
+
@artifact.fulfill(artifact) unless @artifact.resolved?
|
|
22
24
|
end
|
|
23
25
|
|
|
24
26
|
def path
|
data/lib/playwright/waiter.rb
CHANGED
|
@@ -10,6 +10,7 @@ module Playwright
|
|
|
10
10
|
@event = wait_name
|
|
11
11
|
@channel = channel_owner.channel
|
|
12
12
|
@registered_listeners = Set.new
|
|
13
|
+
@listeners_mutex = Mutex.new
|
|
13
14
|
@logs = []
|
|
14
15
|
wait_for_event_info_before
|
|
15
16
|
end
|
|
@@ -50,8 +51,7 @@ module Playwright
|
|
|
50
51
|
end
|
|
51
52
|
end
|
|
52
53
|
}
|
|
53
|
-
emitter
|
|
54
|
-
@registered_listeners << [emitter, event, listener]
|
|
54
|
+
register_listener(emitter, event, listener)
|
|
55
55
|
|
|
56
56
|
self
|
|
57
57
|
end
|
|
@@ -69,16 +69,22 @@ module Playwright
|
|
|
69
69
|
end
|
|
70
70
|
|
|
71
71
|
private def cleanup
|
|
72
|
-
@
|
|
72
|
+
listeners = @listeners_mutex.synchronize do
|
|
73
|
+
@registered_listeners.to_a.tap { @registered_listeners.clear }
|
|
74
|
+
end
|
|
75
|
+
listeners.each do |emitter, event, listener|
|
|
73
76
|
emitter.off(event, listener)
|
|
74
77
|
end
|
|
75
|
-
@registered_listeners.clear
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
def force_fulfill(result)
|
|
79
81
|
fulfill(result)
|
|
80
82
|
end
|
|
81
83
|
|
|
84
|
+
def force_reject(error)
|
|
85
|
+
reject(error)
|
|
86
|
+
end
|
|
87
|
+
|
|
82
88
|
private def fulfill(result)
|
|
83
89
|
cleanup
|
|
84
90
|
return if @result.resolved?
|
|
@@ -107,12 +113,24 @@ module Playwright
|
|
|
107
113
|
reject(err)
|
|
108
114
|
end
|
|
109
115
|
}
|
|
110
|
-
emitter
|
|
111
|
-
@registered_listeners << [emitter, event, listener]
|
|
116
|
+
register_listener(emitter, event, listener)
|
|
112
117
|
|
|
113
118
|
self
|
|
114
119
|
end
|
|
115
120
|
|
|
121
|
+
private def register_listener(emitter, event, listener)
|
|
122
|
+
emitter.on(event, listener)
|
|
123
|
+
remove_later = false
|
|
124
|
+
@listeners_mutex.synchronize do
|
|
125
|
+
if @result.resolved?
|
|
126
|
+
remove_later = true
|
|
127
|
+
else
|
|
128
|
+
@registered_listeners << [emitter, event, listener]
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
emitter.off(event, listener) if remove_later
|
|
132
|
+
end
|
|
133
|
+
|
|
116
134
|
attr_reader :result
|
|
117
135
|
|
|
118
136
|
def log(message)
|
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/disposable'
|
|
23
24
|
require 'playwright/har_router'
|
|
24
25
|
require 'playwright/raw_headers'
|
|
25
26
|
require 'playwright/route_handler'
|
|
@@ -28,6 +29,7 @@ require 'playwright/timeout_settings'
|
|
|
28
29
|
require 'playwright/transport'
|
|
29
30
|
require 'playwright/url_matcher'
|
|
30
31
|
require 'playwright/version'
|
|
32
|
+
require 'playwright/screencast'
|
|
31
33
|
require 'playwright/video'
|
|
32
34
|
require 'playwright/waiter'
|
|
33
35
|
|
|
@@ -21,7 +21,7 @@ module Playwright
|
|
|
21
21
|
#
|
|
22
22
|
# This methods attaches Playwright to an existing Android device.
|
|
23
23
|
# Use [`method: Android.launchServer`] to launch a new Android server instance.
|
|
24
|
-
def connect(
|
|
24
|
+
def connect(endpoint, headers: nil, slowMo: nil, timeout: nil)
|
|
25
25
|
raise NotImplementedError.new('connect is not implemented yet.')
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -43,12 +43,6 @@ module Playwright
|
|
|
43
43
|
wrap_impl(@impl.set_default_navigation_timeout(unwrap_impl(timeout)))
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
-
# -- inherited from EventEmitter --
|
|
47
|
-
# @nodoc
|
|
48
|
-
def once(event, callback)
|
|
49
|
-
event_emitter_proxy.once(event, callback)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
46
|
# -- inherited from EventEmitter --
|
|
53
47
|
# @nodoc
|
|
54
48
|
def on(event, callback)
|
|
@@ -61,6 +55,12 @@ module Playwright
|
|
|
61
55
|
event_emitter_proxy.off(event, callback)
|
|
62
56
|
end
|
|
63
57
|
|
|
58
|
+
# -- inherited from EventEmitter --
|
|
59
|
+
# @nodoc
|
|
60
|
+
def once(event, callback)
|
|
61
|
+
event_emitter_proxy.once(event, callback)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
64
|
private def event_emitter_proxy
|
|
65
65
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
66
66
|
end
|
|
@@ -194,20 +194,14 @@ module Playwright
|
|
|
194
194
|
raise NotImplementedError.new('web_views is not implemented yet.')
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
-
# @nodoc
|
|
198
|
-
def tap_on(selector, duration: nil, timeout: nil)
|
|
199
|
-
wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
|
|
200
|
-
end
|
|
201
|
-
|
|
202
197
|
# @nodoc
|
|
203
198
|
def should_close_connection_on_close!
|
|
204
199
|
wrap_impl(@impl.should_close_connection_on_close!)
|
|
205
200
|
end
|
|
206
201
|
|
|
207
|
-
# -- inherited from EventEmitter --
|
|
208
202
|
# @nodoc
|
|
209
|
-
def
|
|
210
|
-
|
|
203
|
+
def tap_on(selector, duration: nil, timeout: nil)
|
|
204
|
+
wrap_impl(@impl.tap_on(unwrap_impl(selector), duration: unwrap_impl(duration), timeout: unwrap_impl(timeout)))
|
|
211
205
|
end
|
|
212
206
|
|
|
213
207
|
# -- inherited from EventEmitter --
|
|
@@ -222,6 +216,12 @@ module Playwright
|
|
|
222
216
|
event_emitter_proxy.off(event, callback)
|
|
223
217
|
end
|
|
224
218
|
|
|
219
|
+
# -- inherited from EventEmitter --
|
|
220
|
+
# @nodoc
|
|
221
|
+
def once(event, callback)
|
|
222
|
+
event_emitter_proxy.once(event, callback)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
225
|
private def event_emitter_proxy
|
|
226
226
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
227
227
|
end
|
|
@@ -286,12 +286,6 @@ module Playwright
|
|
|
286
286
|
raise NotImplementedError.new('storage_state is not implemented yet.')
|
|
287
287
|
end
|
|
288
288
|
|
|
289
|
-
# -- inherited from EventEmitter --
|
|
290
|
-
# @nodoc
|
|
291
|
-
def once(event, callback)
|
|
292
|
-
event_emitter_proxy.once(event, callback)
|
|
293
|
-
end
|
|
294
|
-
|
|
295
289
|
# -- inherited from EventEmitter --
|
|
296
290
|
# @nodoc
|
|
297
291
|
def on(event, callback)
|
|
@@ -304,6 +298,12 @@ module Playwright
|
|
|
304
298
|
event_emitter_proxy.off(event, callback)
|
|
305
299
|
end
|
|
306
300
|
|
|
301
|
+
# -- inherited from EventEmitter --
|
|
302
|
+
# @nodoc
|
|
303
|
+
def once(event, callback)
|
|
304
|
+
event_emitter_proxy.once(event, callback)
|
|
305
|
+
end
|
|
306
|
+
|
|
307
307
|
private def event_emitter_proxy
|
|
308
308
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
309
309
|
end
|
|
@@ -172,6 +172,12 @@ module Playwright
|
|
|
172
172
|
wrap_impl(@impl.new_page(acceptDownloads: unwrap_impl(acceptDownloads), baseURL: unwrap_impl(baseURL), bypassCSP: unwrap_impl(bypassCSP), clientCertificates: unwrap_impl(clientCertificates), colorScheme: unwrap_impl(colorScheme), contrast: unwrap_impl(contrast), 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), proxy: unwrap_impl(proxy), 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), storageState: unwrap_impl(storageState), strictSelectors: unwrap_impl(strictSelectors), timezoneId: unwrap_impl(timezoneId), userAgent: unwrap_impl(userAgent), viewport: unwrap_impl(viewport), &wrap_block_call(block)))
|
|
173
173
|
end
|
|
174
174
|
|
|
175
|
+
#
|
|
176
|
+
# Binds the browser to a named pipe or web socket, making it available for other clients to connect to.
|
|
177
|
+
def bind(title, host: nil, port: nil, workspaceDir: nil)
|
|
178
|
+
raise NotImplementedError.new('bind is not implemented yet.')
|
|
179
|
+
end
|
|
180
|
+
|
|
175
181
|
#
|
|
176
182
|
# **NOTE**: This API controls [Chromium Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) which is a low-level chromium-specific debugging tool. API to control [Playwright Tracing](../trace-viewer) could be found [here](./class-tracing).
|
|
177
183
|
#
|
|
@@ -197,18 +203,18 @@ module Playwright
|
|
|
197
203
|
wrap_impl(@impl.stop_tracing)
|
|
198
204
|
end
|
|
199
205
|
|
|
206
|
+
#
|
|
207
|
+
# Unbinds the browser server previously bound with [`method: Browser.bind`].
|
|
208
|
+
def unbind
|
|
209
|
+
raise NotImplementedError.new('unbind is not implemented yet.')
|
|
210
|
+
end
|
|
211
|
+
|
|
200
212
|
#
|
|
201
213
|
# Returns the browser version.
|
|
202
214
|
def version
|
|
203
215
|
wrap_impl(@impl.version)
|
|
204
216
|
end
|
|
205
217
|
|
|
206
|
-
# -- inherited from EventEmitter --
|
|
207
|
-
# @nodoc
|
|
208
|
-
def once(event, callback)
|
|
209
|
-
event_emitter_proxy.once(event, callback)
|
|
210
|
-
end
|
|
211
|
-
|
|
212
218
|
# -- inherited from EventEmitter --
|
|
213
219
|
# @nodoc
|
|
214
220
|
def on(event, callback)
|
|
@@ -221,6 +227,12 @@ module Playwright
|
|
|
221
227
|
event_emitter_proxy.off(event, callback)
|
|
222
228
|
end
|
|
223
229
|
|
|
230
|
+
# -- inherited from EventEmitter --
|
|
231
|
+
# @nodoc
|
|
232
|
+
def once(event, callback)
|
|
233
|
+
event_emitter_proxy.once(event, callback)
|
|
234
|
+
end
|
|
235
|
+
|
|
224
236
|
private def event_emitter_proxy
|
|
225
237
|
@event_emitter_proxy ||= EventEmitterProxy.new(self, @impl)
|
|
226
238
|
end
|