playwright-ruby-client 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +7 -5
- data/lib/playwright.rb +4 -0
- data/lib/playwright/channel_owner.rb +13 -0
- data/lib/playwright/channel_owners/browser.rb +7 -14
- data/lib/playwright/channel_owners/browser_context.rb +43 -0
- data/lib/playwright/channel_owners/console_message.rb +0 -4
- data/lib/playwright/channel_owners/frame.rb +121 -7
- data/lib/playwright/channel_owners/page.rb +218 -0
- data/lib/playwright/connection.rb +6 -8
- data/lib/playwright/event_emitter.rb +13 -0
- data/lib/playwright/javascript.rb +13 -0
- data/lib/playwright/javascript/expression.rb +30 -0
- data/lib/playwright/javascript/function.rb +30 -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 +8 -4
- data/lib/playwright/timeout_settings.rb +19 -0
- data/lib/playwright/utils.rb +19 -0
- data/lib/playwright/version.rb +1 -1
- data/lib/playwright/wait_helper.rb +73 -0
- data/lib/playwright_api/binding_call.rb +18 -0
- data/lib/playwright_api/browser.rb +18 -0
- data/lib/playwright_api/browser_context.rb +27 -4
- data/lib/playwright_api/browser_type.rb +18 -0
- data/lib/playwright_api/chromium_browser_context.rb +18 -0
- data/lib/playwright_api/console_message.rb +18 -0
- data/lib/playwright_api/element_handle.rb +19 -0
- data/lib/playwright_api/file_chooser.rb +1 -0
- data/lib/playwright_api/frame.rb +36 -12
- data/lib/playwright_api/js_handle.rb +18 -0
- data/lib/playwright_api/page.rb +40 -21
- data/lib/playwright_api/playwright.rb +18 -0
- data/lib/playwright_api/request.rb +18 -0
- data/lib/playwright_api/response.rb +18 -0
- data/lib/playwright_api/selectors.rb +18 -0
- data/playwright.gemspec +2 -0
- metadata +38 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c54a8690be4b1b2e33cecb6cda92071cd1d6867647fe939b004bf0434c31c74e
|
4
|
+
data.tar.gz: 1c2c784a5970c7a89bffc6bdb12cf7c8e1353a676881a99862bb9bbe30dd3dea
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9ca66a5edc3d168e16b552f3c84e4b4a939a7e8610da439fdea8350a87fed0656a9b5c715e4ac384d23b1d089ab23fa61ccd06288b1f11045aa83a3351a4f94
|
7
|
+
data.tar.gz: cad563aa4e2f81a026f08a04a7fd3caf1295f6419b01f1601d324583243dd839bb4b7f3aec73967555c4dbb6b8ffb8b65e7607836ec2c11231512c6e45fbf526
|
data/README.md
CHANGED
@@ -8,14 +8,14 @@ Note: Currently, this Gem is just a PoC (Proof of Concept). If you want to devel
|
|
8
8
|
|
9
9
|
## Getting Started
|
10
10
|
|
11
|
-
At this point, playwright-ruby-client doesn't include the downloader of playwright
|
11
|
+
At this point, playwright-ruby-client doesn't include the downloader of playwright driver, so **we have to install [playwright CLI](https://github.com/microsoft/playwright-cli) in advance**.
|
12
12
|
|
13
13
|
```sh
|
14
|
-
npm install playwright
|
15
|
-
./node_modules/.bin/playwright
|
14
|
+
npm install playwright
|
15
|
+
./node_modules/.bin/playwright install
|
16
16
|
```
|
17
17
|
|
18
|
-
and then, set `playwright_cli_executable_path: ./node_modules/.bin/playwright
|
18
|
+
and then, set `playwright_cli_executable_path: ./node_modules/.bin/playwright` at `Playwright.create`.
|
19
19
|
|
20
20
|
Instead of npm install, you can also directly download playwright driver from playwright.azureedge.net/builds/. The URL can be easily detected from [here](https://github.com/microsoft/playwright-python/blob/79f6ce0a6a69c480573372706df84af5ef99c4a4/setup.py#L56-L61)
|
21
21
|
|
@@ -24,7 +24,7 @@ Instead of npm install, you can also directly download playwright driver from pl
|
|
24
24
|
```ruby
|
25
25
|
require 'playwright'
|
26
26
|
|
27
|
-
Playwright.create(playwright_cli_executable_path: '/path/to/playwright
|
27
|
+
Playwright.create(playwright_cli_executable_path: '/path/to/playwright') do |playwright|
|
28
28
|
playwright.chromium.launch(headless: false) do |browser|
|
29
29
|
page = browser.new_page
|
30
30
|
page.goto('https://github.com/YusukeIwaki')
|
@@ -33,6 +33,8 @@ Playwright.create(playwright_cli_executable_path: '/path/to/playwright-cli') do
|
|
33
33
|
end
|
34
34
|
```
|
35
35
|
|
36
|
+

|
37
|
+
|
36
38
|
## License
|
37
39
|
|
38
40
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/lib/playwright.rb
CHANGED
@@ -10,12 +10,16 @@ require 'concurrent'
|
|
10
10
|
require 'playwright/errors'
|
11
11
|
require 'playwright/events'
|
12
12
|
require 'playwright/event_emitter'
|
13
|
+
require 'playwright/javascript'
|
14
|
+
require 'playwright/utils'
|
13
15
|
|
14
16
|
require 'playwright/channel'
|
15
17
|
require 'playwright/channel_owner'
|
16
18
|
require 'playwright/connection'
|
19
|
+
require 'playwright/timeout_settings'
|
17
20
|
require 'playwright/transport'
|
18
21
|
require 'playwright/version'
|
22
|
+
require 'playwright/wait_helper'
|
19
23
|
|
20
24
|
require 'playwright/playwright_api'
|
21
25
|
# load generated files
|
@@ -6,6 +6,10 @@ module Playwright
|
|
6
6
|
channel.object
|
7
7
|
end
|
8
8
|
|
9
|
+
def self.from_nullable(channel)
|
10
|
+
channel&.object
|
11
|
+
end
|
12
|
+
|
9
13
|
# @param parent [Playwright::ChannelOwner|Playwright::Connection]
|
10
14
|
# @param type [String]
|
11
15
|
# @param guid [String]
|
@@ -45,6 +49,15 @@ module Playwright
|
|
45
49
|
@objects.clear
|
46
50
|
end
|
47
51
|
|
52
|
+
# Suppress long long inspect log and avoid RSpec from hanging up...
|
53
|
+
def inspect
|
54
|
+
to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"#<#{@guid}>"
|
59
|
+
end
|
60
|
+
|
48
61
|
private
|
49
62
|
|
50
63
|
def after_initialize
|
@@ -1,9 +1,11 @@
|
|
1
1
|
module Playwright
|
2
2
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser.py
|
3
3
|
define_channel_owner :Browser do
|
4
|
+
include Utils::Errors::SafeCloseError
|
5
|
+
|
4
6
|
def after_initialize
|
5
7
|
@contexts = Set.new
|
6
|
-
@channel.on('close', method(:
|
8
|
+
@channel.on('close', method(:on_close))
|
7
9
|
end
|
8
10
|
|
9
11
|
def contexts
|
@@ -57,24 +59,15 @@ module Playwright
|
|
57
59
|
@initializer['version']
|
58
60
|
end
|
59
61
|
|
60
|
-
private
|
61
|
-
|
62
|
-
def handle_close(_ = {})
|
62
|
+
private def on_close(_ = {})
|
63
63
|
@connected = false
|
64
64
|
emit(Events::Browser::Disconnected)
|
65
65
|
@closed_or_closing = false
|
66
66
|
end
|
67
67
|
|
68
|
-
#
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
[
|
73
|
-
'Browser has been closed',
|
74
|
-
'Target page, context or browser has been closed',
|
75
|
-
].any? do |closed_message|
|
76
|
-
err.message.end_with?(closed_message)
|
77
|
-
end
|
68
|
+
# called from BrowserContext#on_close with send(:remove_context), so keep private.
|
69
|
+
private def remove_context(context)
|
70
|
+
@contexts.delete(context)
|
78
71
|
end
|
79
72
|
end
|
80
73
|
end
|
@@ -1,13 +1,56 @@
|
|
1
1
|
module Playwright
|
2
2
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_browser_context.py
|
3
3
|
define_channel_owner :BrowserContext do
|
4
|
+
include Utils::Errors::SafeCloseError
|
4
5
|
attr_writer :browser, :owner_page, :options
|
5
6
|
|
7
|
+
def after_initialize
|
8
|
+
@pages = Set.new
|
9
|
+
|
10
|
+
@channel.once('close', ->(_) { on_close })
|
11
|
+
@channel.on('page', ->(hash) { on_page(ChannelOwners::Page.from(hash['page']) )})
|
12
|
+
end
|
13
|
+
|
14
|
+
private def on_page(page)
|
15
|
+
page.send(:update_browser_context, self)
|
16
|
+
@pages << page
|
17
|
+
emit(Events::BrowserContext::Page, page)
|
18
|
+
end
|
19
|
+
|
20
|
+
def pages
|
21
|
+
@pages.to_a
|
22
|
+
end
|
23
|
+
|
6
24
|
# @returns [Playwright::Page]
|
7
25
|
def new_page
|
8
26
|
raise 'Please use browser.new_context' if @owner_page
|
9
27
|
resp = @channel.send_message_to_server('newPage')
|
10
28
|
ChannelOwners::Page.from(resp)
|
11
29
|
end
|
30
|
+
|
31
|
+
private def on_close
|
32
|
+
@closed_or_closing = true
|
33
|
+
@browser&.send(:remove_context, self)
|
34
|
+
emit(Events::BrowserContext::Close)
|
35
|
+
end
|
36
|
+
|
37
|
+
def close
|
38
|
+
return if @closed_or_closing
|
39
|
+
@closed_or_closing = true
|
40
|
+
@channel.send_message_to_server('close')
|
41
|
+
nil
|
42
|
+
rescue => err
|
43
|
+
raise unless safe_close_error?(err)
|
44
|
+
end
|
45
|
+
|
46
|
+
# called from Page#on_close with send(:remove_page, page), so keep private
|
47
|
+
private def remove_page(page)
|
48
|
+
@pages.delete(page)
|
49
|
+
end
|
50
|
+
|
51
|
+
# called from Page with send(:_timeout_settings), so keep private.
|
52
|
+
private def _timeout_settings
|
53
|
+
@timeout_settings
|
54
|
+
end
|
12
55
|
end
|
13
56
|
end
|
@@ -2,9 +2,8 @@ module Playwright
|
|
2
2
|
# @ref https://github.com/microsoft/playwright-python/blob/master/playwright/_impl/_frame.py
|
3
3
|
define_channel_owner :Frame do
|
4
4
|
def after_initialize
|
5
|
-
@event_emitter = Object.new.extend(EventEmitter)
|
6
5
|
if @initializer['parentFrame']
|
7
|
-
@parent_frame =
|
6
|
+
@parent_frame = ChannelOwners::Frame.from(@initializer['parentFrame'])
|
8
7
|
@parent_frame.send(:append_child_frame_from_child, self)
|
9
8
|
end
|
10
9
|
@name = @initializer['name']
|
@@ -12,9 +11,36 @@ module Playwright
|
|
12
11
|
@detached = false
|
13
12
|
@child_frames = Set.new
|
14
13
|
@load_states = Set.new(@initializer['loadStates'])
|
14
|
+
@event_emitter = Object.new.extend(EventEmitter)
|
15
|
+
|
16
|
+
@channel.on('loadstate', ->(params) {
|
17
|
+
on_load_state(add: params['add'], remove: params['remove'])
|
18
|
+
})
|
19
|
+
@channel.on('navigated', method(:on_frame_navigated))
|
15
20
|
end
|
16
21
|
|
17
|
-
attr_reader :page
|
22
|
+
attr_reader :page, :parent_frame
|
23
|
+
attr_writer :detached
|
24
|
+
|
25
|
+
private def on_load_state(add:, remove:)
|
26
|
+
if add
|
27
|
+
@load_states << add
|
28
|
+
@event_emitter.emit('loadstate', add)
|
29
|
+
end
|
30
|
+
if remove
|
31
|
+
@load_states.delete(remove)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private def on_frame_navigated(event)
|
36
|
+
@url = event['url']
|
37
|
+
@name = event['name']
|
38
|
+
@event_emitter.emit('navigated', event)
|
39
|
+
|
40
|
+
unless event['error']
|
41
|
+
@page&.emit('framenavigated', self)
|
42
|
+
end
|
43
|
+
end
|
18
44
|
|
19
45
|
def goto(url, timeout: nil, waitUntil: nil, referer: nil)
|
20
46
|
params = {
|
@@ -24,20 +50,108 @@ module Playwright
|
|
24
50
|
referer: referer
|
25
51
|
}.compact
|
26
52
|
resp = @channel.send_message_to_server('goto', params)
|
27
|
-
ChannelOwners::Response.
|
53
|
+
ChannelOwners::Response.from_nullable(resp)
|
54
|
+
end
|
55
|
+
|
56
|
+
def evaluate(pageFunction, arg: nil)
|
57
|
+
if JavaScript.function?(pageFunction)
|
58
|
+
JavaScript::Function.new(pageFunction, arg).evaluate(@channel)
|
59
|
+
else
|
60
|
+
JavaScript::Expression.new(pageFunction).evaluate(@channel)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def evaluate_handle(pageFunction, arg: nil)
|
65
|
+
if JavaScript.function?(pageFunction)
|
66
|
+
JavaScript::Function.new(pageFunction, arg).evaluate_handle(@channel)
|
67
|
+
else
|
68
|
+
JavaScript::Expression.new(pageFunction).evaluate_handle(@channel)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def content
|
73
|
+
@channel.send_message_to_server('content')
|
74
|
+
end
|
75
|
+
|
76
|
+
def set_content(html, timeout: nil, waitUntil: nil)
|
77
|
+
params = {
|
78
|
+
html: html,
|
79
|
+
timeout: timeout,
|
80
|
+
waitUntil: waitUntil,
|
81
|
+
}.compact
|
82
|
+
|
83
|
+
@channel.send_message_to_server('setContent', params)
|
84
|
+
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def focus(selector, timeout: nil)
|
89
|
+
params = { selector: selector, timeout: timeout }.compact
|
90
|
+
@channel.send_message_to_server('focus', params)
|
91
|
+
nil
|
28
92
|
end
|
29
93
|
|
30
|
-
|
94
|
+
def type_text(
|
95
|
+
selector,
|
96
|
+
text,
|
97
|
+
delay: nil,
|
98
|
+
noWaitAfter: nil,
|
99
|
+
timeout: nil)
|
100
|
+
|
101
|
+
params = {
|
102
|
+
selector: selector,
|
103
|
+
text: text,
|
104
|
+
delay: delay,
|
105
|
+
noWaitAfter: noWaitAfter,
|
106
|
+
timeout: timeout,
|
107
|
+
}.compact
|
108
|
+
|
109
|
+
@channel.send_message_to_server('type', params)
|
110
|
+
end
|
111
|
+
|
112
|
+
def press(
|
113
|
+
selector,
|
114
|
+
key,
|
115
|
+
delay: nil,
|
116
|
+
noWaitAfter: nil,
|
117
|
+
timeout: nil)
|
118
|
+
|
119
|
+
params = {
|
120
|
+
selector: selector,
|
121
|
+
key: key,
|
122
|
+
delay: delay,
|
123
|
+
noWaitAfter: noWaitAfter,
|
124
|
+
timeout: timeout,
|
125
|
+
}.compact
|
126
|
+
|
127
|
+
@channel.send_message_to_server('press', params)
|
128
|
+
end
|
129
|
+
|
130
|
+
def name
|
131
|
+
@name || ''
|
132
|
+
end
|
133
|
+
|
134
|
+
def url
|
135
|
+
@url || ''
|
136
|
+
end
|
137
|
+
|
138
|
+
def child_frames
|
139
|
+
@child_frames.to_a
|
140
|
+
end
|
141
|
+
|
142
|
+
def title
|
143
|
+
@channel.send_message_to_server('title')
|
144
|
+
end
|
31
145
|
|
32
146
|
# @param page [Page]
|
33
147
|
# @note This method should be used internally. Accessed via .send method, so keep private!
|
34
|
-
def update_page_from_page(page)
|
148
|
+
private def update_page_from_page(page)
|
35
149
|
@page = page
|
36
150
|
end
|
37
151
|
|
38
152
|
# @param child [Frame]
|
39
153
|
# @note This method should be used internally. Accessed via .send method, so keep private!
|
40
|
-
def append_child_frame_from_child(frame)
|
154
|
+
private def append_child_frame_from_child(frame)
|
41
155
|
@child_frames << frame
|
42
156
|
end
|
43
157
|
end
|
@@ -3,19 +3,40 @@ 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
13
|
@keyboard = Keyboard.new(@channel)
|
11
14
|
@mouse = Mouse.new(@channel)
|
12
15
|
@touchscreen = Touchscreen.new(@channel)
|
13
16
|
|
14
17
|
@viewport_size = @initializer['viewportSize']
|
18
|
+
@closed = false
|
15
19
|
@main_frame = ChannelOwners::Frame.from(@initializer['mainFrame'])
|
16
20
|
@main_frame.send(:update_page_from_page, self)
|
17
21
|
@frames = Set.new
|
18
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
|
+
})
|
19
40
|
end
|
20
41
|
|
21
42
|
attr_reader \
|
@@ -26,6 +47,82 @@ module Playwright
|
|
26
47
|
:viewport_size,
|
27
48
|
:main_frame
|
28
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 evaluate(pageFunction, arg: nil)
|
107
|
+
@main_frame.evaluate(pageFunction, arg: arg)
|
108
|
+
end
|
109
|
+
|
110
|
+
def evaluate_handle(pageFunction, arg: nil)
|
111
|
+
@main_frame.evaluate_handle(pageFunction, arg: arg)
|
112
|
+
end
|
113
|
+
|
114
|
+
def url
|
115
|
+
@main_frame.url
|
116
|
+
end
|
117
|
+
|
118
|
+
def content
|
119
|
+
@main_frame.content
|
120
|
+
end
|
121
|
+
|
122
|
+
def set_content(html, timeout: nil, waitUntil: nil)
|
123
|
+
@main_frame.set_content(html, timeout: timeout, waitUntil: waitUntil)
|
124
|
+
end
|
125
|
+
|
29
126
|
def goto(url, timeout: nil, waitUntil: nil, referer: nil)
|
30
127
|
@main_frame.goto(url, timeout: timeout, waitUntil: waitUntil, referer: referer)
|
31
128
|
end
|
@@ -62,5 +159,126 @@ module Playwright
|
|
62
159
|
end
|
63
160
|
decoded_binary
|
64
161
|
end
|
162
|
+
|
163
|
+
def title
|
164
|
+
@main_frame.title
|
165
|
+
end
|
166
|
+
|
167
|
+
def close(runBeforeUnload: nil)
|
168
|
+
options = { runBeforeUnload: runBeforeUnload }.compact
|
169
|
+
@channel.send_message_to_server('close', options)
|
170
|
+
@owned_context&.close
|
171
|
+
nil
|
172
|
+
rescue => err
|
173
|
+
raise unless safe_close_error?(err)
|
174
|
+
end
|
175
|
+
|
176
|
+
def closed?
|
177
|
+
@closed
|
178
|
+
end
|
179
|
+
|
180
|
+
def focus(selector, timeout: nil)
|
181
|
+
@main_frame.focus(selector, timeout: timeout)
|
182
|
+
end
|
183
|
+
|
184
|
+
def type_text(
|
185
|
+
selector,
|
186
|
+
text,
|
187
|
+
delay: nil,
|
188
|
+
noWaitAfter: nil,
|
189
|
+
timeout: nil)
|
190
|
+
|
191
|
+
@main_frame.type_text(selector, text, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
|
192
|
+
end
|
193
|
+
|
194
|
+
def press(
|
195
|
+
selector,
|
196
|
+
key,
|
197
|
+
delay: nil,
|
198
|
+
noWaitAfter: nil,
|
199
|
+
timeout: nil)
|
200
|
+
|
201
|
+
@main_frame.press(selector, key, delay: delay, noWaitAfter: noWaitAfter, timeout: timeout)
|
202
|
+
end
|
203
|
+
|
204
|
+
class CrashedError < StandardError
|
205
|
+
def initialize
|
206
|
+
super('Page crashed')
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
class AlreadyClosedError < StandardError
|
211
|
+
def initialize
|
212
|
+
super('Page closed')
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def wait_for_event(event, optionsOrPredicate: nil, &block)
|
217
|
+
predicate, timeout =
|
218
|
+
case optionsOrPredicate
|
219
|
+
when Proc
|
220
|
+
[optionsOrPredicate, nil]
|
221
|
+
when Hash
|
222
|
+
[optionsOrPredicate[:predicate], optionsOrPredicate[:timeout]]
|
223
|
+
else
|
224
|
+
[nil, nil]
|
225
|
+
end
|
226
|
+
timeout ||= @timeout_settings.timeout
|
227
|
+
|
228
|
+
wait_helper = WaitHelper.new
|
229
|
+
wait_helper.reject_on_timeout(timeout, "Timeout while waiting for event \"#{event}\"")
|
230
|
+
|
231
|
+
unless event == Events::Page::Crash
|
232
|
+
wait_helper.reject_on_event(self, Events::Page::Crash, CrashedError.new)
|
233
|
+
end
|
234
|
+
|
235
|
+
unless event == Events::Page::Close
|
236
|
+
wait_helper.reject_on_event(self, Events::Page::Close, AlreadyClosedError.new)
|
237
|
+
end
|
238
|
+
|
239
|
+
wait_helper.wait_for_event(self, event, predicate: predicate)
|
240
|
+
|
241
|
+
block&.call
|
242
|
+
|
243
|
+
wait_helper.promise.value!
|
244
|
+
end
|
245
|
+
|
246
|
+
def wait_for_request(urlOrPredicate, timeout: nil)
|
247
|
+
predicate =
|
248
|
+
case urlOrPredicate
|
249
|
+
when String
|
250
|
+
-> (req){ req.url == urlOrPredicate }
|
251
|
+
when Regexp
|
252
|
+
-> (req){ urlOrPredicate.match?(req.url) }
|
253
|
+
when Proc
|
254
|
+
urlOrPredicate
|
255
|
+
else
|
256
|
+
-> (_) { true }
|
257
|
+
end
|
258
|
+
|
259
|
+
wait_for_event(Events::Page::Request, optionsOrPredicate: { predicate: predicate, timeout: timeout})
|
260
|
+
end
|
261
|
+
|
262
|
+
def wait_for_response(urlOrPredicate, timeout: nil)
|
263
|
+
predicate =
|
264
|
+
case urlOrPredicate
|
265
|
+
when String
|
266
|
+
-> (res){ res.url == urlOrPredicate }
|
267
|
+
when Regexp
|
268
|
+
-> (res){ urlOrPredicate.match?(res.url) }
|
269
|
+
when Proc
|
270
|
+
urlOrPredicate
|
271
|
+
else
|
272
|
+
-> (_) { true }
|
273
|
+
end
|
274
|
+
|
275
|
+
wait_for_event(Events::Page::Response, optionsOrPredicate: { predicate: predicate, timeout: timeout})
|
276
|
+
end
|
277
|
+
|
278
|
+
# called from BrowserContext#on_page with send(:update_browser_context, page), so keep private.
|
279
|
+
private def update_browser_context(context)
|
280
|
+
@browser_context = context
|
281
|
+
@timeout_settings = TimeoutSettings.new(context.send(:_timeout_settings))
|
282
|
+
end
|
65
283
|
end
|
66
284
|
end
|