playwright-ruby-client 0.0.3 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +119 -12
- data/docs/api_coverage.md +354 -0
- data/lib/playwright.rb +8 -0
- data/lib/playwright/channel_owner.rb +16 -2
- data/lib/playwright/channel_owners/android.rb +10 -1
- data/lib/playwright/channel_owners/android_device.rb +163 -0
- data/lib/playwright/channel_owners/browser.rb +22 -29
- data/lib/playwright/channel_owners/browser_context.rb +43 -0
- data/lib/playwright/channel_owners/console_message.rb +21 -0
- data/lib/playwright/channel_owners/element_handle.rb +314 -0
- data/lib/playwright/channel_owners/frame.rb +466 -7
- data/lib/playwright/channel_owners/js_handle.rb +55 -0
- data/lib/playwright/channel_owners/page.rb +353 -5
- data/lib/playwright/channel_owners/request.rb +90 -0
- data/lib/playwright/channel_owners/webkit_browser.rb +1 -1
- data/lib/playwright/connection.rb +15 -14
- data/lib/playwright/errors.rb +1 -1
- data/lib/playwright/event_emitter.rb +13 -0
- data/lib/playwright/input_files.rb +42 -0
- data/lib/playwright/input_type.rb +19 -0
- data/lib/playwright/input_types/android_input.rb +19 -0
- data/lib/playwright/input_types/keyboard.rb +32 -0
- data/lib/playwright/input_types/mouse.rb +4 -0
- data/lib/playwright/input_types/touchscreen.rb +4 -0
- data/lib/playwright/javascript.rb +13 -0
- data/lib/playwright/javascript/expression.rb +67 -0
- data/lib/playwright/javascript/function.rb +67 -0
- data/lib/playwright/javascript/value_parser.rb +75 -0
- data/lib/playwright/javascript/value_serializer.rb +54 -0
- data/lib/playwright/playwright_api.rb +45 -25
- data/lib/playwright/select_option_values.rb +32 -0
- data/lib/playwright/timeout_settings.rb +19 -0
- data/lib/playwright/url_matcher.rb +19 -0
- data/lib/playwright/utils.rb +37 -0
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright/wait_helper.rb +73 -0
- data/lib/playwright_api/accessibility.rb +60 -6
- data/lib/playwright_api/android.rb +33 -0
- data/lib/playwright_api/android_device.rb +78 -0
- data/lib/playwright_api/android_input.rb +25 -0
- data/lib/playwright_api/binding_call.rb +18 -0
- data/lib/playwright_api/browser.rb +136 -44
- data/lib/playwright_api/browser_context.rb +378 -51
- data/lib/playwright_api/browser_type.rb +137 -55
- data/lib/playwright_api/cdp_session.rb +32 -7
- data/lib/playwright_api/chromium_browser_context.rb +31 -0
- data/lib/playwright_api/console_message.rb +27 -7
- data/lib/playwright_api/dialog.rb +47 -3
- data/lib/playwright_api/download.rb +29 -5
- data/lib/playwright_api/element_handle.rb +429 -143
- data/lib/playwright_api/file_chooser.rb +13 -2
- data/lib/playwright_api/frame.rb +633 -179
- data/lib/playwright_api/js_handle.rb +97 -17
- data/lib/playwright_api/keyboard.rb +152 -24
- data/lib/playwright_api/mouse.rb +28 -3
- data/lib/playwright_api/page.rb +1183 -317
- data/lib/playwright_api/playwright.rb +174 -13
- data/lib/playwright_api/request.rb +115 -30
- data/lib/playwright_api/response.rb +22 -3
- data/lib/playwright_api/route.rb +63 -4
- data/lib/playwright_api/selectors.rb +29 -7
- data/lib/playwright_api/touchscreen.rb +2 -1
- data/lib/playwright_api/video.rb +11 -1
- data/lib/playwright_api/web_socket.rb +5 -5
- data/lib/playwright_api/worker.rb +29 -5
- data/playwright.gemspec +3 -0
- metadata +68 -2
@@ -0,0 +1,55 @@
|
|
1
|
+
module Playwright
|
2
|
+
define_channel_owner :JSHandle do
|
3
|
+
def after_initialize
|
4
|
+
@preview = @initializer['preview']
|
5
|
+
@channel.on('previewUpdated', method(:on_preview_updated))
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
@preview
|
10
|
+
end
|
11
|
+
|
12
|
+
private def on_preview_updated(preview)
|
13
|
+
@preview = preview
|
14
|
+
end
|
15
|
+
|
16
|
+
def evaluate(pageFunction, arg: nil)
|
17
|
+
if JavaScript.function?(pageFunction)
|
18
|
+
JavaScript::Function.new(pageFunction, arg).evaluate(@channel)
|
19
|
+
else
|
20
|
+
JavaScript::Expression.new(pageFunction).evaluate(@channel)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def evaluate_handle(pageFunction, arg: nil)
|
25
|
+
if JavaScript.function?(pageFunction)
|
26
|
+
JavaScript::Function.new(pageFunction, arg).evaluate_handle(@channel)
|
27
|
+
else
|
28
|
+
JavaScript::Expression.new(pageFunction).evaluate_handle(@channel)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_properties
|
33
|
+
resp = @channel.send_message_to_server('getPropertyList')
|
34
|
+
resp.map { |prop| [prop['name'], ChannelOwner.from(prop['value'])] }.to_h
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_property(name)
|
38
|
+
resp = @channel.send_message_to_server('getProperty', name: name)
|
39
|
+
ChannelOwner.from(resp)
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_element
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
|
46
|
+
def dispose
|
47
|
+
@channel.send_message_to_server('dispose')
|
48
|
+
end
|
49
|
+
|
50
|
+
def json_value
|
51
|
+
value = @channel.send_message_to_server('jsonValue')
|
52
|
+
JavaScript::ValueParser.new(value).parse
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -3,26 +3,183 @@ require 'base64'
|
|
3
3
|
module Playwright
|
4
4
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_page.py
|
5
5
|
define_channel_owner :Page do
|
6
|
+
include Utils::Errors::SafeCloseError
|
6
7
|
attr_writer :owned_context
|
7
8
|
|
8
9
|
def after_initialize
|
10
|
+
@browser_context = @parent
|
11
|
+
@timeout_settings = TimeoutSettings.new(@browser_context.send(:_timeout_settings))
|
9
12
|
@accessibility = Accessibility.new(@channel)
|
10
|
-
@keyboard = Keyboard.new(@channel)
|
11
|
-
@mouse = Mouse.new(@channel)
|
12
|
-
@touchscreen = Touchscreen.new(@channel)
|
13
|
+
@keyboard = InputTypes::Keyboard.new(@channel)
|
14
|
+
@mouse = InputTypes::Mouse.new(@channel)
|
15
|
+
@touchscreen = InputTypes::Touchscreen.new(@channel)
|
13
16
|
|
17
|
+
@viewport_size = @initializer['viewportSize']
|
18
|
+
@closed = false
|
14
19
|
@main_frame = ChannelOwners::Frame.from(@initializer['mainFrame'])
|
15
20
|
@main_frame.send(:update_page_from_page, self)
|
16
21
|
@frames = Set.new
|
17
22
|
@frames << @main_frame
|
23
|
+
|
24
|
+
@channel.once('close', ->(_) { on_close })
|
25
|
+
@channel.on('console', ->(params) {
|
26
|
+
console_message = ChannelOwners::ConsoleMessage.from(params['message'])
|
27
|
+
emit(Events::Page::Console, console_message)
|
28
|
+
})
|
29
|
+
@channel.on('domcontentloaded', ->(_) { emit(Events::Page::DOMContentLoaded) })
|
30
|
+
@channel.on('frameAttached', ->(params) {
|
31
|
+
on_frame_attached(ChannelOwners::Frame.from(params['frame']))
|
32
|
+
})
|
33
|
+
@channel.on('frameDetached', ->(params) {
|
34
|
+
on_frame_detached(ChannelOwners::Frame.from(params['frame']))
|
35
|
+
})
|
36
|
+
@channel.on('load', ->(_) { emit(Events::Page::Load) })
|
37
|
+
@channel.on('popup', ->(params) {
|
38
|
+
emit(Events::Page::Popup, ChannelOwners::Page.from(params['page']))
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader \
|
43
|
+
:accessibility,
|
44
|
+
:keyboard,
|
45
|
+
:mouse,
|
46
|
+
:touchscreen,
|
47
|
+
:viewport_size,
|
48
|
+
:main_frame
|
49
|
+
|
50
|
+
private def on_frame_attached(frame)
|
51
|
+
frame.send(:update_page_from_page, self)
|
52
|
+
@frames << frame
|
53
|
+
emit(Events::Page::FrameAttached, frame)
|
54
|
+
end
|
55
|
+
|
56
|
+
private def on_frame_detached(frame)
|
57
|
+
@frames.delete(frame)
|
58
|
+
frame.detached = true
|
59
|
+
emit(Events::Page::FrameDetached, frame)
|
60
|
+
end
|
61
|
+
|
62
|
+
private def on_close
|
63
|
+
@closed = true
|
64
|
+
@browser_context.send(:remove_page, self)
|
65
|
+
emit(Events::Page::Close)
|
66
|
+
end
|
67
|
+
|
68
|
+
def context
|
69
|
+
@browser_context
|
70
|
+
end
|
71
|
+
|
72
|
+
def opener
|
73
|
+
resp = @channel.send_message_to_server('opener')
|
74
|
+
ChannelOwners::Page.from(resp)
|
75
|
+
end
|
76
|
+
|
77
|
+
def frame(frameSelector)
|
78
|
+
name, url =
|
79
|
+
if frameSelector.is_a?(Hash)
|
80
|
+
[frameSelector[:name], frameSelector[:url]]
|
81
|
+
else
|
82
|
+
[frameSelector, nil]
|
83
|
+
end
|
84
|
+
|
85
|
+
if name
|
86
|
+
@frames.find { |f| f.name == name }
|
87
|
+
elsif url
|
88
|
+
# ref: https://github.com/microsoft/playwright-python/blob/c4320c27cb080b385a5e45be46baa3cb7a9409ff/playwright/_impl/_helper.py#L104
|
89
|
+
case url
|
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
|
97
|
+
else
|
98
|
+
raise ArgumentError.new('Either name or url matcher should be specified')
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def frames
|
103
|
+
@frames.to_a
|
104
|
+
end
|
105
|
+
|
106
|
+
def set_default_navigation_timeout(timeout)
|
107
|
+
@timeout_settings.default_navigation_timeout = timeout
|
108
|
+
@channel.send_message_to_server('setDefaultNavigationTimeoutNoReply', timeout: timeout)
|
109
|
+
end
|
110
|
+
|
111
|
+
def set_default_timeout(timeout)
|
112
|
+
@timeout_settings.default_timeout = timeout
|
113
|
+
@channel.send_message_to_server('setDefaultTimeoutNoReply', timeout: timeout)
|
114
|
+
end
|
115
|
+
|
116
|
+
def query_selector(selector)
|
117
|
+
@main_frame.query_selector(selector)
|
118
|
+
end
|
119
|
+
|
120
|
+
def query_selector_all(selector)
|
121
|
+
@main_frame.query_selector_all(selector)
|
122
|
+
end
|
123
|
+
|
124
|
+
def evaluate(pageFunction, arg: nil)
|
125
|
+
@main_frame.evaluate(pageFunction, arg: arg)
|
126
|
+
end
|
127
|
+
|
128
|
+
def evaluate_handle(pageFunction, arg: nil)
|
129
|
+
@main_frame.evaluate_handle(pageFunction, arg: arg)
|
130
|
+
end
|
131
|
+
|
132
|
+
def eval_on_selector(selector, pageFunction, arg: nil)
|
133
|
+
@main_frame.eval_on_selector(selector, pageFunction, arg: arg)
|
134
|
+
end
|
135
|
+
|
136
|
+
def eval_on_selector_all(selector, pageFunction, arg: nil)
|
137
|
+
@main_frame.eval_on_selector_all(selector, pageFunction, arg: arg)
|
18
138
|
end
|
19
139
|
|
20
|
-
|
140
|
+
def add_script_tag(content: nil, path: nil, type: nil, url: nil)
|
141
|
+
@main_frame.add_script_tag(content: content, path: path, type: type, url: url)
|
142
|
+
end
|
143
|
+
|
144
|
+
def add_style_tag(content: nil, path: nil, url: nil)
|
145
|
+
@main_frame.add_style_tag(content: content, path: path, url: url)
|
146
|
+
end
|
147
|
+
|
148
|
+
def url
|
149
|
+
@main_frame.url
|
150
|
+
end
|
151
|
+
|
152
|
+
def content
|
153
|
+
@main_frame.content
|
154
|
+
end
|
155
|
+
|
156
|
+
def set_content(html, timeout: nil, waitUntil: nil)
|
157
|
+
@main_frame.set_content(html, timeout: timeout, waitUntil: waitUntil)
|
158
|
+
end
|
21
159
|
|
22
160
|
def goto(url, timeout: nil, waitUntil: nil, referer: nil)
|
23
161
|
@main_frame.goto(url, timeout: timeout, waitUntil: waitUntil, referer: referer)
|
24
162
|
end
|
25
163
|
|
164
|
+
def reload(timeout: nil, waitUntil: nil)
|
165
|
+
params = {
|
166
|
+
timeout: timeout,
|
167
|
+
waitUntil: waitUntil,
|
168
|
+
}.compact
|
169
|
+
resp = @channel.send_message_to_server('reoad', params)
|
170
|
+
ChannelOwners::Response.from_nullable(resp)
|
171
|
+
end
|
172
|
+
|
173
|
+
def wait_for_load_state(state: nil, timeout: nil)
|
174
|
+
@main_frame.wait_for_load_state(state: state, timeout: timeout)
|
175
|
+
end
|
176
|
+
|
177
|
+
def set_viewport_size(viewportSize)
|
178
|
+
@viewport_size = viewportSize
|
179
|
+
@channel.send_message_to_server('setViewportSize', { viewportSize: viewportSize })
|
180
|
+
nil
|
181
|
+
end
|
182
|
+
|
26
183
|
def screenshot(
|
27
184
|
path: nil,
|
28
185
|
type: nil,
|
@@ -41,7 +198,7 @@ module Playwright
|
|
41
198
|
timeout: timeout,
|
42
199
|
}.compact
|
43
200
|
encoded_binary = @channel.send_message_to_server('screenshot', params)
|
44
|
-
decoded_binary = Base64.
|
201
|
+
decoded_binary = Base64.strict_decode64(encoded_binary)
|
45
202
|
if path
|
46
203
|
File.open(path, 'wb') do |f|
|
47
204
|
f.write(decoded_binary)
|
@@ -49,5 +206,196 @@ module Playwright
|
|
49
206
|
end
|
50
207
|
decoded_binary
|
51
208
|
end
|
209
|
+
|
210
|
+
def title
|
211
|
+
@main_frame.title
|
212
|
+
end
|
213
|
+
|
214
|
+
def close(runBeforeUnload: nil)
|
215
|
+
options = { runBeforeUnload: runBeforeUnload }.compact
|
216
|
+
@channel.send_message_to_server('close', options)
|
217
|
+
@owned_context&.close
|
218
|
+
nil
|
219
|
+
rescue => err
|
220
|
+
raise unless safe_close_error?(err)
|
221
|
+
end
|
222
|
+
|
223
|
+
def closed?
|
224
|
+
@closed
|
225
|
+
end
|
226
|
+
|
227
|
+
def click(
|
228
|
+
selector,
|
229
|
+
button: nil,
|
230
|
+
clickCount: nil,
|
231
|
+
delay: nil,
|
232
|
+
force: nil,
|
233
|
+
modifiers: nil,
|
234
|
+
noWaitAfter: nil,
|
235
|
+
position: nil,
|
236
|
+
timeout: nil)
|
237
|
+
|
238
|
+
@main_frame.click(
|
239
|
+
selector,
|
240
|
+
button: button,
|
241
|
+
clickCount: clickCount,
|
242
|
+
delay: delay,
|
243
|
+
force: force,
|
244
|
+
modifiers: modifiers,
|
245
|
+
noWaitAfter: noWaitAfter,
|
246
|
+
position: position,
|
247
|
+
timeout: timeout,
|
248
|
+
)
|
249
|
+
end
|
250
|
+
|
251
|
+
def dblclick(
|
252
|
+
selector,
|
253
|
+
button: nil,
|
254
|
+
delay: nil,
|
255
|
+
force: nil,
|
256
|
+
modifiers: nil,
|
257
|
+
noWaitAfter: nil,
|
258
|
+
position: nil,
|
259
|
+
timeout: nil)
|
260
|
+
@main_frame.dblclick(
|
261
|
+
selector,
|
262
|
+
button: button,
|
263
|
+
delay: delay,
|
264
|
+
force: force,
|
265
|
+
modifiers: modifiers,
|
266
|
+
noWaitAfter: noWaitAfter,
|
267
|
+
position: position,
|
268
|
+
timeout: timeout,
|
269
|
+
)
|
270
|
+
end
|
271
|
+
|
272
|
+
def fill(selector, value, noWaitAfter: nil, timeout: nil)
|
273
|
+
@main_frame.fill(selector, value, noWaitAfter: noWaitAfter, timeout: timeout)
|
274
|
+
end
|
275
|
+
|
276
|
+
def focus(selector, timeout: nil)
|
277
|
+
@main_frame.focus(selector, timeout: timeout)
|
278
|
+
end
|
279
|
+
|
280
|
+
def type(
|
281
|
+
selector,
|
282
|
+
text,
|
283
|
+
delay: nil,
|
284
|
+
noWaitAfter: nil,
|
285
|
+
timeout: nil)
|
286
|
+
|
287
|
+
@main_frame.type(selector, text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
|
288
|
+
end
|
289
|
+
|
290
|
+
def press(
|
291
|
+
selector,
|
292
|
+
key,
|
293
|
+
delay: nil,
|
294
|
+
noWaitAfter: nil,
|
295
|
+
timeout: nil)
|
296
|
+
|
297
|
+
@main_frame.press(selector, key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
|
298
|
+
end
|
299
|
+
|
300
|
+
def wait_for_function(pageFunction, arg: nil, polling: nil, timeout: nil)
|
301
|
+
@main_frame.wait_for_function(pageFunction, arg: arg, polling: polling, timeout: timeout)
|
302
|
+
end
|
303
|
+
|
304
|
+
class CrashedError < StandardError
|
305
|
+
def initialize
|
306
|
+
super('Page crashed')
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
class AlreadyClosedError < StandardError
|
311
|
+
def initialize
|
312
|
+
super('Page closed')
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
class FrameAlreadyDetachedError < StandardError
|
317
|
+
def initialize
|
318
|
+
super('Navigating frame was detached!')
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def expect_event(event, optionsOrPredicate: nil, &block)
|
323
|
+
predicate, timeout =
|
324
|
+
case optionsOrPredicate
|
325
|
+
when Proc
|
326
|
+
[optionsOrPredicate, nil]
|
327
|
+
when Hash
|
328
|
+
[optionsOrPredicate[:predicate], optionsOrPredicate[:timeout]]
|
329
|
+
else
|
330
|
+
[nil, nil]
|
331
|
+
end
|
332
|
+
timeout ||= @timeout_settings.timeout
|
333
|
+
|
334
|
+
wait_helper = WaitHelper.new
|
335
|
+
wait_helper.reject_on_timeout(timeout, "Timeout while waiting for event \"#{event}\"")
|
336
|
+
|
337
|
+
unless event == Events::Page::Crash
|
338
|
+
wait_helper.reject_on_event(self, Events::Page::Crash, CrashedError.new)
|
339
|
+
end
|
340
|
+
|
341
|
+
unless event == Events::Page::Close
|
342
|
+
wait_helper.reject_on_event(self, Events::Page::Close, AlreadyClosedError.new)
|
343
|
+
end
|
344
|
+
|
345
|
+
wait_helper.wait_for_event(self, event, predicate: predicate)
|
346
|
+
|
347
|
+
block&.call
|
348
|
+
|
349
|
+
wait_helper.promise.value!
|
350
|
+
end
|
351
|
+
|
352
|
+
def expect_navigation(timeout: nil, url: nil, waitUntil: nil, &block)
|
353
|
+
@main_frame.expect_navigation(
|
354
|
+
timeout: timeout,
|
355
|
+
url: url,
|
356
|
+
waitUntil: waitUntil,
|
357
|
+
&block)
|
358
|
+
end
|
359
|
+
|
360
|
+
def expect_request(urlOrPredicate, timeout: nil)
|
361
|
+
predicate =
|
362
|
+
case urlOrPredicate
|
363
|
+
when String, Regexp
|
364
|
+
url_matcher = UrlMatcher.new(urlOrPredicate)
|
365
|
+
-> (req){ url_matcher.match?(req.url) }
|
366
|
+
when Proc
|
367
|
+
urlOrPredicate
|
368
|
+
else
|
369
|
+
-> (_) { true }
|
370
|
+
end
|
371
|
+
|
372
|
+
expect_event(Events::Page::Request, optionsOrPredicate: { predicate: predicate, timeout: timeout})
|
373
|
+
end
|
374
|
+
|
375
|
+
def expect_response(urlOrPredicate, timeout: nil)
|
376
|
+
predicate =
|
377
|
+
case urlOrPredicate
|
378
|
+
when String, Regexp
|
379
|
+
url_matcher = UrlMatcher.new(urlOrPredicate)
|
380
|
+
-> (req){ url_matcher.match?(req.url) }
|
381
|
+
when Proc
|
382
|
+
urlOrPredicate
|
383
|
+
else
|
384
|
+
-> (_) { true }
|
385
|
+
end
|
386
|
+
|
387
|
+
expect_event(Events::Page::Response, optionsOrPredicate: { predicate: predicate, timeout: timeout})
|
388
|
+
end
|
389
|
+
|
390
|
+
# called from BrowserContext#on_page with send(:update_browser_context, page), so keep private.
|
391
|
+
private def update_browser_context(context)
|
392
|
+
@browser_context = context
|
393
|
+
@timeout_settings = TimeoutSettings.new(context.send(:_timeout_settings))
|
394
|
+
end
|
395
|
+
|
396
|
+
# called from Frame with send(:timeout_settings)
|
397
|
+
private def timeout_settings
|
398
|
+
@timeout_settings
|
399
|
+
end
|
52
400
|
end
|
53
401
|
end
|
@@ -1,5 +1,95 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
1
3
|
module Playwright
|
2
4
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_network.py
|
3
5
|
define_channel_owner :Request do
|
6
|
+
def after_initialize
|
7
|
+
@redirected_from = ChannelOwners::Request.from_nullable(@initializer['redirectedFrom'])
|
8
|
+
@redirected_from&.send(:update_redirected_to, self)
|
9
|
+
@timing = {
|
10
|
+
startTime: 0,
|
11
|
+
domainLookupStart: -1,
|
12
|
+
domainLookupEnd: -1,
|
13
|
+
connectStart: -1,
|
14
|
+
secureConnectionStart: -1,
|
15
|
+
connectEnd: -1,
|
16
|
+
requestStart: -1,
|
17
|
+
responseStart: -1,
|
18
|
+
responseEnd: -1,
|
19
|
+
}
|
20
|
+
@headers = parse_headers(@initializer['headers'])
|
21
|
+
end
|
22
|
+
|
23
|
+
def url
|
24
|
+
@initializer['url']
|
25
|
+
end
|
26
|
+
|
27
|
+
def resource_type
|
28
|
+
@initializer['resourceType']
|
29
|
+
end
|
30
|
+
|
31
|
+
def method
|
32
|
+
@initialize['method']
|
33
|
+
end
|
34
|
+
|
35
|
+
def post_data
|
36
|
+
post_data_buffer
|
37
|
+
end
|
38
|
+
|
39
|
+
def post_data_json
|
40
|
+
data = post_data
|
41
|
+
return unless data
|
42
|
+
|
43
|
+
content_type = @headers['content-type']
|
44
|
+
return unless content_type
|
45
|
+
|
46
|
+
if content_type == "application/x-www-form-urlencoded"
|
47
|
+
URI.decode_www_form(data).to_h
|
48
|
+
else
|
49
|
+
JSON.parse(data)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def post_data_buffer
|
54
|
+
base64_content = @initializer['postData']
|
55
|
+
if base64_content
|
56
|
+
Base64.strict_decode64(base64_content)
|
57
|
+
else
|
58
|
+
nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def headers
|
63
|
+
@headers
|
64
|
+
end
|
65
|
+
|
66
|
+
def response
|
67
|
+
resp = @channel.send_message_to_server('response')
|
68
|
+
ChannelOwners::Response.from_nullable(resp)
|
69
|
+
end
|
70
|
+
|
71
|
+
def frame
|
72
|
+
@initializer['frame']
|
73
|
+
end
|
74
|
+
|
75
|
+
def navigation_request?
|
76
|
+
@initializer['isNavigationRequest']
|
77
|
+
end
|
78
|
+
|
79
|
+
def failure
|
80
|
+
@failure_text
|
81
|
+
end
|
82
|
+
|
83
|
+
attr_reader :headers, :redirected_from, :redirected_to, :timing
|
84
|
+
|
85
|
+
private def update_redirected_to(request)
|
86
|
+
@redirected_to = request
|
87
|
+
end
|
88
|
+
|
89
|
+
private def parse_headers(headers)
|
90
|
+
headers.map do |header|
|
91
|
+
[header['name'].downcase, header['value']]
|
92
|
+
end.to_h
|
93
|
+
end
|
4
94
|
end
|
5
95
|
end
|