playwright-ruby-client 1.28.0 → 1.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/documentation/docs/api/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
|