cuprite 0.19 → 0.20
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 +43 -41
- data/lib/capybara/cuprite/browser/deprecations.rb +26 -0
- data/lib/capybara/cuprite/browser/extensions.rb +59 -0
- data/lib/capybara/cuprite/browser.rb +18 -232
- data/lib/capybara/cuprite/deprecation.rb +13 -0
- data/lib/capybara/cuprite/driver/deprecations.rb +198 -0
- data/lib/capybara/cuprite/driver/extensions.rb +13 -0
- data/lib/capybara/cuprite/driver.rb +66 -201
- data/lib/capybara/cuprite/finder.rb +22 -0
- data/lib/capybara/cuprite/javascripts/drag.js +96 -101
- data/lib/capybara/cuprite/javascripts/index.js +507 -508
- data/lib/capybara/cuprite/node/deprecations.rb +43 -0
- data/lib/capybara/cuprite/node/extensions.rb +27 -0
- data/lib/capybara/cuprite/node.rb +130 -116
- data/lib/capybara/cuprite/options.rb +1 -1
- data/lib/capybara/cuprite/page/frames.rb +47 -0
- data/lib/capybara/cuprite/page/modals.rb +118 -0
- data/lib/capybara/cuprite/page.rb +6 -209
- data/lib/capybara/cuprite/version.rb +1 -1
- metadata +15 -6
- data/lib/capybara/cuprite/cookie.rb +0 -47
|
@@ -1,181 +1,25 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require "
|
|
3
|
+
require "capybara/cuprite/page/frames"
|
|
4
|
+
require "capybara/cuprite/page/modals"
|
|
4
5
|
|
|
5
6
|
module Capybara
|
|
6
7
|
module Cuprite
|
|
7
|
-
class ClosedPage
|
|
8
|
-
def closed?
|
|
9
|
-
true
|
|
10
|
-
end
|
|
11
|
-
end
|
|
12
|
-
|
|
13
8
|
class Page < Ferrum::Page
|
|
14
|
-
|
|
15
|
-
TRIGGER_CLICK_WAIT = ENV.fetch("CUPRITE_TRIGGER_CLICK_WAIT", 0.1).to_f
|
|
9
|
+
EXTENSION_JS = File.read(Driver::EXTENSION).freeze
|
|
16
10
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
delegate %i[at_css at_xpath css xpath
|
|
20
|
-
current_url current_title body execution_id execution_id!
|
|
21
|
-
evaluate evaluate_on evaluate_async execute] => :active_frame
|
|
22
|
-
|
|
23
|
-
def initialize(...)
|
|
24
|
-
@frame_stack = []
|
|
25
|
-
@accept_modal = []
|
|
26
|
-
@modal_messages = []
|
|
27
|
-
@modal_response = nil
|
|
28
|
-
@unhandled_modal_error = nil
|
|
29
|
-
super
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# Keep a handle to Ferrum's own implementation before overriding it
|
|
33
|
-
# below, so answering a dialog (see `handle_javascript_dialog`) can
|
|
34
|
-
# bypass our override.
|
|
35
|
-
alias ferrum_command command
|
|
36
|
-
|
|
37
|
-
# The `Page.javascriptDialogOpening` event is handled on Ferrum's
|
|
38
|
-
# background CDP dispatcher thread, so raising there wouldn't reach
|
|
39
|
-
# the caller and would permanently kill that thread instead. The
|
|
40
|
-
# dialog is always accepted immediately from that thread, and the
|
|
41
|
-
# error (if any) is stashed here to be raised from the main thread
|
|
42
|
-
# the next time it makes a command round trip.
|
|
43
|
-
def command(...)
|
|
44
|
-
raise_pending_unhandled_modal_error! { super }
|
|
45
|
-
end
|
|
11
|
+
include Frames
|
|
12
|
+
include Modals
|
|
46
13
|
|
|
47
14
|
def set_viewport(width: 0, height: 0, scale_factor: @options.scale_factor, mobile: @options.mobile)
|
|
48
15
|
super
|
|
49
16
|
end
|
|
50
17
|
|
|
51
|
-
def set(node, value)
|
|
52
|
-
object_id = command("DOM.resolveNode", nodeId: node.node_id).dig("object", "objectId")
|
|
53
|
-
evaluate("_cuprite.set(arguments[0], arguments[1])", { "objectId" => object_id }, value)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def select(node, value)
|
|
57
|
-
evaluate_on(node: node, expression: "_cuprite.select(this, #{value})")
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def trigger(node, event)
|
|
61
|
-
options = {}
|
|
62
|
-
options.merge!(wait: TRIGGER_CLICK_WAIT) if event.to_s == "click" && TRIGGER_CLICK_WAIT.positive?
|
|
63
|
-
evaluate_on(node: node, expression: %(_cuprite.trigger(this, "#{event}")), **options)
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def hover(node)
|
|
67
|
-
evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
|
|
68
|
-
x, y = find_position(node)
|
|
69
|
-
command("Input.dispatchMouseEvent", type: "mouseMoved", x: x, y: y)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def send_keys(node, keys)
|
|
73
|
-
unless evaluate_on(node: node, expression: %(_cuprite.containsSelection(this) || _cuprite.hasFocus(this)))
|
|
74
|
-
before_click(node, "click")
|
|
75
|
-
node.click(mode: :left, keys: keys)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
keyboard.type(keys)
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def accept_confirm
|
|
82
|
-
@accept_modal << true
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def dismiss_confirm
|
|
86
|
-
@accept_modal << false
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def accept_prompt(modal_response)
|
|
90
|
-
@accept_modal << true
|
|
91
|
-
@modal_response = modal_response
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
def dismiss_prompt
|
|
95
|
-
@accept_modal << false
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
def find_modal(options)
|
|
99
|
-
start = Ferrum::Utils::ElapsedTime.monotonic_time
|
|
100
|
-
expect_text = options[:text]
|
|
101
|
-
expect_regexp = expect_text.is_a?(Regexp) ? expect_text : Regexp.escape(expect_text.to_s)
|
|
102
|
-
not_found_msg = "Unable to find modal dialog"
|
|
103
|
-
not_found_msg += " with #{expect_text}" if expect_text
|
|
104
|
-
wait = options.fetch(:wait, timeout)
|
|
105
|
-
|
|
106
|
-
begin
|
|
107
|
-
modal_text = @modal_messages.shift
|
|
108
|
-
raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp))
|
|
109
|
-
rescue Capybara::ModalNotFound => e
|
|
110
|
-
raise e, not_found_msg if Ferrum::Utils::ElapsedTime.timeout?(start, wait)
|
|
111
|
-
|
|
112
|
-
sleep(MODAL_WAIT)
|
|
113
|
-
retry
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
modal_text
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def reset_modals
|
|
120
|
-
@accept_modal = []
|
|
121
|
-
@modal_response = nil
|
|
122
|
-
@modal_messages = []
|
|
123
|
-
@unhandled_modal_error = nil
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
def before_click(node, name, _keys = [], offset = {})
|
|
127
|
-
evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
|
|
128
|
-
|
|
129
|
-
# If offset is given it may go outside of the element and likely error
|
|
130
|
-
# will be raised that we detected another element at this position.
|
|
131
|
-
return true if offset[:x] || offset[:y]
|
|
132
|
-
|
|
133
|
-
x, y = find_position(node, **offset)
|
|
134
|
-
evaluate_on(node: node, expression: "_cuprite.mouseEventTest(this, '#{name}', #{x}, #{y})")
|
|
135
|
-
true
|
|
136
|
-
rescue Ferrum::JavaScriptError => e
|
|
137
|
-
raise MouseEventFailed, e.message if e.class_name == "MouseEventFailed"
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def switch_to_frame(handle)
|
|
141
|
-
case handle
|
|
142
|
-
when :parent
|
|
143
|
-
@frame_stack.pop
|
|
144
|
-
when :top
|
|
145
|
-
@frame_stack = []
|
|
146
|
-
else
|
|
147
|
-
@frame_stack << handle
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def frame_name
|
|
152
|
-
evaluate("window.name")
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
def title
|
|
156
|
-
active_frame.current_title
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def closed?
|
|
160
|
-
false
|
|
161
|
-
end
|
|
162
|
-
|
|
163
18
|
private
|
|
164
19
|
|
|
165
|
-
def raise_pending_unhandled_modal_error!
|
|
166
|
-
error = @unhandled_modal_error
|
|
167
|
-
@unhandled_modal_error = nil
|
|
168
|
-
raise error if error
|
|
169
|
-
|
|
170
|
-
yield
|
|
171
|
-
ensure
|
|
172
|
-
error = @unhandled_modal_error
|
|
173
|
-
@unhandled_modal_error = nil
|
|
174
|
-
raise error if error
|
|
175
|
-
end
|
|
176
|
-
|
|
177
20
|
def prepare_page
|
|
178
21
|
super
|
|
22
|
+
execute(EXTENSION_JS)
|
|
179
23
|
|
|
180
24
|
width, height = @options.window_size
|
|
181
25
|
width && height ? resize(width: width, height: height) : set_viewport
|
|
@@ -186,53 +30,6 @@ module Capybara
|
|
|
186
30
|
elsif @options.url_whitelist.any?
|
|
187
31
|
network.whitelist = @options.url_whitelist
|
|
188
32
|
end
|
|
189
|
-
|
|
190
|
-
on("Page.javascriptDialogOpening") do |params|
|
|
191
|
-
accept_modal = @accept_modal.last
|
|
192
|
-
unhandled_modal_error = nil
|
|
193
|
-
|
|
194
|
-
if [true, false].include?(accept_modal)
|
|
195
|
-
@accept_modal.pop
|
|
196
|
-
@modal_messages << params["message"]
|
|
197
|
-
options = { accept: accept_modal }
|
|
198
|
-
response = @modal_response || params["defaultPrompt"]
|
|
199
|
-
else
|
|
200
|
-
with_text = params["message"] ? "with text `#{params['message']}` " : ""
|
|
201
|
-
message = "Modal window #{with_text}has been opened, but you didn't wrap " \
|
|
202
|
-
"your code into (`accept_prompt` | `dismiss_prompt` | " \
|
|
203
|
-
"`accept_confirm` | `dismiss_confirm` | `accept_alert`), " \
|
|
204
|
-
"accepting by default"
|
|
205
|
-
|
|
206
|
-
if @options.raise_on_unhandled_modal
|
|
207
|
-
unhandled_modal_error = UnhandledModalError.new(message)
|
|
208
|
-
else
|
|
209
|
-
warn message
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
options = { accept: true }
|
|
213
|
-
response = params["defaultPrompt"]
|
|
214
|
-
end
|
|
215
|
-
options.merge!(promptText: response) if response
|
|
216
|
-
ferrum_command("Page.handleJavaScriptDialog", **options)
|
|
217
|
-
|
|
218
|
-
@unhandled_modal_error = unhandled_modal_error if unhandled_modal_error
|
|
219
|
-
end
|
|
220
|
-
end
|
|
221
|
-
|
|
222
|
-
def find_position(node, **options)
|
|
223
|
-
node.find_position(**options)
|
|
224
|
-
rescue Ferrum::BrowserError => e
|
|
225
|
-
raise MouseEventFailed, "MouseEventFailed: click, none, 0, 0" if e.message == "Could not compute content quads."
|
|
226
|
-
|
|
227
|
-
raise
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
def active_frame
|
|
231
|
-
if @frame_stack.empty?
|
|
232
|
-
main_frame
|
|
233
|
-
else
|
|
234
|
-
@frames[@frame_stack.last]
|
|
235
|
-
end
|
|
236
33
|
end
|
|
237
34
|
end
|
|
238
35
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cuprite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: '0.
|
|
4
|
+
version: '0.20'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dmitry Vorotilin
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-10-
|
|
11
|
+
date: 2026-10-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: capybara
|
|
@@ -30,14 +30,14 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 0.
|
|
33
|
+
version: 0.20.1
|
|
34
34
|
type: :runtime
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 0.
|
|
40
|
+
version: 0.20.1
|
|
41
41
|
description: Cuprite is a driver for Capybara that allows you to run your tests on
|
|
42
42
|
a headless Chrome browser
|
|
43
43
|
email:
|
|
@@ -50,15 +50,24 @@ files:
|
|
|
50
50
|
- README.md
|
|
51
51
|
- lib/capybara/cuprite.rb
|
|
52
52
|
- lib/capybara/cuprite/browser.rb
|
|
53
|
-
- lib/capybara/cuprite/
|
|
53
|
+
- lib/capybara/cuprite/browser/deprecations.rb
|
|
54
|
+
- lib/capybara/cuprite/browser/extensions.rb
|
|
55
|
+
- lib/capybara/cuprite/deprecation.rb
|
|
54
56
|
- lib/capybara/cuprite/devices.rb
|
|
55
57
|
- lib/capybara/cuprite/driver.rb
|
|
58
|
+
- lib/capybara/cuprite/driver/deprecations.rb
|
|
59
|
+
- lib/capybara/cuprite/driver/extensions.rb
|
|
56
60
|
- lib/capybara/cuprite/errors.rb
|
|
61
|
+
- lib/capybara/cuprite/finder.rb
|
|
57
62
|
- lib/capybara/cuprite/javascripts/drag.js
|
|
58
63
|
- lib/capybara/cuprite/javascripts/index.js
|
|
59
64
|
- lib/capybara/cuprite/node.rb
|
|
65
|
+
- lib/capybara/cuprite/node/deprecations.rb
|
|
66
|
+
- lib/capybara/cuprite/node/extensions.rb
|
|
60
67
|
- lib/capybara/cuprite/options.rb
|
|
61
68
|
- lib/capybara/cuprite/page.rb
|
|
69
|
+
- lib/capybara/cuprite/page/frames.rb
|
|
70
|
+
- lib/capybara/cuprite/page/modals.rb
|
|
62
71
|
- lib/capybara/cuprite/version.rb
|
|
63
72
|
homepage: https://github.com/rubycdp/cuprite
|
|
64
73
|
licenses:
|
|
@@ -77,7 +86,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
77
86
|
requirements:
|
|
78
87
|
- - ">="
|
|
79
88
|
- !ruby/object:Gem::Version
|
|
80
|
-
version: '3.
|
|
89
|
+
version: '3.2'
|
|
81
90
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
91
|
requirements:
|
|
83
92
|
- - ">="
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Capybara
|
|
4
|
-
module Cuprite
|
|
5
|
-
class Cookie
|
|
6
|
-
def initialize(attributes)
|
|
7
|
-
@attributes = attributes
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def name
|
|
11
|
-
@attributes["name"]
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
def value
|
|
15
|
-
@attributes["value"]
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def domain
|
|
19
|
-
@attributes["domain"]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def path
|
|
23
|
-
@attributes["path"]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def size
|
|
27
|
-
@attributes["size"]
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def secure?
|
|
31
|
-
@attributes["secure"]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def httponly?
|
|
35
|
-
@attributes["httpOnly"]
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def session?
|
|
39
|
-
@attributes["session"]
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def expires
|
|
43
|
-
Time.at(@attributes["expires"]) if @attributes["expires"].positive?
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
end
|