cuprite 0.12 → 0.15.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.
@@ -2,198 +2,192 @@
2
2
 
3
3
  require "forwardable"
4
4
 
5
- module Capybara::Cuprite
6
- class Page < Ferrum::Page
7
- MODAL_WAIT = ENV.fetch("CUPRITE_MODAL_WAIT", 0.05).to_f
8
- TRIGGER_CLICK_WAIT = ENV.fetch("CUPRITE_TRIGGER_CLICK_WAIT", 0.1).to_f
9
-
10
- extend Forwardable
11
- delegate %i[at_css at_xpath css xpath
12
- current_url current_title body execution_id
13
- evaluate evaluate_on evaluate_async execute] => :active_frame
14
-
15
- def initialize(*args)
16
- @frame_stack = []
17
- @accept_modal = []
18
- @modal_messages = []
19
- super
5
+ module Capybara
6
+ module Cuprite
7
+ class ClosedPage
8
+ def closed?
9
+ true
10
+ end
20
11
  end
21
12
 
22
- def set(node, value)
23
- object_id = command("DOM.resolveNode", nodeId: node.node_id).dig("object", "objectId")
24
- evaluate("_cuprite.set(arguments[0], arguments[1])", { "objectId" => object_id }, value)
25
- end
13
+ class Page < Ferrum::Page
14
+ MODAL_WAIT = ENV.fetch("CUPRITE_MODAL_WAIT", 0.05).to_f
15
+ TRIGGER_CLICK_WAIT = ENV.fetch("CUPRITE_TRIGGER_CLICK_WAIT", 0.1).to_f
26
16
 
27
- def select(node, value)
28
- evaluate_on(node: node, expression: "_cuprite.select(this, #{value})")
29
- end
17
+ extend Forwardable
18
+ delegate %i[at_css at_xpath css xpath
19
+ current_url current_title body execution_id execution_id!
20
+ evaluate evaluate_on evaluate_async execute] => :active_frame
30
21
 
31
- def trigger(node, event)
32
- options = {}
33
- options.merge!(wait: TRIGGER_CLICK_WAIT) if event.to_s == "click" && TRIGGER_CLICK_WAIT > 0
34
- evaluate_on(node: node, expression: %(_cuprite.trigger(this, "#{event}")), **options)
35
- end
22
+ def initialize(...)
23
+ @frame_stack = []
24
+ @accept_modal = []
25
+ @modal_messages = []
26
+ @modal_response = nil
27
+ super
28
+ end
36
29
 
37
- def hover(node)
38
- evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
39
- x, y = find_position(node)
40
- command("Input.dispatchMouseEvent", type: "mouseMoved", x: x, y: y)
41
- end
30
+ def set(node, value)
31
+ object_id = command("DOM.resolveNode", nodeId: node.node_id).dig("object", "objectId")
32
+ evaluate("_cuprite.set(arguments[0], arguments[1])", { "objectId" => object_id }, value)
33
+ end
42
34
 
43
- def send_keys(node, keys)
44
- if !evaluate_on(node: node, expression: %(_cuprite.containsSelection(this)))
45
- before_click(node, "click")
46
- node.click(mode: :left, keys: keys)
35
+ def select(node, value)
36
+ evaluate_on(node: node, expression: "_cuprite.select(this, #{value})")
47
37
  end
48
38
 
49
- keyboard.type(keys)
50
- end
39
+ def trigger(node, event)
40
+ options = {}
41
+ options.merge!(wait: TRIGGER_CLICK_WAIT) if event.to_s == "click" && TRIGGER_CLICK_WAIT.positive?
42
+ evaluate_on(node: node, expression: %(_cuprite.trigger(this, "#{event}")), **options)
43
+ end
51
44
 
52
- def accept_confirm
53
- @accept_modal << true
54
- end
45
+ def hover(node)
46
+ evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
47
+ x, y = find_position(node)
48
+ command("Input.dispatchMouseEvent", type: "mouseMoved", x: x, y: y)
49
+ end
55
50
 
56
- def dismiss_confirm
57
- @accept_modal << false
58
- end
51
+ def send_keys(node, keys)
52
+ unless evaluate_on(node: node, expression: %(_cuprite.containsSelection(this)))
53
+ before_click(node, "click")
54
+ node.click(mode: :left, keys: keys)
55
+ end
59
56
 
60
- def accept_prompt(modal_response)
61
- @accept_modal << true
62
- @modal_response = modal_response
63
- end
57
+ keyboard.type(keys)
58
+ end
64
59
 
65
- def dismiss_prompt
66
- @accept_modal << false
67
- end
60
+ def accept_confirm
61
+ @accept_modal << true
62
+ end
68
63
 
69
- def find_modal(options)
70
- start = Ferrum.monotonic_time
71
- timeout = options.fetch(:wait, browser.timeout)
72
- expect_text = options[:text]
73
- expect_regexp = expect_text.is_a?(Regexp) ? expect_text : Regexp.escape(expect_text.to_s)
74
- not_found_msg = "Unable to find modal dialog"
75
- not_found_msg += " with #{expect_text}" if expect_text
64
+ def dismiss_confirm
65
+ @accept_modal << false
66
+ end
76
67
 
77
- begin
78
- modal_text = @modal_messages.shift
79
- raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp))
80
- rescue Capybara::ModalNotFound => e
81
- raise e, not_found_msg if Ferrum.timeout?(start, timeout)
82
- sleep(MODAL_WAIT)
83
- retry
68
+ def accept_prompt(modal_response)
69
+ @accept_modal << true
70
+ @modal_response = modal_response
84
71
  end
85
72
 
86
- modal_text
87
- end
73
+ def dismiss_prompt
74
+ @accept_modal << false
75
+ end
88
76
 
89
- def reset_modals
90
- @accept_modal = []
91
- @modal_response = nil
92
- @modal_messages = []
93
- end
77
+ def find_modal(options)
78
+ start = Ferrum::Utils::ElapsedTime.monotonic_time
79
+ expect_text = options[:text]
80
+ expect_regexp = expect_text.is_a?(Regexp) ? expect_text : Regexp.escape(expect_text.to_s)
81
+ not_found_msg = "Unable to find modal dialog"
82
+ not_found_msg += " with #{expect_text}" if expect_text
83
+ wait = options.fetch(:wait, timeout)
84
+
85
+ begin
86
+ modal_text = @modal_messages.shift
87
+ raise Capybara::ModalNotFound if modal_text.nil? || (expect_text && !modal_text.match(expect_regexp))
88
+ rescue Capybara::ModalNotFound => e
89
+ raise e, not_found_msg if Ferrum::Utils::ElapsedTime.timeout?(start, wait)
90
+
91
+ sleep(MODAL_WAIT)
92
+ retry
93
+ end
94
94
 
95
- def before_click(node, name, keys = [], offset = {})
96
- evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
95
+ modal_text
96
+ end
97
97
 
98
- # If offset is given it may go outside of the element and likely error
99
- # will be raised that we detected another element at this position.
100
- return true if offset[:x] || offset[:y]
98
+ def reset_modals
99
+ @accept_modal = []
100
+ @modal_response = nil
101
+ @modal_messages = []
102
+ end
101
103
 
102
- x, y = find_position(node, **offset)
103
- evaluate_on(node: node, expression: "_cuprite.mouseEventTest(this, '#{name}', #{x}, #{y})")
104
- true
105
- rescue Ferrum::JavaScriptError => e
106
- raise MouseEventFailed.new(e.message) if e.class_name == "MouseEventFailed"
107
- end
104
+ def before_click(node, name, _keys = [], offset = {})
105
+ evaluate_on(node: node, expression: "_cuprite.scrollIntoViewport(this)")
108
106
 
109
- def switch_to_frame(handle)
110
- case handle
111
- when :parent
112
- @frame_stack.pop
113
- when :top
114
- @frame_stack = []
115
- else
116
- @frame_stack << handle
117
- inject_extensions
107
+ # If offset is given it may go outside of the element and likely error
108
+ # will be raised that we detected another element at this position.
109
+ return true if offset[:x] || offset[:y]
110
+
111
+ x, y = find_position(node, **offset)
112
+ evaluate_on(node: node, expression: "_cuprite.mouseEventTest(this, '#{name}', #{x}, #{y})")
113
+ true
114
+ rescue Ferrum::JavaScriptError => e
115
+ raise MouseEventFailed, e.message if e.class_name == "MouseEventFailed"
118
116
  end
119
- end
120
117
 
121
- def frame_name
122
- evaluate("window.name")
123
- end
118
+ def switch_to_frame(handle)
119
+ case handle
120
+ when :parent
121
+ @frame_stack.pop
122
+ when :top
123
+ @frame_stack = []
124
+ else
125
+ @frame_stack << handle
126
+ inject_extensions
127
+ end
128
+ end
124
129
 
125
- def title
126
- active_frame.current_title
127
- end
130
+ def frame_name
131
+ evaluate("window.name")
132
+ end
128
133
 
129
- private
134
+ def title
135
+ active_frame.current_title
136
+ end
130
137
 
131
- def prepare_page
132
- super
138
+ def closed?
139
+ false
140
+ end
133
141
 
134
- network.intercept if !Array(@browser.url_whitelist).empty? ||
135
- !Array(@browser.url_blacklist).empty?
142
+ private
136
143
 
137
- on(:request) do |request, index, total|
138
- if @browser.url_blacklist && !@browser.url_blacklist.empty?
139
- if @browser.url_blacklist.any? { |r| request.match?(r) }
140
- request.abort and next
141
- else
142
- request.continue and next
143
- end
144
- elsif @browser.url_whitelist && !@browser.url_whitelist.empty?
145
- if @browser.url_whitelist.any? { |r| request.match?(r) }
146
- request.continue and next
147
- else
148
- request.abort and next
149
- end
150
- elsif index + 1 < total
151
- # There are other callbacks that may handle this request
152
- next
153
- else
154
- # If there are no callbacks then just continue
155
- request.continue
144
+ def prepare_page
145
+ super
146
+
147
+ width, height = @options.window_size
148
+ resize(width: width, height: height)
149
+
150
+ if @options.url_blacklist.any?
151
+ network.blacklist = @options.url_blacklist
152
+ elsif @options.url_whitelist.any?
153
+ network.whitelist = @options.url_whitelist
156
154
  end
157
- end
158
155
 
159
- on("Page.javascriptDialogOpening") do |params|
160
- accept_modal = @accept_modal.last
161
- if accept_modal == true || accept_modal == false
162
- @accept_modal.pop
163
- @modal_messages << params["message"]
164
- options = { accept: accept_modal }
165
- response = @modal_response || params["defaultPrompt"]
166
- options.merge!(promptText: response) if response
167
- command("Page.handleJavaScriptDialog", **options)
168
- else
169
- with_text = params["message"] ? "with text `#{params["message"]}` " : ""
170
- warn "Modal window #{with_text}has been opened, but you didn't wrap "\
171
- "your code into (`accept_prompt` | `dismiss_prompt` | "\
172
- "`accept_confirm` | `dismiss_confirm` | `accept_alert`), "\
173
- "accepting by default"
174
- options = { accept: true }
175
- response = params["defaultPrompt"]
156
+ on("Page.javascriptDialogOpening") do |params|
157
+ accept_modal = @accept_modal.last
158
+ if [true, false].include?(accept_modal)
159
+ @accept_modal.pop
160
+ @modal_messages << params["message"]
161
+ options = { accept: accept_modal }
162
+ response = @modal_response || params["defaultPrompt"]
163
+ else
164
+ with_text = params["message"] ? "with text `#{params['message']}` " : ""
165
+ warn "Modal window #{with_text}has been opened, but you didn't wrap " \
166
+ "your code into (`accept_prompt` | `dismiss_prompt` | " \
167
+ "`accept_confirm` | `dismiss_confirm` | `accept_alert`), " \
168
+ "accepting by default"
169
+ options = { accept: true }
170
+ response = params["defaultPrompt"]
171
+ end
176
172
  options.merge!(promptText: response) if response
177
173
  command("Page.handleJavaScriptDialog", **options)
178
174
  end
179
175
  end
180
- end
181
176
 
182
- def find_position(node, **options)
183
- x, y = node.find_position(**options)
184
- rescue Ferrum::BrowserError => e
185
- if e.message == "Could not compute content quads."
186
- raise MouseEventFailed.new("MouseEventFailed: click, none, 0, 0")
187
- else
177
+ def find_position(node, **options)
178
+ node.find_position(**options)
179
+ rescue Ferrum::BrowserError => e
180
+ raise MouseEventFailed, "MouseEventFailed: click, none, 0, 0" if e.message == "Could not compute content quads."
181
+
188
182
  raise
189
183
  end
190
- end
191
184
 
192
- def active_frame
193
- if @frame_stack.empty?
194
- main_frame
195
- else
196
- @frames[@frame_stack.last]
185
+ def active_frame
186
+ if @frame_stack.empty?
187
+ main_frame
188
+ else
189
+ @frames[@frame_stack.last]
190
+ end
197
191
  end
198
192
  end
199
193
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Capybara
4
4
  module Cuprite
5
- VERSION = "0.12"
5
+ VERSION = "0.15.1"
6
6
  end
7
7
  end
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ ENV["FERRUM_DEBUG"] = "true" if ENV["CUPRITE_DEBUG"]
4
+
3
5
  require "ferrum"
4
6
  require "capybara"
5
7
  require "capybara/cuprite/driver"
6
8
  require "capybara/cuprite/browser"
7
9
  require "capybara/cuprite/page"
10
+ require "capybara/cuprite/options"
8
11
  require "capybara/cuprite/node"
9
12
  require "capybara/cuprite/errors"
10
13
 
metadata CHANGED
@@ -1,155 +1,23 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cuprite
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.12'
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Vorotilin
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-24 00:00:00.000000000 Z
11
+ date: 2024-06-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capybara
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '2.1'
20
- - - "<"
21
- - !ruby/object:Gem::Version
22
- version: '4'
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- version: '2.1'
30
- - - "<"
31
- - !ruby/object:Gem::Version
32
- version: '4'
33
- - !ruby/object:Gem::Dependency
34
- name: ferrum
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: 0.10.0
40
- type: :runtime
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: 0.10.0
47
- - !ruby/object:Gem::Dependency
48
- name: image_size
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '2.0'
54
- type: :development
55
- prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '2.0'
61
- - !ruby/object:Gem::Dependency
62
- name: pdf-reader
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '2.1'
68
- type: :development
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '2.1'
75
- - !ruby/object:Gem::Dependency
76
- name: rake
77
- requirement: !ruby/object:Gem::Requirement
78
- requirements:
79
- - - "~>"
80
- - !ruby/object:Gem::Version
81
- version: '12.3'
82
- type: :development
83
- prerelease: false
84
- version_requirements: !ruby/object:Gem::Requirement
85
- requirements:
86
- - - "~>"
87
- - !ruby/object:Gem::Version
88
- version: '12.3'
89
- - !ruby/object:Gem::Dependency
90
- name: rspec
91
- requirement: !ruby/object:Gem::Requirement
92
- requirements:
93
- - - "~>"
94
- - !ruby/object:Gem::Version
95
- version: '3.7'
96
- type: :development
97
- prerelease: false
98
- version_requirements: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - "~>"
101
- - !ruby/object:Gem::Version
102
- version: '3.7'
103
- - !ruby/object:Gem::Dependency
104
- name: sinatra
105
- requirement: !ruby/object:Gem::Requirement
106
- requirements:
107
- - - "~>"
108
- - !ruby/object:Gem::Version
109
- version: '2.0'
110
- type: :development
111
- prerelease: false
112
- version_requirements: !ruby/object:Gem::Requirement
113
- requirements:
114
- - - "~>"
115
- - !ruby/object:Gem::Version
116
- version: '2.0'
117
- - !ruby/object:Gem::Dependency
118
- name: launchy
119
- requirement: !ruby/object:Gem::Requirement
120
- requirements:
121
- - - "~>"
122
- - !ruby/object:Gem::Version
123
- version: '2.4'
124
- type: :development
125
- prerelease: false
126
- version_requirements: !ruby/object:Gem::Requirement
127
- requirements:
128
- - - "~>"
129
- - !ruby/object:Gem::Version
130
- version: '2.4'
131
- - !ruby/object:Gem::Dependency
132
- name: byebug
133
- requirement: !ruby/object:Gem::Requirement
134
- requirements:
135
- - - "~>"
136
- - !ruby/object:Gem::Version
137
- version: '10.0'
138
- type: :development
139
- prerelease: false
140
- version_requirements: !ruby/object:Gem::Requirement
141
- requirements:
142
- - - "~>"
143
- - !ruby/object:Gem::Version
144
- version: '10.0'
145
- - !ruby/object:Gem::Dependency
146
- name: puma
147
15
  requirement: !ruby/object:Gem::Requirement
148
16
  requirements:
149
17
  - - "~>"
150
18
  - !ruby/object:Gem::Version
151
19
  version: '3.0'
152
- type: :development
20
+ type: :runtime
153
21
  prerelease: false
154
22
  version_requirements: !ruby/object:Gem::Requirement
155
23
  requirements:
@@ -157,19 +25,19 @@ dependencies:
157
25
  - !ruby/object:Gem::Version
158
26
  version: '3.0'
159
27
  - !ruby/object:Gem::Dependency
160
- name: chunky_png
28
+ name: ferrum
161
29
  requirement: !ruby/object:Gem::Requirement
162
30
  requirements:
163
31
  - - "~>"
164
32
  - !ruby/object:Gem::Version
165
- version: '1.3'
166
- type: :development
33
+ version: 0.15.0
34
+ type: :runtime
167
35
  prerelease: false
168
36
  version_requirements: !ruby/object:Gem::Requirement
169
37
  requirements:
170
38
  - - "~>"
171
39
  - !ruby/object:Gem::Version
172
- version: '1.3'
40
+ version: 0.15.0
173
41
  description: Cuprite is a driver for Capybara that allows you to run your tests on
174
42
  a headless Chrome browser
175
43
  email:
@@ -187,13 +55,19 @@ files:
187
55
  - lib/capybara/cuprite/errors.rb
188
56
  - lib/capybara/cuprite/javascripts/index.js
189
57
  - lib/capybara/cuprite/node.rb
58
+ - lib/capybara/cuprite/options.rb
190
59
  - lib/capybara/cuprite/page.rb
191
60
  - lib/capybara/cuprite/version.rb
192
61
  homepage: https://github.com/rubycdp/cuprite
193
62
  licenses:
194
63
  - MIT
195
- metadata: {}
196
- post_install_message:
64
+ metadata:
65
+ homepage_uri: https://cuprite.rubycdp.com/
66
+ bug_tracker_uri: https://github.com/rubycdp/cuprite/issues
67
+ documentation_uri: https://github.com/rubycdp/cuprite/blob/main/README.md
68
+ source_code_uri: https://github.com/rubycdp/cuprite
69
+ rubygems_mfa_required: 'true'
70
+ post_install_message:
197
71
  rdoc_options: []
198
72
  require_paths:
199
73
  - lib
@@ -201,15 +75,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
201
75
  requirements:
202
76
  - - ">="
203
77
  - !ruby/object:Gem::Version
204
- version: 2.3.0
78
+ version: 2.7.0
205
79
  required_rubygems_version: !ruby/object:Gem::Requirement
206
80
  requirements:
207
81
  - - ">="
208
82
  - !ruby/object:Gem::Version
209
83
  version: '0'
210
84
  requirements: []
211
- rubygems_version: 3.1.2
212
- signing_key:
85
+ rubygems_version: 3.5.11
86
+ signing_key:
213
87
  specification_version: 4
214
88
  summary: Headless Chrome driver for Capybara
215
89
  test_files: []