playwright-ruby-client 1.28.0 → 1.29.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/documentation/docs/api/accessibility.md +9 -14
- data/documentation/docs/api/api_request_context.md +44 -41
- data/documentation/docs/api/api_response.md +13 -3
- data/documentation/docs/api/browser.md +24 -23
- data/documentation/docs/api/browser_context.md +71 -45
- data/documentation/docs/api/browser_type.md +21 -14
- data/documentation/docs/api/cdp_session.md +3 -5
- data/documentation/docs/api/console_message.md +7 -4
- data/documentation/docs/api/dialog.md +9 -5
- data/documentation/docs/api/download.md +19 -11
- data/documentation/docs/api/element_handle.md +125 -116
- data/documentation/docs/api/experimental/android.md +4 -5
- data/documentation/docs/api/experimental/android_device.md +11 -2
- data/documentation/docs/api/experimental/android_input.md +5 -0
- data/documentation/docs/api/file_chooser.md +6 -3
- data/documentation/docs/api/frame.md +182 -171
- data/documentation/docs/api/frame_locator.md +27 -38
- data/documentation/docs/api/js_handle.md +16 -10
- data/documentation/docs/api/keyboard.md +29 -16
- data/documentation/docs/api/locator.md +189 -140
- data/documentation/docs/api/mouse.md +9 -4
- data/documentation/docs/api/page.md +304 -289
- data/documentation/docs/api/playwright.md +8 -5
- data/documentation/docs/api/request.md +34 -15
- data/documentation/docs/api/response.md +27 -10
- data/documentation/docs/api/route.md +44 -12
- data/documentation/docs/api/selectors.md +5 -3
- data/documentation/docs/api/touchscreen.md +2 -0
- data/documentation/docs/api/tracing.md +11 -11
- data/documentation/docs/api/web_socket.md +9 -4
- data/documentation/docs/api/worker.md +12 -11
- data/documentation/docs/include/api_coverage.md +2 -0
- data/lib/playwright/channel_owners/android.rb +2 -2
- data/lib/playwright/channel_owners/android_device.rb +14 -55
- data/lib/playwright/channel_owners/api_request_context.rb +37 -2
- data/lib/playwright/channel_owners/browser_context.rb +22 -26
- data/lib/playwright/channel_owners/page.rb +35 -25
- data/lib/playwright/channel_owners/playwright.rb +7 -0
- data/lib/playwright/channel_owners/route.rb +28 -8
- data/lib/playwright/event_emitter.rb +6 -1
- data/lib/playwright/input_files.rb +3 -1
- data/lib/playwright/locator_impl.rb +8 -0
- data/lib/playwright/select_option_values.rb +2 -0
- data/lib/playwright/version.rb +2 -2
- data/lib/playwright/web_socket_transport.rb +1 -1
- data/lib/playwright.rb +55 -0
- data/lib/playwright_api/accessibility.rb +9 -13
- data/lib/playwright_api/android.rb +8 -6
- data/lib/playwright_api/android_device.rb +37 -7
- data/lib/playwright_api/android_input.rb +5 -0
- data/lib/playwright_api/android_socket.rb +4 -2
- data/lib/playwright_api/android_web_view.rb +5 -2
- data/lib/playwright_api/api_request.rb +6 -3
- data/lib/playwright_api/api_request_context.rb +46 -36
- data/lib/playwright_api/api_response.rb +13 -2
- data/lib/playwright_api/browser.rb +24 -16
- data/lib/playwright_api/browser_context.rb +76 -39
- data/lib/playwright_api/browser_type.rb +23 -13
- data/lib/playwright_api/cdp_session.rb +3 -4
- data/lib/playwright_api/console_message.rb +7 -2
- data/lib/playwright_api/dialog.rb +8 -4
- data/lib/playwright_api/download.rb +19 -9
- data/lib/playwright_api/element_handle.rb +116 -93
- data/lib/playwright_api/file_chooser.rb +6 -1
- data/lib/playwright_api/frame.rb +180 -135
- data/lib/playwright_api/frame_locator.rb +29 -32
- data/lib/playwright_api/js_handle.rb +16 -6
- data/lib/playwright_api/keyboard.rb +29 -14
- data/lib/playwright_api/locator.rb +183 -112
- data/lib/playwright_api/mouse.rb +9 -2
- data/lib/playwright_api/page.rb +301 -253
- data/lib/playwright_api/playwright.rb +11 -4
- data/lib/playwright_api/request.rb +34 -7
- data/lib/playwright_api/response.rb +27 -10
- data/lib/playwright_api/route.rb +44 -11
- data/lib/playwright_api/selectors.rb +6 -1
- data/lib/playwright_api/touchscreen.rb +2 -0
- data/lib/playwright_api/tracing.rb +11 -5
- data/lib/playwright_api/web_socket.rb +9 -4
- data/lib/playwright_api/worker.rb +16 -13
- data/playwright.gemspec +1 -1
- metadata +7 -7
@@ -4,6 +4,7 @@ sidebar_position: 10
|
|
4
4
|
|
5
5
|
# WebSocket
|
6
6
|
|
7
|
+
|
7
8
|
The [WebSocket](./web_socket) class represents websocket connections in the page.
|
8
9
|
|
9
10
|
## closed?
|
@@ -12,6 +13,7 @@ The [WebSocket](./web_socket) class represents websocket connections in the page
|
|
12
13
|
def closed?
|
13
14
|
```
|
14
15
|
|
16
|
+
|
15
17
|
Indicates that the web socket has been closed.
|
16
18
|
|
17
19
|
## url
|
@@ -20,6 +22,7 @@ Indicates that the web socket has been closed.
|
|
20
22
|
def url
|
21
23
|
```
|
22
24
|
|
25
|
+
|
23
26
|
Contains the URL of the WebSocket.
|
24
27
|
|
25
28
|
## expect_event
|
@@ -28,6 +31,7 @@ Contains the URL of the WebSocket.
|
|
28
31
|
def expect_event(event, predicate: nil, timeout: nil, &block)
|
29
32
|
```
|
30
33
|
|
34
|
+
|
31
35
|
Waits for event to fire and passes its value into the predicate function. Returns when the predicate returns truthy
|
32
36
|
value. Will throw an error if the webSocket is closed before the event is fired. Returns the event data value.
|
33
37
|
|
@@ -37,8 +41,9 @@ value. Will throw an error if the webSocket is closed before the event is fired.
|
|
37
41
|
def wait_for_event(event, predicate: nil, timeout: nil, &block)
|
38
42
|
```
|
39
43
|
|
40
|
-
> NOTE: In most cases, you should use [WebSocket#wait_for_event](./web_socket#wait_for_event).
|
41
44
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
**NOTE**: In most cases, you should use [WebSocket#wait_for_event](./web_socket#wait_for_event).
|
46
|
+
|
47
|
+
Waits for given `event` to fire. If predicate is provided, it passes
|
48
|
+
event's value into the `predicate` function and waits for `predicate(event)` to return a truthy value.
|
49
|
+
Will throw an error if the socket is closed before the `event` is fired.
|
@@ -4,6 +4,7 @@ sidebar_position: 10
|
|
4
4
|
|
5
5
|
# Worker
|
6
6
|
|
7
|
+
|
7
8
|
The Worker class represents a [WebWorker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API). `worker`
|
8
9
|
event is emitted on the page object to signal a worker creation. `close` event is emitted on the worker object when the
|
9
10
|
worker is gone.
|
@@ -22,22 +23,20 @@ page.workers.each do |worker|
|
|
22
23
|
end
|
23
24
|
```
|
24
25
|
|
25
|
-
|
26
|
-
|
27
26
|
## evaluate
|
28
27
|
|
29
28
|
```
|
30
29
|
def evaluate(expression, arg: nil)
|
31
30
|
```
|
32
31
|
|
32
|
+
|
33
33
|
Returns the return value of `expression`.
|
34
34
|
|
35
|
-
If the function passed to the [Worker#evaluate](./worker#evaluate) returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then [Worker#evaluate](./worker#evaluate) would
|
36
|
-
|
35
|
+
If the function passed to the [Worker#evaluate](./worker#evaluate) returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then [Worker#evaluate](./worker#evaluate) would wait for the promise
|
36
|
+
to resolve and return its value.
|
37
37
|
|
38
|
-
If the function passed to the [Worker#evaluate](./worker#evaluate) returns a non-[Serializable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description) value, then
|
39
|
-
|
40
|
-
not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
|
38
|
+
If the function passed to the [Worker#evaluate](./worker#evaluate) returns a non-[Serializable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#description) value, then [Worker#evaluate](./worker#evaluate) returns `undefined`. Playwright also supports transferring some
|
39
|
+
additional values that are not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
|
41
40
|
|
42
41
|
## evaluate_handle
|
43
42
|
|
@@ -45,13 +44,15 @@ not serializable by `JSON`: `-0`, `NaN`, `Infinity`, `-Infinity`.
|
|
45
44
|
def evaluate_handle(expression, arg: nil)
|
46
45
|
```
|
47
46
|
|
47
|
+
|
48
48
|
Returns the return value of `expression` as a [JSHandle](./js_handle).
|
49
49
|
|
50
|
-
The only difference between [Worker#evaluate](./worker#evaluate) and
|
51
|
-
[Worker#evaluate_handle](./worker#evaluate_handle)
|
50
|
+
The only difference between [Worker#evaluate](./worker#evaluate) and
|
51
|
+
[Worker#evaluate_handle](./worker#evaluate_handle) is that [Worker#evaluate_handle](./worker#evaluate_handle)
|
52
|
+
returns [JSHandle](./js_handle).
|
52
53
|
|
53
|
-
If the function passed to the [Worker#evaluate_handle](./worker#evaluate_handle) returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then
|
54
|
-
|
54
|
+
If the function passed to the [Worker#evaluate_handle](./worker#evaluate_handle) returns a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), then [Worker#evaluate_handle](./worker#evaluate_handle) would wait for
|
55
|
+
the promise to resolve and return its value.
|
55
56
|
|
56
57
|
## url
|
57
58
|
|
@@ -4,8 +4,8 @@ module Playwright
|
|
4
4
|
@timeout_settings = TimeoutSettings.new
|
5
5
|
end
|
6
6
|
|
7
|
-
def devices(port: nil)
|
8
|
-
params = { port: port }.compact
|
7
|
+
def devices(host: nil, omitDriverInstall: nil, port: nil)
|
8
|
+
params = { host: host, port: port, omitDriverInstall: omitDriverInstall }.compact
|
9
9
|
resp = @channel.send_message_to_server('devices', params)
|
10
10
|
resp.map { |device| ChannelOwners::AndroidDevice.from(device) }
|
11
11
|
end
|
@@ -4,6 +4,11 @@ module Playwright
|
|
4
4
|
|
5
5
|
private def after_initialize
|
6
6
|
@input = AndroidInputImpl.new(@channel)
|
7
|
+
@should_close_connection_on_close = false
|
8
|
+
end
|
9
|
+
|
10
|
+
def should_close_connection_on_close!
|
11
|
+
@should_close_connection_on_close = true
|
7
12
|
end
|
8
13
|
|
9
14
|
attr_reader :input
|
@@ -77,8 +82,12 @@ module Playwright
|
|
77
82
|
end
|
78
83
|
|
79
84
|
def close
|
80
|
-
@channel.send_message_to_server('close')
|
81
85
|
emit(Events::AndroidDevice::Close)
|
86
|
+
if @should_close_connection_on_close
|
87
|
+
@connection.stop
|
88
|
+
else
|
89
|
+
@channel.send_message_to_server('close')
|
90
|
+
end
|
82
91
|
end
|
83
92
|
|
84
93
|
def shell(command)
|
@@ -86,60 +95,10 @@ module Playwright
|
|
86
95
|
Base64.strict_decode64(resp)
|
87
96
|
end
|
88
97
|
|
89
|
-
def launch_browser(
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
colorScheme: nil,
|
94
|
-
deviceScaleFactor: nil,
|
95
|
-
extraHTTPHeaders: nil,
|
96
|
-
geolocation: nil,
|
97
|
-
hasTouch: nil,
|
98
|
-
httpCredentials: nil,
|
99
|
-
ignoreHTTPSErrors: nil,
|
100
|
-
isMobile: nil,
|
101
|
-
javaScriptEnabled: nil,
|
102
|
-
locale: nil,
|
103
|
-
noViewport: nil,
|
104
|
-
offline: nil,
|
105
|
-
permissions: nil,
|
106
|
-
proxy: nil,
|
107
|
-
record_har_omit_content: nil,
|
108
|
-
record_har_path: nil,
|
109
|
-
record_video_dir: nil,
|
110
|
-
record_video_size: nil,
|
111
|
-
storageState: nil,
|
112
|
-
timezoneId: nil,
|
113
|
-
userAgent: nil,
|
114
|
-
viewport: nil,
|
115
|
-
&block)
|
116
|
-
params = {
|
117
|
-
pkg: pkg,
|
118
|
-
acceptDownloads: acceptDownloads,
|
119
|
-
bypassCSP: bypassCSP,
|
120
|
-
colorScheme: colorScheme,
|
121
|
-
deviceScaleFactor: deviceScaleFactor,
|
122
|
-
extraHTTPHeaders: extraHTTPHeaders,
|
123
|
-
geolocation: geolocation,
|
124
|
-
hasTouch: hasTouch,
|
125
|
-
httpCredentials: httpCredentials,
|
126
|
-
ignoreHTTPSErrors: ignoreHTTPSErrors,
|
127
|
-
isMobile: isMobile,
|
128
|
-
javaScriptEnabled: javaScriptEnabled,
|
129
|
-
locale: locale,
|
130
|
-
noViewport: noViewport,
|
131
|
-
offline: offline,
|
132
|
-
permissions: permissions,
|
133
|
-
proxy: proxy,
|
134
|
-
record_har_omit_content: record_har_omit_content,
|
135
|
-
record_har_path: record_har_path,
|
136
|
-
record_video_dir: record_video_dir,
|
137
|
-
record_video_size: record_video_size,
|
138
|
-
storageState: storageState,
|
139
|
-
timezoneId: timezoneId,
|
140
|
-
userAgent: userAgent,
|
141
|
-
viewport: viewport,
|
142
|
-
}.compact
|
98
|
+
def launch_browser(pkg: nil, **options, &block)
|
99
|
+
params = options.dup
|
100
|
+
params[:pkg] = pkg
|
101
|
+
params.compact!
|
143
102
|
prepare_browser_context_options(params)
|
144
103
|
|
145
104
|
resp = @channel.send_message_to_server('launchBrowser', params)
|
@@ -56,6 +56,42 @@ module Playwright
|
|
56
56
|
if [ChannelOwners::Request, String].none? { |type| urlOrRequest.is_a?(type) }
|
57
57
|
raise ArgumentError.new("First argument must be either URL string or Request")
|
58
58
|
end
|
59
|
+
if urlOrRequest.is_a?(ChannelOwners::Request)
|
60
|
+
request = urlOrRequest
|
61
|
+
url = nil
|
62
|
+
else
|
63
|
+
url = urlOrRequest
|
64
|
+
request = nil
|
65
|
+
end
|
66
|
+
_inner_fetch(
|
67
|
+
request,
|
68
|
+
url,
|
69
|
+
data: data,
|
70
|
+
failOnStatusCode: failOnStatusCode,
|
71
|
+
form: form,
|
72
|
+
headers: headers,
|
73
|
+
ignoreHTTPSErrors: ignoreHTTPSErrors,
|
74
|
+
maxRedirects: maxRedirects,
|
75
|
+
method: method,
|
76
|
+
multipart: multipart,
|
77
|
+
params: params,
|
78
|
+
timeout: timeout,
|
79
|
+
)
|
80
|
+
end
|
81
|
+
|
82
|
+
private def _inner_fetch(
|
83
|
+
request,
|
84
|
+
url,
|
85
|
+
data: nil,
|
86
|
+
failOnStatusCode: nil,
|
87
|
+
form: nil,
|
88
|
+
headers: nil,
|
89
|
+
ignoreHTTPSErrors: nil,
|
90
|
+
maxRedirects: nil,
|
91
|
+
method: nil,
|
92
|
+
multipart: nil,
|
93
|
+
params: nil,
|
94
|
+
timeout: nil)
|
59
95
|
if [data, form, multipart].compact.count > 1
|
60
96
|
raise ArgumentError.new("Only one of 'data', 'form' or 'multipart' can be specified")
|
61
97
|
end
|
@@ -63,10 +99,9 @@ module Playwright
|
|
63
99
|
raise ArgumentError.new("'maxRedirects' should be greater than or equal to '0'")
|
64
100
|
end
|
65
101
|
|
66
|
-
request = urlOrRequest.is_a?(ChannelOwners::Request) ? urlOrRequest : nil
|
67
102
|
headers_obj = headers || request&.headers
|
68
103
|
fetch_params = {
|
69
|
-
url:
|
104
|
+
url: url || request.url,
|
70
105
|
params: object_to_array(params),
|
71
106
|
method: method || request&.method || 'GET',
|
72
107
|
headers: headers_obj ? HttpHeaders.new(headers_obj).as_serialized : nil,
|
@@ -24,13 +24,7 @@ module Playwright
|
|
24
24
|
@channel.on('bindingCall', ->(params) { on_binding(ChannelOwners::BindingCall.from(params['binding'])) })
|
25
25
|
@channel.once('close', ->(_) { on_close })
|
26
26
|
@channel.on('page', ->(params) { on_page(ChannelOwners::Page.from(params['page']) )})
|
27
|
-
@channel.on('route', ->(params) {
|
28
|
-
Concurrent::Promises.future {
|
29
|
-
on_route(ChannelOwners::Route.from(params['route']))
|
30
|
-
}.rescue do |err|
|
31
|
-
puts err, err.backtrace
|
32
|
-
end
|
33
|
-
})
|
27
|
+
@channel.on('route', ->(params) { on_route(ChannelOwners::Route.from(params['route'])) })
|
34
28
|
@channel.on('backgroundPage', ->(params) {
|
35
29
|
on_background_page(ChannelOwners::Page.from(params['page']))
|
36
30
|
})
|
@@ -93,31 +87,33 @@ module Playwright
|
|
93
87
|
# It is not desired to use PlaywrightApi.wrap directly.
|
94
88
|
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
95
89
|
# Just a workaround...
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
next false unless handler_entry.match?(route.request.url)
|
90
|
+
Concurrent::Promises.future(PlaywrightApi.wrap(route)) do |wrapped_route|
|
91
|
+
handled = @routes.any? do |handler_entry|
|
92
|
+
next false unless handler_entry.match?(route.request.url)
|
100
93
|
|
101
|
-
|
102
|
-
|
94
|
+
promise = Concurrent::Promises.resolvable_future
|
95
|
+
route.send(:set_handling_future, promise)
|
103
96
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
97
|
+
promise_handled = Concurrent::Promises.zip(
|
98
|
+
promise,
|
99
|
+
handler_entry.async_handle(wrapped_route)
|
100
|
+
).value!.first
|
108
101
|
|
109
|
-
|
110
|
-
|
102
|
+
promise_handled
|
103
|
+
end
|
111
104
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
105
|
+
@routes.reject!(&:expired?)
|
106
|
+
if @routes.count == 0
|
107
|
+
@channel.async_send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
108
|
+
end
|
116
109
|
|
117
|
-
|
118
|
-
|
119
|
-
|
110
|
+
unless handled
|
111
|
+
route.send(:async_continue_route).rescue do |err|
|
112
|
+
puts err, err.backtrace
|
113
|
+
end
|
120
114
|
end
|
115
|
+
end.rescue do |err|
|
116
|
+
puts err, err.backtrace
|
121
117
|
end
|
122
118
|
end
|
123
119
|
|
@@ -59,13 +59,7 @@ module Playwright
|
|
59
59
|
@channel.on('pageError', ->(params) {
|
60
60
|
emit(Events::Page::PageError, Error.parse(params['error']['error']))
|
61
61
|
})
|
62
|
-
@channel.on('route', ->(params) {
|
63
|
-
Concurrent::Promises.future {
|
64
|
-
on_route(ChannelOwners::Route.from(params['route']))
|
65
|
-
}.rescue do |err|
|
66
|
-
puts err, err.backtrace
|
67
|
-
end
|
68
|
-
})
|
62
|
+
@channel.on('route', ->(params) { on_route(ChannelOwners::Route.from(params['route'])) })
|
69
63
|
@channel.on('video', method(:on_video))
|
70
64
|
@channel.on('webSocket', ->(params) {
|
71
65
|
emit(Events::Page::WebSocket, ChannelOwners::WebSocket.from(params['webSocket']))
|
@@ -108,29 +102,31 @@ module Playwright
|
|
108
102
|
# It is not desired to use PlaywrightApi.wrap directly.
|
109
103
|
# However it is a little difficult to define wrapper for `handler` parameter in generate_api.
|
110
104
|
# Just a workaround...
|
111
|
-
|
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)
|
112
108
|
|
113
|
-
|
114
|
-
|
109
|
+
promise = Concurrent::Promises.resolvable_future
|
110
|
+
route.send(:set_handling_future, promise)
|
115
111
|
|
116
|
-
|
117
|
-
|
112
|
+
promise_handled = Concurrent::Promises.zip(
|
113
|
+
promise,
|
114
|
+
handler_entry.async_handle(wrapped_route)
|
115
|
+
).value!.first
|
118
116
|
|
119
|
-
|
120
|
-
|
121
|
-
handler_entry.async_handle(wrapped_route)
|
122
|
-
).value!.first
|
123
|
-
|
124
|
-
promise_handled
|
125
|
-
end
|
117
|
+
promise_handled
|
118
|
+
end
|
126
119
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
120
|
+
@routes.reject!(&:expired?)
|
121
|
+
if @routes.count == 0
|
122
|
+
@channel.async_send_message_to_server('setNetworkInterceptionEnabled', enabled: false)
|
123
|
+
end
|
131
124
|
|
132
|
-
|
133
|
-
|
125
|
+
unless handled
|
126
|
+
@browser_context.send(:on_route, route)
|
127
|
+
end
|
128
|
+
end.rescue do |err|
|
129
|
+
puts err, err.backtrace
|
134
130
|
end
|
135
131
|
end
|
136
132
|
|
@@ -178,6 +174,20 @@ module Playwright
|
|
178
174
|
video.send(:set_artifact, artifact)
|
179
175
|
end
|
180
176
|
|
177
|
+
# @override
|
178
|
+
private def perform_event_emitter_callback(event, callback, args)
|
179
|
+
should_callback_async = [
|
180
|
+
Events::Page::Dialog,
|
181
|
+
Events::Page::Response,
|
182
|
+
].freeze
|
183
|
+
|
184
|
+
if should_callback_async.include?(event)
|
185
|
+
Concurrent::Promises.future { super }
|
186
|
+
else
|
187
|
+
super
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
181
191
|
def context
|
182
192
|
@browser_context
|
183
193
|
end
|
@@ -39,6 +39,13 @@ module Playwright
|
|
39
39
|
::Playwright::ChannelOwners::Browser.from(@initializer['preLaunchedBrowser'])
|
40
40
|
end
|
41
41
|
|
42
|
+
private def pre_connected_android_device
|
43
|
+
unless @initializer['preConnectedAndroidDevice']
|
44
|
+
raise 'Malformed endpoint. Did you use Android.launchServer method?'
|
45
|
+
end
|
46
|
+
::Playwright::ChannelOwners::AndroidDevice.from(@initializer['preConnectedAndroidDevice'])
|
47
|
+
end
|
48
|
+
|
42
49
|
private def parse_device_descriptor(descriptor)
|
43
50
|
# This return value can be passed into Browser#new_context as it is.
|
44
51
|
# ex:
|
@@ -31,21 +31,27 @@ module Playwright
|
|
31
31
|
body: nil,
|
32
32
|
contentType: nil,
|
33
33
|
headers: nil,
|
34
|
+
json: nil,
|
34
35
|
path: nil,
|
35
36
|
status: nil,
|
36
37
|
response: nil)
|
37
38
|
handling_with_result(true) do
|
38
|
-
|
39
|
-
|
40
|
-
status: status,
|
41
|
-
}.compact
|
39
|
+
option_status = status
|
40
|
+
option_headers = headers
|
42
41
|
option_body = body
|
43
42
|
|
43
|
+
if json
|
44
|
+
raise ArgumentError.new('Can specify either body or json parameters') if body
|
45
|
+
option_body = JSON.generate(json)
|
46
|
+
end
|
47
|
+
|
48
|
+
params = {}
|
49
|
+
|
44
50
|
if response
|
45
|
-
|
46
|
-
|
51
|
+
option_status ||= response.status
|
52
|
+
option_headers ||= response.headers
|
47
53
|
|
48
|
-
if !body && !path && response.is_a?(
|
54
|
+
if !body && !path && response.is_a?(APIResponseImpl)
|
49
55
|
if response.send(:_request).send(:same_connection?, self)
|
50
56
|
params[:fetchResponseUid] = response.send(:fetch_uid)
|
51
57
|
else
|
@@ -63,9 +69,11 @@ module Playwright
|
|
63
69
|
nil
|
64
70
|
end
|
65
71
|
|
66
|
-
param_headers =
|
72
|
+
param_headers = option_headers || {}
|
67
73
|
if contentType
|
68
74
|
param_headers['content-type'] = contentType
|
75
|
+
elsif json
|
76
|
+
param_headers['content-type'] = 'application/json'
|
69
77
|
elsif path
|
70
78
|
param_headers['content-type'] = mime_type_for(path)
|
71
79
|
end
|
@@ -81,6 +89,7 @@ module Playwright
|
|
81
89
|
param_headers['content-length'] ||= content.length.to_s
|
82
90
|
end
|
83
91
|
|
92
|
+
params[:status] = option_status || 200
|
84
93
|
params[:headers] = HttpHeaders.new(param_headers).as_serialized
|
85
94
|
|
86
95
|
@channel.async_send_message_to_server('fulfill', params)
|
@@ -100,6 +109,17 @@ module Playwright
|
|
100
109
|
end
|
101
110
|
end
|
102
111
|
|
112
|
+
def fetch(headers: nil, method: nil, postData: nil, url: nil)
|
113
|
+
api_request_context = request.frame.page.context.request
|
114
|
+
api_request_context.send(:_inner_fetch,
|
115
|
+
request,
|
116
|
+
url,
|
117
|
+
headers: headers,
|
118
|
+
method: method,
|
119
|
+
data: postData,
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
103
123
|
def continue(headers: nil, method: nil, postData: nil, url: nil)
|
104
124
|
overrides = {
|
105
125
|
headers: headers,
|
@@ -38,7 +38,7 @@ module Playwright
|
|
38
38
|
def emit(event, *args)
|
39
39
|
handled = false
|
40
40
|
(@__event_emitter ||= {})[event.to_s]&.each do |callback|
|
41
|
-
callback
|
41
|
+
perform_event_emitter_callback(event, callback, args)
|
42
42
|
handled = true
|
43
43
|
end
|
44
44
|
handled
|
@@ -48,6 +48,11 @@ module Playwright
|
|
48
48
|
((@__event_emitter ||= {})[event.to_s] ||= Set.new).count
|
49
49
|
end
|
50
50
|
|
51
|
+
# can be overriden
|
52
|
+
private def perform_event_emitter_callback(event, callback, args)
|
53
|
+
callback.call(*args)
|
54
|
+
end
|
55
|
+
|
51
56
|
# @param event [String]
|
52
57
|
# @param callback [Proc]
|
53
58
|
def on(event, callback)
|
@@ -263,6 +263,14 @@ module Playwright
|
|
263
263
|
@frame.channel.send_message_to_server('blur', params)
|
264
264
|
end
|
265
265
|
|
266
|
+
def all
|
267
|
+
Enumerator.new do |out|
|
268
|
+
count.times do |i|
|
269
|
+
out << nth(i)
|
270
|
+
end
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
266
274
|
def count
|
267
275
|
@frame.eval_on_selector_all(@selector, 'ee => ee.length')
|
268
276
|
end
|
data/lib/playwright/version.rb
CHANGED
data/lib/playwright.rb
CHANGED
@@ -51,6 +51,22 @@ module Playwright
|
|
51
51
|
attr_reader :playwright, :browser
|
52
52
|
end
|
53
53
|
|
54
|
+
class AndroidExecution
|
55
|
+
def initialize(connection, playwright, device = nil)
|
56
|
+
@connection = connection
|
57
|
+
@playwright = playwright
|
58
|
+
@device = device
|
59
|
+
end
|
60
|
+
|
61
|
+
def stop
|
62
|
+
@device&.close
|
63
|
+
@connection.stop
|
64
|
+
end
|
65
|
+
|
66
|
+
attr_reader :playwright, :device
|
67
|
+
end
|
68
|
+
|
69
|
+
|
54
70
|
# Recommended to call this method with block.
|
55
71
|
#
|
56
72
|
# Playwright.create(...) do |playwright|
|
@@ -161,4 +177,43 @@ module Playwright
|
|
161
177
|
execution
|
162
178
|
end
|
163
179
|
end
|
180
|
+
|
181
|
+
# Connects to Playwright server, launched by `npx playwright launch-server chromium` or `playwright.chromium.launchServer()`
|
182
|
+
#
|
183
|
+
# Playwright.connect_to_browser_server('ws://....') do |browser|
|
184
|
+
# page = browser.new_page
|
185
|
+
# ...
|
186
|
+
# end
|
187
|
+
#
|
188
|
+
# @experimental
|
189
|
+
module_function def connect_to_android_server(ws_endpoint, &block)
|
190
|
+
require 'playwright/web_socket_client'
|
191
|
+
require 'playwright/web_socket_transport'
|
192
|
+
|
193
|
+
transport = WebSocketTransport.new(ws_endpoint: ws_endpoint)
|
194
|
+
connection = Connection.new(transport)
|
195
|
+
connection.mark_as_remote
|
196
|
+
connection.async_run
|
197
|
+
|
198
|
+
execution =
|
199
|
+
begin
|
200
|
+
playwright = connection.initialize_playwright
|
201
|
+
android_device = playwright.send(:pre_connected_android_device)
|
202
|
+
android_device.should_close_connection_on_close!
|
203
|
+
AndroidExecution.new(connection, PlaywrightApi.wrap(playwright), PlaywrightApi.wrap(android_device))
|
204
|
+
rescue
|
205
|
+
connection.stop
|
206
|
+
raise
|
207
|
+
end
|
208
|
+
|
209
|
+
if block
|
210
|
+
begin
|
211
|
+
block.call(execution.device)
|
212
|
+
ensure
|
213
|
+
execution.stop
|
214
|
+
end
|
215
|
+
else
|
216
|
+
execution
|
217
|
+
end
|
218
|
+
end
|
164
219
|
end
|