playwright-ruby-client 0.0.8 → 1.58.1.alpha1
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/AGENTS.md +4 -0
- data/CLAUDE/api_generation.md +28 -0
- data/CLAUDE/ci_expectations.md +23 -0
- data/CLAUDE/gem_release_flow.md +39 -0
- data/CLAUDE/past_upgrade_pr_patterns.md +42 -0
- data/CLAUDE/playwright_upgrade_workflow.md +35 -0
- data/CLAUDE/rspec_debugging.md +30 -0
- data/CLAUDE/unimplemented_examples.md +18 -0
- data/CLAUDE.md +32 -0
- data/CONTRIBUTING.md +5 -0
- data/README.md +60 -16
- data/documentation/README.md +33 -0
- data/documentation/babel.config.js +3 -0
- data/documentation/docs/api/api_request.md +7 -0
- data/documentation/docs/api/api_request_context.md +298 -0
- data/documentation/docs/api/api_response.md +114 -0
- data/documentation/docs/api/browser.md +237 -0
- data/documentation/docs/api/browser_context.md +503 -0
- data/documentation/docs/api/browser_type.md +184 -0
- data/documentation/docs/api/cdp_session.md +44 -0
- data/documentation/docs/api/clock.md +154 -0
- data/documentation/docs/api/console_message.md +85 -0
- data/documentation/docs/api/dialog.md +84 -0
- data/documentation/docs/api/download.md +111 -0
- data/documentation/docs/api/element_handle.md +694 -0
- data/documentation/docs/api/experimental/_category_.yml +3 -0
- data/documentation/docs/api/experimental/android.md +42 -0
- data/documentation/docs/api/experimental/android_device.md +109 -0
- data/documentation/docs/api/experimental/android_input.md +43 -0
- data/documentation/docs/api/experimental/android_socket.md +7 -0
- data/documentation/docs/api/experimental/android_web_view.md +7 -0
- data/documentation/docs/api/file_chooser.md +53 -0
- data/documentation/docs/api/frame.md +1218 -0
- data/documentation/docs/api/frame_locator.md +348 -0
- data/documentation/docs/api/js_handle.md +121 -0
- data/documentation/docs/api/keyboard.md +170 -0
- data/documentation/docs/api/locator.md +1495 -0
- data/documentation/docs/api/locator_assertions.md +827 -0
- data/documentation/docs/api/mouse.md +86 -0
- data/documentation/docs/api/page.md +1946 -0
- data/documentation/docs/api/page_assertions.md +65 -0
- data/documentation/docs/api/playwright.md +66 -0
- data/documentation/docs/api/request.md +255 -0
- data/documentation/docs/api/response.md +176 -0
- data/documentation/docs/api/route.md +205 -0
- data/documentation/docs/api/selectors.md +63 -0
- data/documentation/docs/api/touchscreen.md +22 -0
- data/documentation/docs/api/tracing.md +129 -0
- data/documentation/docs/api/web_socket.md +51 -0
- data/documentation/docs/api/worker.md +83 -0
- data/documentation/docs/article/api_coverage.mdx +11 -0
- data/documentation/docs/article/getting_started.md +161 -0
- data/documentation/docs/article/guides/_category_.yml +3 -0
- data/documentation/docs/article/guides/download_playwright_driver.md +55 -0
- data/documentation/docs/article/guides/inspector.md +31 -0
- data/documentation/docs/article/guides/launch_browser.md +121 -0
- data/documentation/docs/article/guides/playwright_on_alpine_linux.md +112 -0
- data/documentation/docs/article/guides/rails_integration.md +278 -0
- data/documentation/docs/article/guides/rails_integration_with_null_driver.md +145 -0
- data/documentation/docs/article/guides/recording_video.md +79 -0
- data/documentation/docs/article/guides/rspec_integration.md +59 -0
- data/documentation/docs/article/guides/semi_automation.md +71 -0
- data/documentation/docs/article/guides/use_storage_state.md +78 -0
- data/documentation/docs/include/api_coverage.md +671 -0
- data/documentation/docusaurus.config.js +114 -0
- data/documentation/package.json +39 -0
- data/documentation/sidebars.js +15 -0
- data/documentation/src/components/HomepageFeatures.js +61 -0
- data/documentation/src/components/HomepageFeatures.module.css +13 -0
- data/documentation/src/css/custom.css +44 -0
- data/documentation/src/pages/index.js +49 -0
- data/documentation/src/pages/index.module.css +41 -0
- data/documentation/src/pages/markdown-page.md +7 -0
- data/documentation/static/.nojekyll +0 -0
- data/documentation/static/img/playwright-logo.svg +9 -0
- data/documentation/static/img/playwright-ruby-client.png +0 -0
- data/documentation/static/img/undraw_dropdown_menu.svg +1 -0
- data/documentation/static/img/undraw_web_development.svg +1 -0
- data/documentation/static/img/undraw_windows.svg +1 -0
- data/documentation/yarn.lock +9005 -0
- data/lib/playwright/{input_types/android_input.rb → android_input_impl.rb} +5 -1
- data/lib/playwright/api_implementation.rb +18 -0
- data/lib/playwright/api_response_impl.rb +77 -0
- data/lib/playwright/channel.rb +62 -1
- data/lib/playwright/channel_owner.rb +70 -7
- data/lib/playwright/channel_owners/android.rb +16 -3
- data/lib/playwright/channel_owners/android_device.rb +22 -66
- data/lib/playwright/channel_owners/api_request_context.rb +247 -0
- data/lib/playwright/channel_owners/artifact.rb +40 -0
- data/lib/playwright/channel_owners/binding_call.rb +70 -0
- data/lib/playwright/channel_owners/browser.rb +114 -22
- data/lib/playwright/channel_owners/browser_context.rb +589 -15
- data/lib/playwright/channel_owners/browser_type.rb +90 -1
- data/lib/playwright/channel_owners/cdp_session.rb +19 -0
- data/lib/playwright/channel_owners/dialog.rb +32 -0
- data/lib/playwright/channel_owners/element_handle.rb +107 -43
- data/lib/playwright/channel_owners/fetch_request.rb +8 -0
- data/lib/playwright/channel_owners/frame.rb +334 -104
- data/lib/playwright/channel_owners/js_handle.rb +9 -13
- data/lib/playwright/channel_owners/local_utils.rb +82 -0
- data/lib/playwright/channel_owners/page.rb +778 -95
- data/lib/playwright/channel_owners/playwright.rb +25 -30
- data/lib/playwright/channel_owners/request.rb +120 -18
- data/lib/playwright/channel_owners/response.rb +113 -0
- data/lib/playwright/channel_owners/route.rb +181 -0
- data/lib/playwright/channel_owners/stream.rb +30 -0
- data/lib/playwright/channel_owners/tracing.rb +117 -0
- data/lib/playwright/channel_owners/web_socket.rb +96 -0
- data/lib/playwright/channel_owners/worker.rb +46 -0
- data/lib/playwright/channel_owners/writable_stream.rb +14 -0
- data/lib/playwright/clock_impl.rb +67 -0
- data/lib/playwright/connection.rb +111 -63
- data/lib/playwright/console_message_impl.rb +29 -0
- data/lib/playwright/download_impl.rb +32 -0
- data/lib/playwright/errors.rb +42 -5
- data/lib/playwright/event_emitter.rb +17 -3
- data/lib/playwright/event_emitter_proxy.rb +49 -0
- data/lib/playwright/events.rb +10 -5
- data/lib/playwright/file_chooser_impl.rb +24 -0
- data/lib/playwright/frame_locator_impl.rb +66 -0
- data/lib/playwright/har_router.rb +89 -0
- data/lib/playwright/http_headers.rb +14 -0
- data/lib/playwright/input_files.rb +102 -15
- data/lib/playwright/javascript/expression.rb +7 -11
- data/lib/playwright/javascript/regex.rb +23 -0
- data/lib/playwright/javascript/source_url.rb +16 -0
- data/lib/playwright/javascript/value_parser.rb +108 -19
- data/lib/playwright/javascript/value_serializer.rb +47 -8
- data/lib/playwright/javascript/visitor_info.rb +26 -0
- data/lib/playwright/javascript.rb +2 -10
- data/lib/playwright/{input_types/keyboard.rb → keyboard_impl.rb} +6 -2
- data/lib/playwright/locator_assertions_impl.rb +571 -0
- data/lib/playwright/locator_impl.rb +544 -0
- data/lib/playwright/locator_utils.rb +136 -0
- data/lib/playwright/mouse_impl.rb +57 -0
- data/lib/playwright/page_assertions_impl.rb +154 -0
- data/lib/playwright/playwright_api.rb +102 -30
- data/lib/playwright/raw_headers.rb +61 -0
- data/lib/playwright/route_handler.rb +78 -0
- data/lib/playwright/select_option_values.rb +34 -13
- data/lib/playwright/selectors_impl.rb +45 -0
- data/lib/playwright/test.rb +102 -0
- data/lib/playwright/timeout_settings.rb +9 -4
- data/lib/playwright/touchscreen_impl.rb +14 -0
- data/lib/playwright/transport.rb +61 -10
- data/lib/playwright/url_matcher.rb +24 -2
- data/lib/playwright/utils.rb +48 -13
- data/lib/playwright/version.rb +2 -1
- data/lib/playwright/video.rb +54 -0
- data/lib/playwright/waiter.rb +166 -0
- data/lib/playwright/web_socket_client.rb +167 -0
- data/lib/playwright/web_socket_transport.rb +116 -0
- data/lib/playwright.rb +188 -11
- data/lib/playwright_api/android.rb +46 -11
- data/lib/playwright_api/android_device.rb +182 -31
- data/lib/playwright_api/android_input.rb +22 -13
- data/lib/playwright_api/android_socket.rb +18 -0
- data/lib/playwright_api/android_web_view.rb +24 -0
- data/lib/playwright_api/api_request.rb +26 -0
- data/lib/playwright_api/api_request_context.rb +311 -0
- data/lib/playwright_api/api_response.rb +92 -0
- data/lib/playwright_api/browser.rb +116 -103
- data/lib/playwright_api/browser_context.rb +290 -389
- data/lib/playwright_api/browser_type.rb +96 -118
- data/lib/playwright_api/cdp_session.rb +36 -39
- data/lib/playwright_api/clock.rb +121 -0
- data/lib/playwright_api/console_message.rb +35 -19
- data/lib/playwright_api/dialog.rb +53 -50
- data/lib/playwright_api/download.rb +49 -43
- data/lib/playwright_api/element_handle.rb +354 -402
- data/lib/playwright_api/file_chooser.rb +15 -18
- data/lib/playwright_api/frame.rb +703 -603
- data/lib/playwright_api/frame_locator.rb +285 -0
- data/lib/playwright_api/js_handle.rb +50 -76
- data/lib/playwright_api/keyboard.rb +67 -146
- data/lib/playwright_api/locator.rb +1304 -0
- data/lib/playwright_api/locator_assertions.rb +704 -0
- data/lib/playwright_api/mouse.rb +23 -29
- data/lib/playwright_api/page.rb +1196 -1176
- data/lib/playwright_api/page_assertions.rb +60 -0
- data/lib/playwright_api/playwright.rb +54 -122
- data/lib/playwright_api/request.rb +112 -74
- data/lib/playwright_api/response.rb +92 -20
- data/lib/playwright_api/route.rb +152 -62
- data/lib/playwright_api/selectors.rb +47 -61
- data/lib/playwright_api/touchscreen.rb +8 -2
- data/lib/playwright_api/tracing.rb +128 -0
- data/lib/playwright_api/web_socket.rb +43 -5
- data/lib/playwright_api/worker.rb +74 -34
- data/playwright.gemspec +14 -9
- data/sig/playwright.rbs +658 -0
- metadata +216 -50
- data/docs/api_coverage.md +0 -354
- data/lib/playwright/channel_owners/chromium_browser.rb +0 -8
- data/lib/playwright/channel_owners/chromium_browser_context.rb +0 -8
- data/lib/playwright/channel_owners/console_message.rb +0 -21
- data/lib/playwright/channel_owners/firefox_browser.rb +0 -8
- data/lib/playwright/channel_owners/selectors.rb +0 -4
- data/lib/playwright/channel_owners/webkit_browser.rb +0 -8
- data/lib/playwright/input_type.rb +0 -19
- data/lib/playwright/input_types/mouse.rb +0 -4
- data/lib/playwright/input_types/touchscreen.rb +0 -4
- data/lib/playwright/javascript/function.rb +0 -67
- data/lib/playwright/wait_helper.rb +0 -73
- data/lib/playwright_api/accessibility.rb +0 -93
- data/lib/playwright_api/binding_call.rb +0 -23
- data/lib/playwright_api/chromium_browser_context.rb +0 -57
- data/lib/playwright_api/video.rb +0 -24
|
@@ -1,46 +1,83 @@
|
|
|
1
1
|
require 'base64'
|
|
2
|
+
require_relative '../locator_utils'
|
|
2
3
|
|
|
3
4
|
module Playwright
|
|
4
5
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_page.py
|
|
5
6
|
define_channel_owner :Page do
|
|
6
|
-
include Utils::Errors::
|
|
7
|
+
include Utils::Errors::TargetClosedErrorMethods
|
|
8
|
+
include LocatorUtils
|
|
7
9
|
attr_writer :owned_context
|
|
8
10
|
|
|
9
|
-
def after_initialize
|
|
11
|
+
private def after_initialize
|
|
10
12
|
@browser_context = @parent
|
|
11
13
|
@timeout_settings = TimeoutSettings.new(@browser_context.send(:_timeout_settings))
|
|
12
|
-
@
|
|
13
|
-
@
|
|
14
|
-
@
|
|
15
|
-
@touchscreen = InputTypes::Touchscreen.new(@channel)
|
|
14
|
+
@keyboard = KeyboardImpl.new(@channel)
|
|
15
|
+
@mouse = MouseImpl.new(@channel)
|
|
16
|
+
@touchscreen = TouchscreenImpl.new(@channel)
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
if @initializer['viewportSize']
|
|
19
|
+
@viewport_size = {
|
|
20
|
+
width: @initializer['viewportSize']['width'],
|
|
21
|
+
height: @initializer['viewportSize']['height'],
|
|
22
|
+
}
|
|
23
|
+
end
|
|
18
24
|
@closed = false
|
|
25
|
+
@workers = Set.new
|
|
26
|
+
@bindings = {}
|
|
27
|
+
@routes = []
|
|
28
|
+
|
|
19
29
|
@main_frame = ChannelOwners::Frame.from(@initializer['mainFrame'])
|
|
20
30
|
@main_frame.send(:update_page_from_page, self)
|
|
21
31
|
@frames = Set.new
|
|
22
32
|
@frames << @main_frame
|
|
33
|
+
@opener = ChannelOwners::Page.from_nullable(@initializer['opener'])
|
|
34
|
+
@close_reason = nil
|
|
23
35
|
|
|
36
|
+
@channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
|
|
37
|
+
@closed_or_crashed_promise = Concurrent::Promises.resolvable_future
|
|
24
38
|
@channel.once('close', ->(_) { on_close })
|
|
25
|
-
@channel.on('
|
|
26
|
-
|
|
27
|
-
|
|
39
|
+
@channel.on('crash', ->(_) { on_crash })
|
|
40
|
+
@channel.on('download', method(:on_download))
|
|
41
|
+
@channel.on('fileChooser', ->(params) {
|
|
42
|
+
chooser = FileChooserImpl.new(
|
|
43
|
+
page: self,
|
|
44
|
+
timeout_settings: @timeout_settings,
|
|
45
|
+
element_handle: ChannelOwners::ElementHandle.from(params['element']),
|
|
46
|
+
is_multiple: params['isMultiple'])
|
|
47
|
+
emit(Events::Page::FileChooser, chooser)
|
|
28
48
|
})
|
|
29
|
-
@channel.on('domcontentloaded', ->(_) { emit(Events::Page::DOMContentLoaded) })
|
|
30
49
|
@channel.on('frameAttached', ->(params) {
|
|
31
50
|
on_frame_attached(ChannelOwners::Frame.from(params['frame']))
|
|
32
51
|
})
|
|
33
52
|
@channel.on('frameDetached', ->(params) {
|
|
34
53
|
on_frame_detached(ChannelOwners::Frame.from(params['frame']))
|
|
35
54
|
})
|
|
36
|
-
@channel.on('
|
|
37
|
-
|
|
38
|
-
|
|
55
|
+
@channel.on('pageError', ->(params) {
|
|
56
|
+
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
|
57
|
+
})
|
|
58
|
+
@channel.on('route', ->(params) { on_route(ChannelOwners::Route.from(params['route'])) })
|
|
59
|
+
@channel.on('video', method(:on_video))
|
|
60
|
+
@channel.on('viewportSizeChanged', method(:on_viewport_size_changed))
|
|
61
|
+
@channel.on('webSocket', ->(params) {
|
|
62
|
+
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
|
63
|
+
})
|
|
64
|
+
@channel.on('worker', ->(params) {
|
|
65
|
+
worker = ChannelOwners::Worker.from(params['worker'])
|
|
66
|
+
on_worker(worker)
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
set_event_to_subscription_mapping({
|
|
70
|
+
Events::Page::Console => "console",
|
|
71
|
+
Events::Page::Dialog => "dialog",
|
|
72
|
+
Events::Page::Request => "request",
|
|
73
|
+
Events::Page::Response => "response",
|
|
74
|
+
Events::Page::RequestFinished => "requestFinished",
|
|
75
|
+
Events::Page::RequestFailed => "requestFailed",
|
|
76
|
+
Events::Page::FileChooser => "fileChooser",
|
|
39
77
|
})
|
|
40
78
|
end
|
|
41
79
|
|
|
42
80
|
attr_reader \
|
|
43
|
-
:accessibility,
|
|
44
81
|
:keyboard,
|
|
45
82
|
:mouse,
|
|
46
83
|
:touchscreen,
|
|
@@ -59,41 +96,135 @@ module Playwright
|
|
|
59
96
|
emit(Events::Page::FrameDetached, frame)
|
|
60
97
|
end
|
|
61
98
|
|
|
99
|
+
private def on_route(route)
|
|
100
|
+
route.send(:update_context, self)
|
|
101
|
+
return if @close_was_called
|
|
102
|
+
# It is not desired to use PlaywrightApi.wrap directly.
|
|
103
|
+
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
|
104
|
+
# Just a workaround...
|
|
105
|
+
Concurrent::Promises.future(PlaywrightApi.wrap(route)) do |wrapped_route|
|
|
106
|
+
handled = @routes.any? do |handler_entry|
|
|
107
|
+
next false unless handler_entry.match?(route.request.url)
|
|
108
|
+
|
|
109
|
+
promise = Concurrent::Promises.resolvable_future
|
|
110
|
+
route.send(:set_handling_future, promise)
|
|
111
|
+
|
|
112
|
+
promise_handled = Concurrent::Promises.zip(
|
|
113
|
+
promise,
|
|
114
|
+
handler_entry.async_handle(wrapped_route)
|
|
115
|
+
).value!.first
|
|
116
|
+
|
|
117
|
+
promise_handled
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
@routes.reject!(&:expired?)
|
|
121
|
+
if @routes.count == 0
|
|
122
|
+
async_update_interception_patterns
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
unless handled
|
|
126
|
+
@browser_context.send(:on_route, route)
|
|
127
|
+
end
|
|
128
|
+
end.rescue do |err|
|
|
129
|
+
puts err, err.backtrace
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
private def on_binding(binding_call)
|
|
134
|
+
func = @bindings[binding_call.name]
|
|
135
|
+
if func
|
|
136
|
+
binding_call.call_async(func)
|
|
137
|
+
end
|
|
138
|
+
@browser_context.send(:on_binding, binding_call)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
private def on_worker(worker)
|
|
142
|
+
worker.page = self
|
|
143
|
+
@workers << worker
|
|
144
|
+
emit(Events::Page::Worker, worker)
|
|
145
|
+
end
|
|
146
|
+
|
|
62
147
|
private def on_close
|
|
63
148
|
@closed = true
|
|
64
149
|
@browser_context.send(:remove_page, self)
|
|
150
|
+
if @closed_or_crashed_promise.pending?
|
|
151
|
+
@closed_or_crashed_promise.fulfill(close_error_with_reason)
|
|
152
|
+
end
|
|
65
153
|
emit(Events::Page::Close)
|
|
66
154
|
end
|
|
67
155
|
|
|
156
|
+
private def on_crash
|
|
157
|
+
if @closed_or_crashed_promise.pending?
|
|
158
|
+
@closed_or_crashed_promise.fulfill(TargetClosedError.new)
|
|
159
|
+
end
|
|
160
|
+
emit(Events::Page::Crash)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
private def on_download(params)
|
|
164
|
+
artifact = ChannelOwners::Artifact.from(params['artifact'])
|
|
165
|
+
download = DownloadImpl.new(
|
|
166
|
+
page: self,
|
|
167
|
+
url: params['url'],
|
|
168
|
+
suggested_filename: params['suggestedFilename'],
|
|
169
|
+
artifact: artifact,
|
|
170
|
+
)
|
|
171
|
+
emit(Events::Page::Download, download)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
private def on_video(params)
|
|
175
|
+
artifact = ChannelOwners::Artifact.from(params['artifact'])
|
|
176
|
+
video.send(:set_artifact, artifact)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
private def on_viewport_size_changed(params)
|
|
180
|
+
@viewport_size = {
|
|
181
|
+
width: params['viewportSize']['width'],
|
|
182
|
+
height: params['viewportSize']['height'],
|
|
183
|
+
}
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# @override
|
|
187
|
+
private def perform_event_emitter_callback(event, callback, args)
|
|
188
|
+
should_callback_async = [
|
|
189
|
+
Events::Page::Dialog,
|
|
190
|
+
Events::Page::Response,
|
|
191
|
+
].freeze
|
|
192
|
+
|
|
193
|
+
if should_callback_async.include?(event)
|
|
194
|
+
Concurrent::Promises.future { super }
|
|
195
|
+
else
|
|
196
|
+
super
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
68
200
|
def context
|
|
69
201
|
@browser_context
|
|
70
202
|
end
|
|
71
203
|
|
|
204
|
+
def clock
|
|
205
|
+
@browser_context.clock
|
|
206
|
+
end
|
|
207
|
+
|
|
72
208
|
def opener
|
|
73
|
-
|
|
74
|
-
|
|
209
|
+
if @opener&.closed?
|
|
210
|
+
nil
|
|
211
|
+
else
|
|
212
|
+
@opener
|
|
213
|
+
end
|
|
75
214
|
end
|
|
76
215
|
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
[frameSelector, nil]
|
|
83
|
-
end
|
|
216
|
+
private def emit_popup_event_from_browser_context
|
|
217
|
+
if @opener && !@opener.closed?
|
|
218
|
+
@opener.emit(Events::Page::Popup, self)
|
|
219
|
+
end
|
|
220
|
+
end
|
|
84
221
|
|
|
222
|
+
def frame(name: nil, url: nil)
|
|
85
223
|
if name
|
|
86
224
|
@frames.find { |f| f.name == name }
|
|
87
225
|
elsif url
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
when String
|
|
91
|
-
@frames.find { |f| f.url == url }
|
|
92
|
-
when Regexp
|
|
93
|
-
@frames.find { |f| url.match?(f.url) }
|
|
94
|
-
else
|
|
95
|
-
raise NotImplementedError.new('Page#frame with url is not completely implemented yet')
|
|
96
|
-
end
|
|
226
|
+
matcher = UrlMatcher.new(url, base_url: @browser_context.send(:base_url))
|
|
227
|
+
@frames.find { |f| matcher.match?(f.url) }
|
|
97
228
|
else
|
|
98
229
|
raise ArgumentError.new('Either name or url matcher should be specified')
|
|
99
230
|
end
|
|
@@ -105,22 +236,52 @@ module Playwright
|
|
|
105
236
|
|
|
106
237
|
def set_default_navigation_timeout(timeout)
|
|
107
238
|
@timeout_settings.default_navigation_timeout = timeout
|
|
108
|
-
@channel.send_message_to_server('setDefaultNavigationTimeoutNoReply', timeout: timeout)
|
|
109
239
|
end
|
|
110
240
|
|
|
111
241
|
def set_default_timeout(timeout)
|
|
112
242
|
@timeout_settings.default_timeout = timeout
|
|
113
|
-
@channel.send_message_to_server('setDefaultTimeoutNoReply', timeout: timeout)
|
|
114
243
|
end
|
|
115
244
|
|
|
116
|
-
def query_selector(selector)
|
|
117
|
-
@main_frame.query_selector(selector)
|
|
245
|
+
def query_selector(selector, strict: nil)
|
|
246
|
+
@main_frame.query_selector(selector, strict: strict)
|
|
118
247
|
end
|
|
119
248
|
|
|
120
249
|
def query_selector_all(selector)
|
|
121
250
|
@main_frame.query_selector_all(selector)
|
|
122
251
|
end
|
|
123
252
|
|
|
253
|
+
def wait_for_selector(selector, state: nil, strict: nil, timeout: nil)
|
|
254
|
+
@main_frame.wait_for_selector(selector, state: state, strict: strict, timeout: timeout)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def checked?(selector, strict: nil, timeout: nil)
|
|
258
|
+
@main_frame.checked?(selector, strict: strict, timeout: timeout)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def disabled?(selector, strict: nil, timeout: nil)
|
|
262
|
+
@main_frame.disabled?(selector, strict: strict, timeout: timeout)
|
|
263
|
+
end
|
|
264
|
+
|
|
265
|
+
def editable?(selector, strict: nil, timeout: nil)
|
|
266
|
+
@main_frame.editable?(selector, strict: strict, timeout: timeout)
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def enabled?(selector, strict: nil, timeout: nil)
|
|
270
|
+
@main_frame.enabled?(selector, strict: strict, timeout: timeout)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def hidden?(selector, strict: nil, timeout: nil)
|
|
274
|
+
@main_frame.hidden?(selector, strict: strict, timeout: timeout)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def visible?(selector, strict: nil, timeout: nil)
|
|
278
|
+
@main_frame.visible?(selector, strict: strict, timeout: timeout)
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def dispatch_event(selector, type, eventInit: nil, strict: nil, timeout: nil)
|
|
282
|
+
@main_frame.dispatch_event(selector, type, eventInit: eventInit, strict: strict, timeout: timeout)
|
|
283
|
+
end
|
|
284
|
+
|
|
124
285
|
def evaluate(pageFunction, arg: nil)
|
|
125
286
|
@main_frame.evaluate(pageFunction, arg: arg)
|
|
126
287
|
end
|
|
@@ -129,8 +290,8 @@ module Playwright
|
|
|
129
290
|
@main_frame.evaluate_handle(pageFunction, arg: arg)
|
|
130
291
|
end
|
|
131
292
|
|
|
132
|
-
def eval_on_selector(selector, pageFunction, arg: nil)
|
|
133
|
-
@main_frame.eval_on_selector(selector, pageFunction, arg: arg)
|
|
293
|
+
def eval_on_selector(selector, pageFunction, arg: nil, strict: nil)
|
|
294
|
+
@main_frame.eval_on_selector(selector, pageFunction, arg: arg, strict: strict)
|
|
134
295
|
end
|
|
135
296
|
|
|
136
297
|
def eval_on_selector_all(selector, pageFunction, arg: nil)
|
|
@@ -145,6 +306,25 @@ module Playwright
|
|
|
145
306
|
@main_frame.add_style_tag(content: content, path: path, url: url)
|
|
146
307
|
end
|
|
147
308
|
|
|
309
|
+
def expose_function(name, callback)
|
|
310
|
+
@channel.send_message_to_server('exposeBinding', name: name)
|
|
311
|
+
@bindings[name] = ->(_source, *args) { callback.call(*args) }
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
def expose_binding(name, callback, handle: nil)
|
|
315
|
+
params = {
|
|
316
|
+
name: name,
|
|
317
|
+
needsHandle: handle,
|
|
318
|
+
}.compact
|
|
319
|
+
@channel.send_message_to_server('exposeBinding', params)
|
|
320
|
+
@bindings[name] = callback
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
def set_extra_http_headers(headers)
|
|
324
|
+
serialized_headers = HttpHeaders.new(headers).as_serialized
|
|
325
|
+
@channel.send_message_to_server('setExtraHTTPHeaders', headers: serialized_headers)
|
|
326
|
+
end
|
|
327
|
+
|
|
148
328
|
def url
|
|
149
329
|
@main_frame.url
|
|
150
330
|
end
|
|
@@ -163,10 +343,10 @@ module Playwright
|
|
|
163
343
|
|
|
164
344
|
def reload(timeout: nil, waitUntil: nil)
|
|
165
345
|
params = {
|
|
166
|
-
timeout: timeout,
|
|
346
|
+
timeout: @timeout_settings.timeout(timeout),
|
|
167
347
|
waitUntil: waitUntil,
|
|
168
348
|
}.compact
|
|
169
|
-
resp = @channel.send_message_to_server('
|
|
349
|
+
resp = @channel.send_message_to_server('reload', params)
|
|
170
350
|
ChannelOwners::Response.from_nullable(resp)
|
|
171
351
|
end
|
|
172
352
|
|
|
@@ -174,29 +354,144 @@ module Playwright
|
|
|
174
354
|
@main_frame.wait_for_load_state(state: state, timeout: timeout)
|
|
175
355
|
end
|
|
176
356
|
|
|
357
|
+
def wait_for_url(url, timeout: nil, waitUntil: nil)
|
|
358
|
+
@main_frame.wait_for_url(url, timeout: timeout, waitUntil: waitUntil)
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def go_back(timeout: nil, waitUntil: nil)
|
|
362
|
+
params = { timeout: @timeout_settings.timeout(timeout), waitUntil: waitUntil }.compact
|
|
363
|
+
resp = @channel.send_message_to_server('goBack', params)
|
|
364
|
+
ChannelOwners::Response.from_nullable(resp)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def go_forward(timeout: nil, waitUntil: nil)
|
|
368
|
+
params = { timeout: @timeout_settings.timeout(timeout), waitUntil: waitUntil }.compact
|
|
369
|
+
resp = @channel.send_message_to_server('goForward', params)
|
|
370
|
+
ChannelOwners::Response.from_nullable(resp)
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
def emulate_media(colorScheme: nil, contrast: nil, forcedColors: nil, media: nil, reducedMotion: nil)
|
|
374
|
+
params = {
|
|
375
|
+
colorScheme: no_override_if_null(colorScheme),
|
|
376
|
+
contrast: no_override_if_null(contrast),
|
|
377
|
+
forcedColors: no_override_if_null(forcedColors),
|
|
378
|
+
media: no_override_if_null(media),
|
|
379
|
+
reducedMotion: no_override_if_null(reducedMotion),
|
|
380
|
+
}.compact
|
|
381
|
+
@channel.send_message_to_server('emulateMedia', params)
|
|
382
|
+
|
|
383
|
+
nil
|
|
384
|
+
end
|
|
385
|
+
|
|
386
|
+
private def no_override_if_null(target)
|
|
387
|
+
if target == 'null'
|
|
388
|
+
'no-override'
|
|
389
|
+
else
|
|
390
|
+
target
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
177
394
|
def set_viewport_size(viewportSize)
|
|
178
395
|
@viewport_size = viewportSize
|
|
179
396
|
@channel.send_message_to_server('setViewportSize', { viewportSize: viewportSize })
|
|
180
397
|
nil
|
|
181
398
|
end
|
|
182
399
|
|
|
400
|
+
def bring_to_front
|
|
401
|
+
@channel.send_message_to_server('bringToFront')
|
|
402
|
+
nil
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
def add_init_script(path: nil, script: nil)
|
|
406
|
+
source =
|
|
407
|
+
if path
|
|
408
|
+
JavaScript::SourceUrl.new(File.read(path), path).to_s
|
|
409
|
+
elsif script
|
|
410
|
+
script
|
|
411
|
+
else
|
|
412
|
+
raise ArgumentError.new('Either path or script parameter must be specified')
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
@channel.send_message_to_server('addInitScript', source: source)
|
|
416
|
+
nil
|
|
417
|
+
end
|
|
418
|
+
|
|
419
|
+
def route(url, handler, times: nil)
|
|
420
|
+
entry = RouteHandler.new(url, @browser_context.send(:base_url), handler, times)
|
|
421
|
+
@routes.unshift(entry)
|
|
422
|
+
update_interception_patterns
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def unroute_all(behavior: nil)
|
|
426
|
+
@routes.clear
|
|
427
|
+
update_interception_patterns
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def unroute(url, handler: nil)
|
|
431
|
+
@routes.reject! do |handler_entry|
|
|
432
|
+
handler_entry.same_value?(url: url, handler: handler)
|
|
433
|
+
end
|
|
434
|
+
update_interception_patterns
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
def route_from_har(har, notFound: nil, update: nil, url: nil, updateContent: nil, updateMode: nil)
|
|
438
|
+
if update
|
|
439
|
+
@browser_context.send(:record_into_har, har, self, url: url, update_content: updateContent, update_mode: updateMode)
|
|
440
|
+
return
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
router = HarRouter.create(
|
|
444
|
+
@connection.local_utils,
|
|
445
|
+
har.to_s,
|
|
446
|
+
notFound || "abort",
|
|
447
|
+
url_match: url,
|
|
448
|
+
)
|
|
449
|
+
router.add_page_route(self)
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
private def async_update_interception_patterns
|
|
453
|
+
patterns = RouteHandler.prepare_interception_patterns(@routes)
|
|
454
|
+
@channel.async_send_message_to_server('setNetworkInterceptionPatterns', patterns: patterns)
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
private def update_interception_patterns
|
|
458
|
+
patterns = RouteHandler.prepare_interception_patterns(@routes)
|
|
459
|
+
@channel.send_message_to_server('setNetworkInterceptionPatterns', patterns: patterns)
|
|
460
|
+
end
|
|
461
|
+
|
|
183
462
|
def screenshot(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
quality: nil,
|
|
187
|
-
fullPage: nil,
|
|
463
|
+
animations: nil,
|
|
464
|
+
caret: nil,
|
|
188
465
|
clip: nil,
|
|
466
|
+
fullPage: nil,
|
|
467
|
+
mask: nil,
|
|
468
|
+
maskColor: nil,
|
|
189
469
|
omitBackground: nil,
|
|
190
|
-
|
|
470
|
+
path: nil,
|
|
471
|
+
quality: nil,
|
|
472
|
+
scale: nil,
|
|
473
|
+
style: nil,
|
|
474
|
+
timeout: nil,
|
|
475
|
+
type: nil)
|
|
191
476
|
|
|
192
477
|
params = {
|
|
193
478
|
type: type,
|
|
194
479
|
quality: quality,
|
|
195
480
|
fullPage: fullPage,
|
|
196
481
|
clip: clip,
|
|
482
|
+
maskColor: maskColor,
|
|
197
483
|
omitBackground: omitBackground,
|
|
198
|
-
|
|
484
|
+
animations: animations,
|
|
485
|
+
caret: caret,
|
|
486
|
+
scale: scale,
|
|
487
|
+
style: style,
|
|
488
|
+
timeout: @timeout_settings.timeout(timeout),
|
|
199
489
|
}.compact
|
|
490
|
+
if mask.is_a?(Enumerable)
|
|
491
|
+
params[:mask] = mask.map do |locator|
|
|
492
|
+
locator.send(:to_protocol)
|
|
493
|
+
end
|
|
494
|
+
end
|
|
200
495
|
encoded_binary = @channel.send_message_to_server('screenshot', params)
|
|
201
496
|
decoded_binary = Base64.strict_decode64(encoded_binary)
|
|
202
497
|
if path
|
|
@@ -211,13 +506,20 @@ module Playwright
|
|
|
211
506
|
@main_frame.title
|
|
212
507
|
end
|
|
213
508
|
|
|
214
|
-
def close(runBeforeUnload: nil)
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
509
|
+
def close(runBeforeUnload: nil, reason: nil)
|
|
510
|
+
@close_reason = reason
|
|
511
|
+
unless runBeforeUnload
|
|
512
|
+
@close_was_called = true
|
|
513
|
+
end
|
|
514
|
+
if @owned_context
|
|
515
|
+
@owned_context.close
|
|
516
|
+
else
|
|
517
|
+
options = { runBeforeUnload: runBeforeUnload }.compact
|
|
518
|
+
@channel.send_message_to_server('close', options)
|
|
519
|
+
end
|
|
218
520
|
nil
|
|
219
521
|
rescue => err
|
|
220
|
-
raise
|
|
522
|
+
raise if !target_closed_error?(err) || !runBeforeUnload
|
|
221
523
|
end
|
|
222
524
|
|
|
223
525
|
def closed?
|
|
@@ -233,7 +535,10 @@ module Playwright
|
|
|
233
535
|
modifiers: nil,
|
|
234
536
|
noWaitAfter: nil,
|
|
235
537
|
position: nil,
|
|
236
|
-
|
|
538
|
+
strict: nil,
|
|
539
|
+
timeout: nil,
|
|
540
|
+
trial: nil,
|
|
541
|
+
steps: nil)
|
|
237
542
|
|
|
238
543
|
@main_frame.click(
|
|
239
544
|
selector,
|
|
@@ -244,7 +549,36 @@ module Playwright
|
|
|
244
549
|
modifiers: modifiers,
|
|
245
550
|
noWaitAfter: noWaitAfter,
|
|
246
551
|
position: position,
|
|
552
|
+
strict: strict,
|
|
247
553
|
timeout: timeout,
|
|
554
|
+
trial: trial,
|
|
555
|
+
steps: steps,
|
|
556
|
+
)
|
|
557
|
+
end
|
|
558
|
+
|
|
559
|
+
def drag_and_drop(
|
|
560
|
+
source,
|
|
561
|
+
target,
|
|
562
|
+
force: nil,
|
|
563
|
+
noWaitAfter: nil,
|
|
564
|
+
sourcePosition: nil,
|
|
565
|
+
strict: nil,
|
|
566
|
+
targetPosition: nil,
|
|
567
|
+
timeout: nil,
|
|
568
|
+
trial: nil,
|
|
569
|
+
steps: nil)
|
|
570
|
+
|
|
571
|
+
@main_frame.drag_and_drop(
|
|
572
|
+
source,
|
|
573
|
+
target,
|
|
574
|
+
force: force,
|
|
575
|
+
noWaitAfter: noWaitAfter,
|
|
576
|
+
sourcePosition: sourcePosition,
|
|
577
|
+
strict: strict,
|
|
578
|
+
targetPosition: targetPosition,
|
|
579
|
+
timeout: timeout,
|
|
580
|
+
trial: trial,
|
|
581
|
+
steps: steps,
|
|
248
582
|
)
|
|
249
583
|
end
|
|
250
584
|
|
|
@@ -256,7 +590,10 @@ module Playwright
|
|
|
256
590
|
modifiers: nil,
|
|
257
591
|
noWaitAfter: nil,
|
|
258
592
|
position: nil,
|
|
259
|
-
|
|
593
|
+
strict: nil,
|
|
594
|
+
timeout: nil,
|
|
595
|
+
trial: nil,
|
|
596
|
+
steps: nil)
|
|
260
597
|
@main_frame.dblclick(
|
|
261
598
|
selector,
|
|
262
599
|
button: button,
|
|
@@ -265,16 +602,157 @@ module Playwright
|
|
|
265
602
|
modifiers: modifiers,
|
|
266
603
|
noWaitAfter: noWaitAfter,
|
|
267
604
|
position: position,
|
|
605
|
+
strict: strict,
|
|
606
|
+
timeout: timeout,
|
|
607
|
+
trial: trial,
|
|
608
|
+
steps: steps,
|
|
609
|
+
)
|
|
610
|
+
end
|
|
611
|
+
|
|
612
|
+
def tap_point(
|
|
613
|
+
selector,
|
|
614
|
+
force: nil,
|
|
615
|
+
modifiers: nil,
|
|
616
|
+
noWaitAfter: nil,
|
|
617
|
+
position: nil,
|
|
618
|
+
strict: nil,
|
|
619
|
+
timeout: nil,
|
|
620
|
+
trial: nil)
|
|
621
|
+
@main_frame.tap_point(
|
|
622
|
+
selector,
|
|
623
|
+
force: force,
|
|
624
|
+
modifiers: modifiers,
|
|
625
|
+
noWaitAfter: noWaitAfter,
|
|
626
|
+
position: position,
|
|
627
|
+
strict: strict,
|
|
628
|
+
timeout: timeout,
|
|
629
|
+
trial: trial,
|
|
630
|
+
)
|
|
631
|
+
end
|
|
632
|
+
|
|
633
|
+
def fill(
|
|
634
|
+
selector,
|
|
635
|
+
value,
|
|
636
|
+
force: nil,
|
|
637
|
+
noWaitAfter: nil,
|
|
638
|
+
strict: nil,
|
|
639
|
+
timeout: nil)
|
|
640
|
+
@main_frame.fill(
|
|
641
|
+
selector,
|
|
642
|
+
value,
|
|
643
|
+
force: force,
|
|
644
|
+
noWaitAfter: noWaitAfter,
|
|
645
|
+
strict: strict,
|
|
646
|
+
timeout: timeout)
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
def console_messages
|
|
650
|
+
messages = @channel.send_message_to_server('consoleMessages')
|
|
651
|
+
messages.map do |message|
|
|
652
|
+
ConsoleMessageImpl.new(message, self, nil)
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
def page_errors
|
|
657
|
+
errors = @channel.send_message_to_server('pageErrors')
|
|
658
|
+
errors.map do |error|
|
|
659
|
+
Error.parse(error['error'])
|
|
660
|
+
end
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
def locator(
|
|
664
|
+
selector,
|
|
665
|
+
has: nil,
|
|
666
|
+
hasNot: nil,
|
|
667
|
+
hasNotText: nil,
|
|
668
|
+
hasText: nil)
|
|
669
|
+
@main_frame.locator(
|
|
670
|
+
selector,
|
|
671
|
+
has: has,
|
|
672
|
+
hasNot: hasNot,
|
|
673
|
+
hasNotText: hasNotText,
|
|
674
|
+
hasText: hasText)
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
def frame_locator(selector)
|
|
678
|
+
@main_frame.frame_locator(selector)
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
def focus(selector, strict: nil, timeout: nil)
|
|
682
|
+
@main_frame.focus(selector, strict: strict, timeout: timeout)
|
|
683
|
+
end
|
|
684
|
+
|
|
685
|
+
def text_content(selector, strict: nil, timeout: nil)
|
|
686
|
+
@main_frame.text_content(selector, strict: strict, timeout: timeout)
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
def inner_text(selector, strict: nil, timeout: nil)
|
|
690
|
+
@main_frame.inner_text(selector, strict: strict, timeout: timeout)
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
def inner_html(selector, strict: nil, timeout: nil)
|
|
694
|
+
@main_frame.inner_html(selector, strict: strict, timeout: timeout)
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
def get_attribute(selector, name, strict: nil, timeout: nil)
|
|
698
|
+
@main_frame.get_attribute(selector, name, strict: strict, timeout: timeout)
|
|
699
|
+
end
|
|
700
|
+
|
|
701
|
+
def hover(
|
|
702
|
+
selector,
|
|
703
|
+
force: nil,
|
|
704
|
+
modifiers: nil,
|
|
705
|
+
noWaitAfter: nil,
|
|
706
|
+
position: nil,
|
|
707
|
+
strict: nil,
|
|
708
|
+
timeout: nil,
|
|
709
|
+
trial: nil)
|
|
710
|
+
@main_frame.hover(
|
|
711
|
+
selector,
|
|
712
|
+
force: force,
|
|
713
|
+
modifiers: modifiers,
|
|
714
|
+
noWaitAfter: noWaitAfter,
|
|
715
|
+
position: position,
|
|
716
|
+
strict: strict,
|
|
717
|
+
timeout: timeout,
|
|
718
|
+
trial: trial,
|
|
719
|
+
)
|
|
720
|
+
end
|
|
721
|
+
|
|
722
|
+
def select_option(
|
|
723
|
+
selector,
|
|
724
|
+
element: nil,
|
|
725
|
+
index: nil,
|
|
726
|
+
value: nil,
|
|
727
|
+
label: nil,
|
|
728
|
+
force: nil,
|
|
729
|
+
noWaitAfter: nil,
|
|
730
|
+
strict: nil,
|
|
731
|
+
timeout: nil)
|
|
732
|
+
@main_frame.select_option(
|
|
733
|
+
selector,
|
|
734
|
+
element: element,
|
|
735
|
+
index: index,
|
|
736
|
+
value: value,
|
|
737
|
+
label: label,
|
|
738
|
+
force: force,
|
|
739
|
+
noWaitAfter: noWaitAfter,
|
|
740
|
+
strict: strict,
|
|
268
741
|
timeout: timeout,
|
|
269
742
|
)
|
|
270
743
|
end
|
|
271
744
|
|
|
272
|
-
def
|
|
273
|
-
@main_frame.
|
|
745
|
+
def input_value(selector, strict: nil, timeout: nil)
|
|
746
|
+
@main_frame.input_value(selector, strict: strict, timeout: timeout)
|
|
274
747
|
end
|
|
275
748
|
|
|
276
|
-
def
|
|
277
|
-
@main_frame.
|
|
749
|
+
def set_input_files(selector, files, noWaitAfter: nil, strict: nil,timeout: nil)
|
|
750
|
+
@main_frame.set_input_files(
|
|
751
|
+
selector,
|
|
752
|
+
files,
|
|
753
|
+
noWaitAfter: noWaitAfter,
|
|
754
|
+
strict: strict,
|
|
755
|
+
timeout: timeout)
|
|
278
756
|
end
|
|
279
757
|
|
|
280
758
|
def type(
|
|
@@ -282,9 +760,16 @@ module Playwright
|
|
|
282
760
|
text,
|
|
283
761
|
delay: nil,
|
|
284
762
|
noWaitAfter: nil,
|
|
763
|
+
strict: nil,
|
|
285
764
|
timeout: nil)
|
|
286
765
|
|
|
287
|
-
@main_frame.type(
|
|
766
|
+
@main_frame.type(
|
|
767
|
+
selector,
|
|
768
|
+
text,
|
|
769
|
+
delay: delay,
|
|
770
|
+
noWaitAfter: noWaitAfter,
|
|
771
|
+
strict: strict,
|
|
772
|
+
timeout: timeout)
|
|
288
773
|
end
|
|
289
774
|
|
|
290
775
|
def press(
|
|
@@ -292,24 +777,185 @@ module Playwright
|
|
|
292
777
|
key,
|
|
293
778
|
delay: nil,
|
|
294
779
|
noWaitAfter: nil,
|
|
780
|
+
strict: nil,
|
|
295
781
|
timeout: nil)
|
|
296
782
|
|
|
297
|
-
@main_frame.press(
|
|
783
|
+
@main_frame.press(
|
|
784
|
+
selector,
|
|
785
|
+
key,
|
|
786
|
+
delay: delay,
|
|
787
|
+
noWaitAfter: noWaitAfter,
|
|
788
|
+
strict: strict,
|
|
789
|
+
timeout: timeout)
|
|
790
|
+
end
|
|
791
|
+
|
|
792
|
+
def check(
|
|
793
|
+
selector,
|
|
794
|
+
force: nil,
|
|
795
|
+
noWaitAfter: nil,
|
|
796
|
+
position: nil,
|
|
797
|
+
strict: nil,
|
|
798
|
+
timeout: nil,
|
|
799
|
+
trial: nil)
|
|
800
|
+
|
|
801
|
+
@main_frame.check(
|
|
802
|
+
selector,
|
|
803
|
+
force: force,
|
|
804
|
+
noWaitAfter: noWaitAfter,
|
|
805
|
+
position: position,
|
|
806
|
+
strict: strict,
|
|
807
|
+
timeout: timeout,
|
|
808
|
+
trial: trial)
|
|
809
|
+
end
|
|
810
|
+
|
|
811
|
+
def uncheck(
|
|
812
|
+
selector,
|
|
813
|
+
force: nil,
|
|
814
|
+
noWaitAfter: nil,
|
|
815
|
+
position: nil,
|
|
816
|
+
strict: nil,
|
|
817
|
+
timeout: nil,
|
|
818
|
+
trial: nil)
|
|
819
|
+
|
|
820
|
+
@main_frame.uncheck(
|
|
821
|
+
selector,
|
|
822
|
+
force: force,
|
|
823
|
+
noWaitAfter: noWaitAfter,
|
|
824
|
+
position: position,
|
|
825
|
+
strict: strict,
|
|
826
|
+
timeout: timeout,
|
|
827
|
+
trial: trial)
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
def set_checked(selector, checked, **options)
|
|
831
|
+
if checked
|
|
832
|
+
check(selector, **options)
|
|
833
|
+
else
|
|
834
|
+
uncheck(selector, **options)
|
|
835
|
+
end
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
def wait_for_timeout(timeout)
|
|
839
|
+
@main_frame.wait_for_timeout(timeout)
|
|
298
840
|
end
|
|
299
841
|
|
|
300
842
|
def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
|
|
301
843
|
@main_frame.wait_for_function(pageFunction, arg: arg, polling: polling, timeout: timeout)
|
|
302
844
|
end
|
|
303
845
|
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
846
|
+
def workers
|
|
847
|
+
@workers.to_a
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
def requests
|
|
851
|
+
@channel.send_message_to_server('requests').map do |req|
|
|
852
|
+
ChannelOwners::Request.from(req)
|
|
307
853
|
end
|
|
308
854
|
end
|
|
309
855
|
|
|
310
|
-
|
|
856
|
+
def request
|
|
857
|
+
@browser_context.request
|
|
858
|
+
end
|
|
859
|
+
|
|
860
|
+
def pause
|
|
861
|
+
@browser_context.send(:pause)
|
|
862
|
+
end
|
|
863
|
+
|
|
864
|
+
def pdf(
|
|
865
|
+
displayHeaderFooter: nil,
|
|
866
|
+
footerTemplate: nil,
|
|
867
|
+
format: nil,
|
|
868
|
+
headerTemplate: nil,
|
|
869
|
+
height: nil,
|
|
870
|
+
landscape: nil,
|
|
871
|
+
margin: nil,
|
|
872
|
+
pageRanges: nil,
|
|
873
|
+
path: nil,
|
|
874
|
+
preferCSSPageSize: nil,
|
|
875
|
+
printBackground: nil,
|
|
876
|
+
scale: nil,
|
|
877
|
+
width: nil,
|
|
878
|
+
tagged: nil,
|
|
879
|
+
outline: nil)
|
|
880
|
+
|
|
881
|
+
params = {
|
|
882
|
+
displayHeaderFooter: displayHeaderFooter,
|
|
883
|
+
footerTemplate: footerTemplate,
|
|
884
|
+
format: format,
|
|
885
|
+
headerTemplate: headerTemplate,
|
|
886
|
+
height: height,
|
|
887
|
+
landscape: landscape,
|
|
888
|
+
margin: margin,
|
|
889
|
+
pageRanges: pageRanges,
|
|
890
|
+
preferCSSPageSize: preferCSSPageSize,
|
|
891
|
+
printBackground: printBackground,
|
|
892
|
+
scale: scale,
|
|
893
|
+
width: width,
|
|
894
|
+
tagged: tagged,
|
|
895
|
+
outline: outline,
|
|
896
|
+
}.compact
|
|
897
|
+
encoded_binary = @channel.send_message_to_server('pdf', params)
|
|
898
|
+
decoded_binary = Base64.strict_decode64(encoded_binary)
|
|
899
|
+
if path
|
|
900
|
+
File.open(path, 'wb') do |f|
|
|
901
|
+
f.write(decoded_binary)
|
|
902
|
+
end
|
|
903
|
+
end
|
|
904
|
+
decoded_binary
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
def video
|
|
908
|
+
return nil unless @browser_context.send(:has_record_video_option?)
|
|
909
|
+
@video ||= Video.new(self)
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
def snapshot_for_ai(timeout: nil, mode: nil, track: nil)
|
|
913
|
+
option_mode = mode || 'full'
|
|
914
|
+
unless ['full', 'incremental'].include?(option_mode)
|
|
915
|
+
raise ArgumentError.new("mode must be either 'full' or 'incremental'")
|
|
916
|
+
end
|
|
917
|
+
|
|
918
|
+
options = {
|
|
919
|
+
timeout: @timeout_settings.timeout(timeout),
|
|
920
|
+
mode: option_mode,
|
|
921
|
+
}
|
|
922
|
+
options[:track] = track if track
|
|
923
|
+
result = @channel.send_message_to_server_result('snapshotForAI', options)
|
|
924
|
+
if option_mode == 'full'
|
|
925
|
+
result['full']
|
|
926
|
+
elsif option_mode == 'incremental'
|
|
927
|
+
result['incremental']
|
|
928
|
+
end
|
|
929
|
+
end
|
|
930
|
+
|
|
931
|
+
def start_js_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
|
|
932
|
+
params = {
|
|
933
|
+
resetOnNavigation: resetOnNavigation,
|
|
934
|
+
reportAnonymousScripts: reportAnonymousScripts,
|
|
935
|
+
}.compact
|
|
936
|
+
|
|
937
|
+
@channel.send_message_to_server('startJSCoverage', params)
|
|
938
|
+
end
|
|
939
|
+
|
|
940
|
+
def stop_js_coverage
|
|
941
|
+
@channel.send_message_to_server('stopJSCoverage')
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
def start_css_coverage(resetOnNavigation: nil, reportAnonymousScripts: nil)
|
|
945
|
+
params = {
|
|
946
|
+
resetOnNavigation: resetOnNavigation,
|
|
947
|
+
}.compact
|
|
948
|
+
|
|
949
|
+
@channel.send_message_to_server('startCSSCoverage', params)
|
|
950
|
+
end
|
|
951
|
+
|
|
952
|
+
def stop_css_coverage
|
|
953
|
+
@channel.send_message_to_server('stopCSSCoverage')
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
class CrashedError < StandardError
|
|
311
957
|
def initialize
|
|
312
|
-
super('Page
|
|
958
|
+
super('Page crashed')
|
|
313
959
|
end
|
|
314
960
|
end
|
|
315
961
|
|
|
@@ -319,34 +965,40 @@ module Playwright
|
|
|
319
965
|
end
|
|
320
966
|
end
|
|
321
967
|
|
|
322
|
-
def
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
[optionsOrPredicate, nil]
|
|
327
|
-
when Hash
|
|
328
|
-
[optionsOrPredicate[:predicate], optionsOrPredicate[:timeout]]
|
|
329
|
-
else
|
|
330
|
-
[nil, nil]
|
|
331
|
-
end
|
|
332
|
-
timeout ||= @timeout_settings.timeout
|
|
968
|
+
private def close_error_with_reason
|
|
969
|
+
reason = @close_reason || @browser_context.send(:effective_close_reason)
|
|
970
|
+
TargetClosedError.new(message: reason)
|
|
971
|
+
end
|
|
333
972
|
|
|
334
|
-
|
|
335
|
-
|
|
973
|
+
def expect_event(event, predicate: nil, timeout: nil, &block)
|
|
974
|
+
waiter = Waiter.new(self, wait_name: "Page.expect_event(#{event})")
|
|
975
|
+
timeout_value = timeout || @timeout_settings.timeout
|
|
976
|
+
waiter.reject_on_timeout(timeout_value, "Timeout #{timeout_value}ms exceeded while waiting for event \"#{event}\"")
|
|
336
977
|
|
|
337
978
|
unless event == Events::Page::Crash
|
|
338
|
-
|
|
979
|
+
waiter.reject_on_event(self, Events::Page::Crash, CrashedError.new)
|
|
339
980
|
end
|
|
340
981
|
|
|
341
982
|
unless event == Events::Page::Close
|
|
342
|
-
|
|
983
|
+
waiter.reject_on_event(self, Events::Page::Close, -> { close_error_with_reason })
|
|
343
984
|
end
|
|
344
985
|
|
|
345
|
-
|
|
346
|
-
|
|
986
|
+
waiter.wait_for_event(self, event, predicate: predicate)
|
|
347
987
|
block&.call
|
|
348
988
|
|
|
349
|
-
|
|
989
|
+
waiter.result.value!
|
|
990
|
+
end
|
|
991
|
+
|
|
992
|
+
def expect_console_message(predicate: nil, timeout: nil, &block)
|
|
993
|
+
expect_event(Events::Page::Console, predicate: predicate, timeout: timeout, &block)
|
|
994
|
+
end
|
|
995
|
+
|
|
996
|
+
def expect_download(predicate: nil, timeout: nil, &block)
|
|
997
|
+
expect_event(Events::Page::Download, predicate: predicate, timeout: timeout, &block)
|
|
998
|
+
end
|
|
999
|
+
|
|
1000
|
+
def expect_file_chooser(predicate: nil, timeout: nil, &block)
|
|
1001
|
+
expect_event(Events::Page::FileChooser, predicate: predicate, timeout: timeout, &block)
|
|
350
1002
|
end
|
|
351
1003
|
|
|
352
1004
|
def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
|
|
@@ -357,11 +1009,15 @@ module Playwright
|
|
|
357
1009
|
&block)
|
|
358
1010
|
end
|
|
359
1011
|
|
|
360
|
-
def
|
|
1012
|
+
def expect_popup(predicate: nil, timeout: nil, &block)
|
|
1013
|
+
expect_event(Events::Page::Popup, predicate: predicate, timeout: timeout, &block)
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
def expect_request(urlOrPredicate, timeout: nil, &block)
|
|
361
1017
|
predicate =
|
|
362
1018
|
case urlOrPredicate
|
|
363
1019
|
when String, Regexp
|
|
364
|
-
url_matcher = UrlMatcher.new(urlOrPredicate)
|
|
1020
|
+
url_matcher = UrlMatcher.new(urlOrPredicate, base_url: @browser_context.send(:base_url))
|
|
365
1021
|
-> (req){ url_matcher.match?(req.url) }
|
|
366
1022
|
when Proc
|
|
367
1023
|
urlOrPredicate
|
|
@@ -369,14 +1025,18 @@ module Playwright
|
|
|
369
1025
|
-> (_) { true }
|
|
370
1026
|
end
|
|
371
1027
|
|
|
372
|
-
expect_event(Events::Page::Request,
|
|
1028
|
+
expect_event(Events::Page::Request, predicate: predicate, timeout: timeout, &block)
|
|
373
1029
|
end
|
|
374
1030
|
|
|
375
|
-
def
|
|
1031
|
+
def expect_request_finished(predicate: nil, timeout: nil, &block)
|
|
1032
|
+
expect_event(Events::Page::RequestFinished, predicate: predicate, timeout: timeout, &block)
|
|
1033
|
+
end
|
|
1034
|
+
|
|
1035
|
+
def expect_response(urlOrPredicate, timeout: nil, &block)
|
|
376
1036
|
predicate =
|
|
377
1037
|
case urlOrPredicate
|
|
378
1038
|
when String, Regexp
|
|
379
|
-
url_matcher = UrlMatcher.new(urlOrPredicate)
|
|
1039
|
+
url_matcher = UrlMatcher.new(urlOrPredicate, base_url: @browser_context.send(:base_url))
|
|
380
1040
|
-> (req){ url_matcher.match?(req.url) }
|
|
381
1041
|
when Proc
|
|
382
1042
|
urlOrPredicate
|
|
@@ -384,18 +1044,41 @@ module Playwright
|
|
|
384
1044
|
-> (_) { true }
|
|
385
1045
|
end
|
|
386
1046
|
|
|
387
|
-
expect_event(Events::Page::Response,
|
|
1047
|
+
expect_event(Events::Page::Response, predicate: predicate, timeout: timeout, &block)
|
|
388
1048
|
end
|
|
389
1049
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
@browser_context = context
|
|
393
|
-
@timeout_settings = TimeoutSettings.new(context.send(:_timeout_settings))
|
|
1050
|
+
def expect_websocket(predicate: nil, timeout: nil, &block)
|
|
1051
|
+
expect_event(Events::Page::WebSocket, predicate: predicate, timeout: timeout, &block)
|
|
394
1052
|
end
|
|
395
1053
|
|
|
396
|
-
|
|
397
|
-
|
|
1054
|
+
def expect_worker(predicate: nil, timeout: nil, &block)
|
|
1055
|
+
expect_event(Events::Page::Worker, predicate: predicate, timeout: timeout, &block)
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
# called from Frame with send(:_timeout_settings)
|
|
1059
|
+
private def _timeout_settings
|
|
398
1060
|
@timeout_settings
|
|
399
1061
|
end
|
|
1062
|
+
|
|
1063
|
+
# called from BrowserContext#expose_binding
|
|
1064
|
+
private def has_bindings?(name)
|
|
1065
|
+
@bindings.key?(name)
|
|
1066
|
+
end
|
|
1067
|
+
|
|
1068
|
+
# called from Worker#on_close
|
|
1069
|
+
private def remove_worker(worker)
|
|
1070
|
+
@workers.delete(worker)
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1073
|
+
# called from Video
|
|
1074
|
+
private def remote_connection?
|
|
1075
|
+
@connection.remote?
|
|
1076
|
+
end
|
|
1077
|
+
|
|
1078
|
+
# Expose guid for library developers.
|
|
1079
|
+
# Not intended to be used by users.
|
|
1080
|
+
def guid
|
|
1081
|
+
@guid
|
|
1082
|
+
end
|
|
400
1083
|
end
|
|
401
1084
|
end
|