cuprite 0.6.0 → 0.7.1
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 +100 -67
- data/lib/capybara/cuprite/browser.rb +66 -224
- data/lib/capybara/cuprite/driver.rb +101 -48
- data/lib/capybara/cuprite/errors.rb +1 -64
- data/lib/capybara/cuprite/{browser/javascripts → javascripts}/index.js +26 -20
- data/lib/capybara/cuprite/node.rb +37 -31
- data/lib/capybara/cuprite/page.rb +166 -0
- data/lib/capybara/cuprite/version.rb +1 -1
- data/lib/capybara/cuprite.rb +8 -21
- metadata +8 -42
- data/lib/capybara/cuprite/browser/client.rb +0 -74
- data/lib/capybara/cuprite/browser/dom.rb +0 -50
- data/lib/capybara/cuprite/browser/frame.rb +0 -115
- data/lib/capybara/cuprite/browser/input.json +0 -1341
- data/lib/capybara/cuprite/browser/input.rb +0 -200
- data/lib/capybara/cuprite/browser/net.rb +0 -90
- data/lib/capybara/cuprite/browser/page.rb +0 -378
- data/lib/capybara/cuprite/browser/process.rb +0 -223
- data/lib/capybara/cuprite/browser/runtime.rb +0 -182
- data/lib/capybara/cuprite/browser/targets.rb +0 -129
- data/lib/capybara/cuprite/browser/web_socket.rb +0 -69
- data/lib/capybara/cuprite/network/error.rb +0 -25
- data/lib/capybara/cuprite/network/request.rb +0 -33
- data/lib/capybara/cuprite/network/response.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 61e6eae56b712430083dd1dc25ae7888016899b9504fcb2795525fe2df0d9b63
|
4
|
+
data.tar.gz: 26f55efb799bff8ffa704fd1955dc01b03c11db3f44806f3a1c8284d84237ae8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8eb4c7caeeaf86f24ebef9bf37edf6bf3e6ccf474633be8c69a1b4296abfcb5df040ede0c5feccecc930393312408800a928f3671aeb658a7d5beadb08a3c0a
|
7
|
+
data.tar.gz: 44387ad8fa9b9a87a236d2df3d754155ad4ed280348d65da2479b1a5a08e6be215ebf2ad652c1159188f08f6f231fbeeeddd2ce767d5bc9a53b1c0e7f39fbdf1
|
data/README.md
CHANGED
@@ -5,59 +5,97 @@
|
|
5
5
|
Cuprite is a pure Ruby driver (read as _no_ Java/Selenium/WebDriver/ChromeDriver
|
6
6
|
requirement) for [Capybara](https://github.com/teamcapybara/capybara). It allows
|
7
7
|
you to run your Capybara tests on a headless [Chrome](https://www.google.com/chrome/)
|
8
|
-
or [Chromium](https://www.chromium.org/)
|
8
|
+
or [Chromium](https://www.chromium.org/) by [CDP protocol](https://chromedevtools.github.io/devtools-protocol/).
|
9
|
+
Under the hood it uses [Ferrum](https://github.com/route/ferrum) which is
|
10
|
+
high-level API to the browser again by CDP protocol.
|
9
11
|
|
10
12
|
The emphasis was made on raw CDP protocol because Headless Chrome allows you to
|
11
|
-
do so many
|
12
|
-
|
13
|
+
do so many things that are barely supported by WebDriver because it should have
|
14
|
+
consistent design with other browsers. The design of the driver will be as
|
13
15
|
close to [Poltergeist](https://github.com/teampoltergeist/poltergeist) as
|
14
|
-
possible
|
16
|
+
possible though it's not a goal.
|
15
17
|
|
16
|
-
##
|
18
|
+
## Install ##
|
19
|
+
|
20
|
+
Add these lines to your `Gemfile` and run `bundle install`.
|
17
21
|
|
18
22
|
``` ruby
|
19
|
-
gem "cuprite"
|
23
|
+
gem "cuprite", group: :test
|
20
24
|
```
|
21
25
|
|
22
|
-
and run `bundle install`.
|
23
|
-
|
24
26
|
In your test setup add:
|
25
27
|
|
26
28
|
``` ruby
|
27
29
|
require "capybara/cuprite"
|
28
30
|
Capybara.javascript_driver = :cuprite
|
31
|
+
Capybara.register_driver(:cuprite) do |app|
|
32
|
+
Capybara::Cuprite::Driver.new(app, window_size: [1200, 800])
|
33
|
+
end
|
29
34
|
```
|
30
35
|
|
31
|
-
|
36
|
+
If you already had tests on Poltergeist then it should simply work, for Selenium
|
37
|
+
you better check your code for `.manage` calls because things are much easier
|
38
|
+
with Cuprite, see the documentation below.
|
32
39
|
|
33
|
-
|
34
|
-
install it this way because it will either be outdated or unofficial package.
|
35
|
-
Both are bad. Download it from official [source](https://www.chromium.org/getting-involved/download-chromium).
|
40
|
+
## Install Chrome ##
|
36
41
|
|
37
|
-
|
42
|
+
There's no official Chrome or Chromium package for Linux don't install it this
|
43
|
+
way because it either will be outdated or unofficial, both are bad. Download it
|
44
|
+
from official [source](https://www.chromium.org/getting-involved/download-chromium).
|
45
|
+
Chrome binary should be in the `PATH` or `BROWSER_PATH` or you can pass it as an
|
46
|
+
option
|
38
47
|
|
39
|
-
|
48
|
+
## Customization ##
|
40
49
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
* `page.driver.basic_authorize(user, password)`
|
49
|
-
* `element.send_keys(*keys)`
|
50
|
-
* `page.driver.set_proxy(ip, port, type, user, password)`
|
51
|
-
* window API
|
52
|
-
* cookie handling
|
50
|
+
You can customize options with the following code in your test setup:
|
51
|
+
|
52
|
+
``` ruby
|
53
|
+
Capybara.register_driver(:cuprite) do |app|
|
54
|
+
Capybara::Cuprite::Driver.new(app, options)
|
55
|
+
end
|
56
|
+
```
|
53
57
|
|
54
|
-
|
58
|
+
#### Running in Docker ####
|
55
59
|
|
56
|
-
|
57
|
-
accomplish this with `page.driver.click(x, y)`, where x and y are the screen
|
58
|
-
coordinates.
|
60
|
+
In docker as root you must pass the no-sandbox browser option:
|
59
61
|
|
60
|
-
|
62
|
+
```ruby
|
63
|
+
Capybara::Cuprite::Driver.new(app, browser_options: { 'no-sandbox': nil })
|
64
|
+
```
|
65
|
+
|
66
|
+
* options `Hash`
|
67
|
+
* `:browser_path` (String) - Path to chrome binary, you can also set ENV
|
68
|
+
variable as `BROWSER_PATH=some/path/chrome bundle exec rspec`.
|
69
|
+
* `:headless` (Boolean) - Set browser as headless or not, `true` by default.
|
70
|
+
* `:slowmo` (Integer | Float) - Set a delay to wait before sending command.
|
71
|
+
Usefull companion of headless option, so that you have time to see changes.
|
72
|
+
* `:logger` (Object responding to `puts`) - When present, debug output is
|
73
|
+
written to this object.
|
74
|
+
* `:timeout` (Numeric) - The number of seconds we'll wait for a response when
|
75
|
+
communicating with browser. Default is 5.
|
76
|
+
* `:js_errors` (Boolean) - When true, JavaScript errors get re-raised in Ruby.
|
77
|
+
* `:window_size` (Array) - The dimensions of the browser window in which to
|
78
|
+
test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
|
79
|
+
* `:browser_options` (Hash) - Additional command line options,
|
80
|
+
[see them all](https://peter.sh/experiments/chromium-command-line-switches/)
|
81
|
+
e.g. `{ "ignore-certificate-errors" => nil }`
|
82
|
+
* `:extensions` (Array) - An array of JS files to be preloaded into the browser
|
83
|
+
* `:port` (Integer) - Remote debugging port for headless Chrome
|
84
|
+
* `:host` (String) - Remote debugging address for headless Chrome
|
85
|
+
* `:url` (String) - URL for a running instance of Chrome. If this is set, a
|
86
|
+
browser process will not be spawned.
|
87
|
+
* `:url_blacklist` (Array) - array of strings to match against requested URLs
|
88
|
+
* `:url_whitelist` (Array) - array of strings to match against requested URLs
|
89
|
+
* `:process_timeout` (Integer) - How long to wait for the Chrome process to
|
90
|
+
respond on startup
|
91
|
+
|
92
|
+
### Clicking/Scrolling ###
|
93
|
+
|
94
|
+
* `page.driver.click(x, y)` Click a very specific area of the screen.
|
95
|
+
* `page.driver.scroll_to(left, top)` Scroll to given position.
|
96
|
+
* `element.send_keys(*keys)` Send keys to given node.
|
97
|
+
|
98
|
+
### Request headers ###
|
61
99
|
|
62
100
|
Manipulate HTTP request headers like a boss:
|
63
101
|
|
@@ -73,12 +111,17 @@ Notice that `headers=` will overwrite already set headers. You should use
|
|
73
111
|
subsequent HTTP requests (including requests for assets, AJAX, etc). They will
|
74
112
|
be automatically cleared at the end of the test.
|
75
113
|
|
76
|
-
###
|
114
|
+
### Network traffic ###
|
115
|
+
|
116
|
+
* `page.driver.network_traffic` Inspect network traffic (resources have been
|
117
|
+
loaded) on the current page. This returns an array of request objects.
|
77
118
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
page.driver.network_traffic # => [Request, ...]
|
122
|
+
request = page.driver.network_traffic.first
|
123
|
+
request.response
|
124
|
+
```
|
82
125
|
|
83
126
|
Please note that network traffic is not cleared when you visit new page. You can
|
84
127
|
manually clear the network traffic by calling `page.driver.clear_network_traffic`
|
@@ -99,41 +142,16 @@ The following methods are used to inspect and manipulate cookies:
|
|
99
142
|
* `page.driver.remove_cookie(name)` - remove a cookie
|
100
143
|
* `page.driver.clear_cookies` - clear all cookies
|
101
144
|
|
102
|
-
|
145
|
+
### Screenshot ###
|
103
146
|
|
104
|
-
|
105
|
-
in your test setup:
|
147
|
+
Besides capybara screenshot method you can get image as Base64:
|
106
148
|
|
107
|
-
|
108
|
-
Capybara.register_driver :cuprite do |app|
|
109
|
-
Capybara::Cuprite::Driver.new(app, options)
|
110
|
-
end
|
111
|
-
```
|
149
|
+
* `page.driver.render_base64(format, options)`
|
112
150
|
|
113
|
-
|
114
|
-
|
115
|
-
* `:browser_path` (String) - Path to chrome binary, you can also set ENV
|
116
|
-
variable as `BROWSER_PATH=some/path/chrome bundle exec rspec`.
|
117
|
-
* `:headless` (Boolean) - Set browser as headless or not, `true` by default.
|
118
|
-
* `:slowmo` (Integer | Float) - Set a delay to wait before sending command.
|
119
|
-
Usefull companion of headless option, so that you have time to see changes.
|
120
|
-
* `:logger` (Object responding to `puts`) - When present, debug output is
|
121
|
-
written to this object.
|
122
|
-
* `:timeout` (Numeric) - The number of seconds we'll wait for a response when
|
123
|
-
communicating with browser. Default is 30.
|
124
|
-
* `:js_errors` (Boolean) - When true, JavaScript errors get re-raised in Ruby.
|
125
|
-
* `:window_size` (Array) - The dimensions of the browser window in which to
|
126
|
-
test, expressed as a 2-element array, e.g. [1024, 768]. Default: [1024, 768]
|
127
|
-
* `:browser_options` (Hash) - Additional command line options,
|
128
|
-
[see them all](https://peter.sh/experiments/chromium-command-line-switches/)
|
129
|
-
e.g. `{ "ignore-certificate-errors" => nil }`
|
130
|
-
* `:extensions` (Array) - An array of JS files to be preloaded into the browser
|
131
|
-
* `:port` (Integer) - Remote debugging port for headless Chrome
|
132
|
-
* `:host` (String) - Remote debugging address for headless Chrome
|
133
|
-
* `:url_blacklist` (Array) - array of strings to match against requested URLs
|
134
|
-
* `:url_whitelist` (Array) - array of strings to match against requested URLs
|
135
|
-
* `:process_timeout` (Integer) - How long to wait for the Chrome process to respond on startup
|
151
|
+
### Authorization ###
|
136
152
|
|
153
|
+
* `page.driver.basic_authorize(user, password)`
|
154
|
+
* `page.driver.set_proxy(ip, port, type, user, password)`
|
137
155
|
|
138
156
|
### URL Blacklisting & Whitelisting ###
|
139
157
|
Cuprite supports URL blacklisting, which allows you to prevent scripts from
|
@@ -154,6 +172,21 @@ If you are experiencing slower run times, consider creating a URL whitelist of
|
|
154
172
|
domains that are essential or a blacklist of domains that are not essential,
|
155
173
|
such as ad networks or analytics, to your testing environment.
|
156
174
|
|
175
|
+
### Remote debugging ###
|
176
|
+
|
177
|
+
If you use the `inspector: true` option, remote debugging will be enabled. When
|
178
|
+
this option is enabled, you can insert `page.driver.debug` into your tests to
|
179
|
+
pause the test and launch a browser which gives you the Chrome inspector to view
|
180
|
+
all your open pages and inspect them.
|
181
|
+
|
182
|
+
You could set the inspector option via an environment variable:
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
Capybara.register_driver :cuprite do |app|
|
186
|
+
Capybara::Cuprite::Driver.new(app, inspector: ENV['INSPECTOR'])
|
187
|
+
end
|
188
|
+
```
|
189
|
+
|
157
190
|
## License ##
|
158
191
|
|
159
192
|
Copyright 2018-2019 Machinio
|
@@ -1,301 +1,143 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "base64"
|
4
3
|
require "forwardable"
|
5
|
-
require "capybara/cuprite/browser/targets"
|
6
|
-
require "capybara/cuprite/browser/process"
|
7
|
-
require "capybara/cuprite/browser/client"
|
8
|
-
require "capybara/cuprite/browser/page"
|
9
4
|
|
10
5
|
module Capybara::Cuprite
|
11
|
-
class Browser
|
12
|
-
TIMEOUT = 5
|
13
|
-
WINDOW_SIZE = [1024, 768].freeze
|
14
|
-
EXTENSIONS = [
|
15
|
-
File.expand_path("browser/javascripts/index.js", __dir__)
|
16
|
-
].freeze
|
17
|
-
|
6
|
+
class Browser < Ferrum::Browser
|
18
7
|
extend Forwardable
|
19
8
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
9
|
+
delegate %i[find_or_create_page] => :targets
|
10
|
+
delegate %i[send_keys select set hover trigger before_click switch_to_frame
|
11
|
+
find_modal accept_confirm dismiss_confirm accept_prompt
|
12
|
+
dismiss_prompt reset_modals] => :page
|
25
13
|
|
26
|
-
|
27
|
-
delegate %i(window_handle window_handles switch_to_window open_new_window
|
28
|
-
close_window within_window page) => :targets
|
29
|
-
delegate %i(visit status_code body all_text property attributes attribute
|
30
|
-
value visible? disabled? network_traffic clear_network_traffic
|
31
|
-
path response_headers refresh click right_click double_click
|
32
|
-
hover set click_coordinates drag drag_by select trigger
|
33
|
-
scroll_to send_keys evaluate evaluate_on evaluate_async execute
|
34
|
-
frame_url frame_title switch_to_frame current_url title go_back
|
35
|
-
go_forward find_modal accept_confirm dismiss_confirm
|
36
|
-
accept_prompt dismiss_prompt reset_modals authorize
|
37
|
-
proxy_authorize) => :page
|
38
|
-
|
39
|
-
attr_reader :process, :logger, :js_errors, :slowmo,
|
40
|
-
:url_blacklist, :url_whitelist
|
41
|
-
attr_writer :timeout
|
14
|
+
attr_reader :url_blacklist, :url_whitelist
|
42
15
|
|
43
16
|
def initialize(options = nil)
|
44
|
-
# Doesn't work on MacOS, so we need to set it by CDP as well
|
45
17
|
options ||= {}
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
@options = Hash(options.merge(window_size: @window_size))
|
50
|
-
@logger, @timeout = @options.values_at(:logger, :timeout)
|
51
|
-
@js_errors = @options.fetch(:js_errors, false)
|
52
|
-
@slowmo = @options[:slowmo]
|
53
|
-
|
54
|
-
self.url_blacklist = @options[:url_blacklist]
|
55
|
-
self.url_whitelist = @options[:url_whitelist]
|
56
|
-
|
57
|
-
if ENV["CUPRITE_DEBUG"] && !@logger
|
58
|
-
STDOUT.sync = true
|
59
|
-
@logger = STDOUT
|
60
|
-
@options[:logger] = @logger
|
61
|
-
end
|
62
|
-
|
63
|
-
@options.freeze
|
18
|
+
self.url_blacklist = options[:url_blacklist]
|
19
|
+
self.url_whitelist = options[:url_whitelist]
|
64
20
|
|
65
|
-
|
21
|
+
super
|
66
22
|
end
|
67
23
|
|
68
|
-
def
|
69
|
-
@
|
70
|
-
|
71
|
-
(EXTENSIONS + exts).map { |p| File.read(p) }
|
72
|
-
end
|
24
|
+
def url_whitelist=(patterns)
|
25
|
+
@url_whitelist = prepare_wildcards(patterns)
|
26
|
+
page.network.intercept if @client && !@url_whitelist.empty?
|
73
27
|
end
|
74
28
|
|
75
|
-
def
|
76
|
-
@
|
29
|
+
def url_blacklist=(patterns)
|
30
|
+
@url_blacklist = prepare_wildcards(patterns)
|
31
|
+
page.network.intercept if @client && !@url_blacklist.empty?
|
77
32
|
end
|
78
33
|
|
79
|
-
def
|
80
|
-
|
34
|
+
def visit(*args)
|
35
|
+
goto(*args)
|
81
36
|
end
|
82
37
|
|
83
|
-
def
|
84
|
-
|
38
|
+
def status_code
|
39
|
+
network.status
|
85
40
|
end
|
86
41
|
|
87
42
|
def find(method, selector)
|
88
43
|
find_all(method, selector)
|
89
44
|
end
|
90
45
|
|
46
|
+
def property(node, name)
|
47
|
+
node.property(name)
|
48
|
+
end
|
49
|
+
|
91
50
|
def find_within(node, method, selector)
|
92
|
-
resolved = page.command("DOM.resolveNode", nodeId: node
|
51
|
+
resolved = page.command("DOM.resolveNode", nodeId: node.node_id)
|
93
52
|
object_id = resolved.dig("object", "objectId")
|
94
53
|
find_all(method, selector, { "objectId" => object_id })
|
95
54
|
end
|
96
55
|
|
97
|
-
def
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
def select_file(node, value)
|
106
|
-
page.command("DOM.setFileInputFiles", nodeId: node["nodeId"], files: Array(value))
|
107
|
-
end
|
108
|
-
|
109
|
-
def render(path, options = {})
|
110
|
-
format = options.delete(:format)
|
111
|
-
options = options.merge(path: path)
|
112
|
-
bin = Base64.decode64(render_base64(format, options))
|
113
|
-
File.open(path.to_s, "wb") { |f| f.write(bin) }
|
114
|
-
end
|
115
|
-
|
116
|
-
def render_base64(format, options = {})
|
117
|
-
options = render_options(format, options)
|
118
|
-
|
119
|
-
if options[:format].to_s == "pdf"
|
120
|
-
options = {}
|
121
|
-
options[:paperWidth] = @paper_size[:width].to_f if @paper_size
|
122
|
-
options[:paperHeight] = @paper_size[:height].to_f if @paper_size
|
123
|
-
options[:scale] = @zoom_factor if @zoom_factor
|
124
|
-
page.command("Page.printToPDF", **options)
|
125
|
-
else
|
126
|
-
page.command("Page.captureScreenshot", **options)
|
127
|
-
end.fetch("data")
|
128
|
-
end
|
129
|
-
|
130
|
-
def set_zoom_factor(zoom_factor)
|
131
|
-
@zoom_factor = zoom_factor.to_f
|
132
|
-
end
|
133
|
-
|
134
|
-
def set_paper_size(size)
|
135
|
-
@paper_size = size
|
136
|
-
end
|
137
|
-
|
138
|
-
def headers=(headers)
|
139
|
-
@headers = {}
|
140
|
-
add_headers(headers)
|
141
|
-
end
|
142
|
-
|
143
|
-
def add_headers(headers, permanent: true)
|
144
|
-
if headers["Referer"]
|
145
|
-
page.referrer = headers["Referer"]
|
146
|
-
headers.delete("Referer") unless permanent
|
56
|
+
def within_window(locator = nil, &block)
|
57
|
+
if Capybara::VERSION.to_f < 3.0
|
58
|
+
target_id = window_handles.find do |target_id|
|
59
|
+
page = find_or_create_page(target_id)
|
60
|
+
locator == page.frame_name
|
61
|
+
end
|
62
|
+
locator = target_id if target_id
|
147
63
|
end
|
148
64
|
|
149
|
-
|
150
|
-
user_agent = @headers["User-Agent"]
|
151
|
-
accept_language = @headers["Accept-Language"]
|
152
|
-
|
153
|
-
set_overrides(user_agent: user_agent, accept_language: accept_language)
|
154
|
-
page.command("Network.setExtraHTTPHeaders", headers: @headers)
|
155
|
-
end
|
156
|
-
|
157
|
-
def add_header(header, permanent: true)
|
158
|
-
add_headers(header, permanent: permanent)
|
159
|
-
end
|
160
|
-
|
161
|
-
def set_overrides(user_agent: nil, accept_language: nil, platform: nil)
|
162
|
-
options = Hash.new
|
163
|
-
options[:userAgent] = user_agent if user_agent
|
164
|
-
options[:acceptLanguage] = accept_language if accept_language
|
165
|
-
options[:platform] if platform
|
166
|
-
|
167
|
-
page.command("Network.setUserAgentOverride", **options) if !options.empty?
|
65
|
+
targets.within_window(locator, &block)
|
168
66
|
end
|
169
67
|
|
170
|
-
def
|
171
|
-
|
172
|
-
cookies.map { |c| [c["name"], Cookie.new(c)] }.to_h
|
68
|
+
def browser_error
|
69
|
+
evaluate("_cuprite.browserError()")
|
173
70
|
end
|
174
71
|
|
175
|
-
def
|
176
|
-
|
72
|
+
def source
|
73
|
+
raise NotImplementedError
|
177
74
|
end
|
178
75
|
|
179
|
-
def
|
180
|
-
|
76
|
+
def drag(node, other)
|
77
|
+
raise NotImplementedError
|
181
78
|
end
|
182
79
|
|
183
|
-
def
|
184
|
-
|
80
|
+
def drag_by(node, x, y)
|
81
|
+
raise NotImplementedError
|
185
82
|
end
|
186
83
|
|
187
|
-
def
|
188
|
-
|
189
|
-
page.intercept_request("*") if @client && !@url_whitelist.empty?
|
84
|
+
def select_file(node, value)
|
85
|
+
node.select_file(value)
|
190
86
|
end
|
191
87
|
|
192
|
-
def
|
193
|
-
|
194
|
-
page.intercept_request("*") if @client && !@url_blacklist.empty?
|
88
|
+
def parents(node)
|
89
|
+
evaluate_on(node: node, expression: "_cuprite.parents(this)", by_value: false)
|
195
90
|
end
|
196
91
|
|
197
|
-
def
|
198
|
-
|
92
|
+
def visible_text(node)
|
93
|
+
evaluate_on(node: node, expression: "_cuprite.visibleText(this)")
|
199
94
|
end
|
200
95
|
|
201
|
-
def
|
202
|
-
|
203
|
-
@zoom_factor = nil
|
204
|
-
@window_size = @original_window_size
|
205
|
-
targets.reset
|
96
|
+
def delete_text(node)
|
97
|
+
evaluate_on(node: node, expression: "_cuprite.deleteText(this)")
|
206
98
|
end
|
207
99
|
|
208
|
-
def
|
209
|
-
|
210
|
-
|
100
|
+
def attributes(node)
|
101
|
+
value = evaluate_on(node: node, expression: "_cuprite.getAttributes(this)")
|
102
|
+
JSON.parse(value)
|
211
103
|
end
|
212
104
|
|
213
|
-
def
|
214
|
-
|
215
|
-
@process.stop
|
216
|
-
@client = @process = @targets = nil
|
105
|
+
def attribute(node, name)
|
106
|
+
evaluate_on(node: node, expression: %Q(_cuprite.getAttribute(this, "#{name}")))
|
217
107
|
end
|
218
108
|
|
219
|
-
def
|
220
|
-
|
109
|
+
def value(node)
|
110
|
+
evaluate_on(node: node, expression: "_cuprite.value(this)")
|
221
111
|
end
|
222
112
|
|
223
|
-
def
|
224
|
-
|
113
|
+
def visible?(node)
|
114
|
+
evaluate_on(node: node, expression: "_cuprite.isVisible(this)")
|
225
115
|
end
|
226
116
|
|
227
|
-
def
|
228
|
-
|
229
|
-
page.resize(**options)
|
117
|
+
def disabled?(node)
|
118
|
+
evaluate_on(node: node, expression: "_cuprite.isDisabled(this)")
|
230
119
|
end
|
231
120
|
|
232
|
-
def
|
233
|
-
|
234
|
-
@client.wait(id: id)
|
235
|
-
rescue DeadBrowser
|
236
|
-
restart
|
237
|
-
raise
|
121
|
+
def path(node)
|
122
|
+
evaluate_on(node: node, expression: "_cuprite.path(this)")
|
238
123
|
end
|
239
124
|
|
240
|
-
def
|
241
|
-
|
125
|
+
def all_text(node)
|
126
|
+
node.text
|
242
127
|
end
|
243
128
|
|
244
129
|
private
|
245
130
|
|
246
|
-
def start
|
247
|
-
@headers = {}
|
248
|
-
@process = Process.start(@options)
|
249
|
-
@client = Client.new(self, @process.ws_url, false)
|
250
|
-
end
|
251
|
-
|
252
|
-
def render_options(format, opts)
|
253
|
-
options = {}
|
254
|
-
|
255
|
-
format ||= File.extname(opts[:path]).delete(".") || "png"
|
256
|
-
format = "jpeg" if format == "jpg"
|
257
|
-
raise "Not supported format: #{format}. jpeg | png | pdf" if format !~ /jpeg|png|pdf/i
|
258
|
-
options.merge!(format: format)
|
259
|
-
|
260
|
-
options.merge!(quality: opts[:quality] ? opts[:quality] : 75) if format == "jpeg"
|
261
|
-
|
262
|
-
warn "Ignoring :selector in #render since full: true was given at #{caller(1..1).first}" if !!opts[:full] && opts[:selector]
|
263
|
-
|
264
|
-
if !!opts[:full]
|
265
|
-
width, height = page.evaluate("[document.documentElement.offsetWidth, document.documentElement.offsetHeight]")
|
266
|
-
options.merge!(clip: { x: 0, y: 0, width: width, height: height, scale: @zoom_factor || 1.0 }) if width > 0 && height > 0
|
267
|
-
elsif opts[:selector]
|
268
|
-
rect = page.evaluate("document.querySelector('#{opts[:selector]}').getBoundingClientRect()")
|
269
|
-
options.merge!(clip: { x: rect["x"], y: rect["y"], width: rect["width"], height: rect["height"], scale: @zoom_factor || 1.0 })
|
270
|
-
end
|
271
|
-
|
272
|
-
if @zoom_factor
|
273
|
-
if !options[:clip]
|
274
|
-
width, height = page.evaluate("[document.documentElement.clientWidth, document.documentElement.clientHeight]")
|
275
|
-
options[:clip] = { x: 0, y: 0, width: width, height: height }
|
276
|
-
end
|
277
|
-
|
278
|
-
options[:clip].merge!(scale: @zoom_factor)
|
279
|
-
end
|
280
|
-
|
281
|
-
options
|
282
|
-
end
|
283
|
-
|
284
131
|
def find_all(method, selector, within = nil)
|
285
132
|
begin
|
286
|
-
|
133
|
+
nodes = if within
|
287
134
|
evaluate("_cuprite.find(arguments[0], arguments[1], arguments[2])", method, selector, within)
|
288
135
|
else
|
289
136
|
evaluate("_cuprite.find(arguments[0], arguments[1])", method, selector)
|
290
137
|
end
|
291
138
|
|
292
|
-
|
293
|
-
|
294
|
-
target_id, node = element.values_at("target_id", "node")
|
295
|
-
next if node["nodeType"] != 1
|
296
|
-
within ? node : [target_id, node]
|
297
|
-
end.compact
|
298
|
-
rescue JavaScriptError => e
|
139
|
+
nodes.map { |n| n.node? ? n : next }.compact
|
140
|
+
rescue Ferrum::JavaScriptError => e
|
299
141
|
if e.class_name == "InvalidSelector"
|
300
142
|
raise InvalidSelector.new(e.response, method, selector)
|
301
143
|
end
|