capybara 2.7.1 → 2.8.0
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/History.md +22 -0
- data/README.md +27 -3
- data/lib/capybara.rb +19 -4
- data/lib/capybara/driver/base.rb +6 -2
- data/lib/capybara/driver/node.rb +13 -5
- data/lib/capybara/helpers.rb +2 -2
- data/lib/capybara/node/actions.rb +116 -17
- data/lib/capybara/node/base.rb +7 -1
- data/lib/capybara/node/element.rb +23 -3
- data/lib/capybara/node/finders.rb +45 -29
- data/lib/capybara/node/matchers.rb +13 -15
- data/lib/capybara/queries/selector_query.rb +22 -5
- data/lib/capybara/queries/text_query.rb +42 -6
- data/lib/capybara/rack_test/node.rb +13 -1
- data/lib/capybara/result.rb +80 -8
- data/lib/capybara/rspec/features.rb +13 -6
- data/lib/capybara/selector.rb +98 -71
- data/lib/capybara/selector/filter_set.rb +46 -0
- data/lib/capybara/selenium/driver.rb +22 -23
- data/lib/capybara/selenium/node.rb +14 -6
- data/lib/capybara/server.rb +20 -10
- data/lib/capybara/session.rb +44 -8
- data/lib/capybara/spec/session/all_spec.rb +4 -4
- data/lib/capybara/spec/session/assert_text.rb +23 -0
- data/lib/capybara/spec/session/check_spec.rb +66 -8
- data/lib/capybara/spec/session/choose_spec.rb +20 -0
- data/lib/capybara/spec/session/click_button_spec.rb +0 -3
- data/lib/capybara/spec/session/click_link_spec.rb +7 -0
- data/lib/capybara/spec/session/execute_script_spec.rb +6 -1
- data/lib/capybara/spec/session/find_button_spec.rb +19 -1
- data/lib/capybara/spec/session/find_field_spec.rb +21 -1
- data/lib/capybara/spec/session/find_link_spec.rb +19 -1
- data/lib/capybara/spec/session/find_spec.rb +32 -4
- data/lib/capybara/spec/session/first_spec.rb +4 -4
- data/lib/capybara/spec/session/has_field_spec.rb +4 -0
- data/lib/capybara/spec/session/has_text_spec.rb +2 -2
- data/lib/capybara/spec/session/node_spec.rb +24 -3
- data/lib/capybara/spec/session/reset_session_spec.rb +7 -0
- data/lib/capybara/spec/session/selectors_spec.rb +14 -0
- data/lib/capybara/spec/session/uncheck_spec.rb +39 -0
- data/lib/capybara/spec/session/window/switch_to_window_spec.rb +4 -2
- data/lib/capybara/spec/session/window/window_opened_by_spec.rb +2 -1
- data/lib/capybara/spec/session/window/window_spec.rb +36 -22
- data/lib/capybara/spec/session/within_frame_spec.rb +19 -0
- data/lib/capybara/spec/spec_helper.rb +3 -0
- data/lib/capybara/spec/views/form.erb +34 -6
- data/lib/capybara/spec/views/with_html.erb +5 -1
- data/lib/capybara/spec/views/with_unload_alert.erb +3 -1
- data/lib/capybara/spec/views/with_windows.erb +2 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/capybara_spec.rb +34 -0
- data/spec/rack_test_spec.rb +24 -0
- data/spec/result_spec.rb +25 -0
- data/spec/rspec/features_spec.rb +3 -3
- data/spec/selenium_spec.rb +6 -3
- data/spec/server_spec.rb +2 -2
- metadata +18 -4
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
if RSpec::Core::Version::STRING.to_f >= 3.0
|
3
|
-
RSpec.shared_context "Capybara Features", :
|
3
|
+
RSpec.shared_context "Capybara Features", capybara_feature: true do
|
4
4
|
instance_eval do
|
5
5
|
alias background before
|
6
6
|
alias given let
|
@@ -8,13 +8,20 @@ if RSpec::Core::Version::STRING.to_f >= 3.0
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
+
# ensure shared_context is included if default shared_context_metadata_behavior is changed
|
12
|
+
if RSpec::Core::Version::STRING.to_f >= 3.5
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.include_context "Capybara Features", capybara_feature: true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
11
18
|
RSpec.configure do |config|
|
12
|
-
config.alias_example_group_to :feature, :
|
13
|
-
config.alias_example_group_to :xfeature, :
|
14
|
-
config.alias_example_group_to :ffeature, :
|
19
|
+
config.alias_example_group_to :feature, capybara_feature: true, type: :feature
|
20
|
+
config.alias_example_group_to :xfeature, capybara_feature: true, type: :feature, skip: "Temporarily disabled with xfeature"
|
21
|
+
config.alias_example_group_to :ffeature, capybara_feature: true, type: :feature, focus: true
|
15
22
|
config.alias_example_to :scenario
|
16
|
-
config.alias_example_to :xscenario, :
|
17
|
-
config.alias_example_to :fscenario, :
|
23
|
+
config.alias_example_to :xscenario, skip: "Temporarily disabled with xscenario"
|
24
|
+
config.alias_example_to :fscenario, focus: true
|
18
25
|
end
|
19
26
|
else
|
20
27
|
module Capybara
|
data/lib/capybara/selector.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require 'capybara/selector/
|
2
|
+
require 'capybara/selector/filter_set'
|
3
3
|
|
4
4
|
module Capybara
|
5
5
|
class Selector
|
6
6
|
|
7
|
-
attr_reader :name, :
|
7
|
+
attr_reader :name, :format
|
8
8
|
|
9
9
|
class << self
|
10
10
|
def all
|
@@ -26,7 +26,7 @@ module Capybara
|
|
26
26
|
|
27
27
|
def initialize(name, &block)
|
28
28
|
@name = name
|
29
|
-
@
|
29
|
+
@filter_set = FilterSet.add(name){}
|
30
30
|
@match = nil
|
31
31
|
@label = nil
|
32
32
|
@failure_message = nil
|
@@ -36,6 +36,10 @@ module Capybara
|
|
36
36
|
instance_eval(&block)
|
37
37
|
end
|
38
38
|
|
39
|
+
def custom_filters
|
40
|
+
@filter_set.filters
|
41
|
+
end
|
42
|
+
|
39
43
|
def xpath(&block)
|
40
44
|
@format, @expression = :xpath, block if block
|
41
45
|
format == :xpath ? @expression : nil
|
@@ -57,7 +61,7 @@ module Capybara
|
|
57
61
|
end
|
58
62
|
|
59
63
|
def description(options={})
|
60
|
-
|
64
|
+
@filter_set.description(options)
|
61
65
|
end
|
62
66
|
|
63
67
|
def call(locator)
|
@@ -73,20 +77,31 @@ module Capybara
|
|
73
77
|
end
|
74
78
|
|
75
79
|
def filter(name, options={}, &block)
|
76
|
-
|
80
|
+
custom_filters[name] = Filter.new(name, block, options)
|
81
|
+
end
|
82
|
+
|
83
|
+
def filter_set(name, filters_to_use = nil)
|
84
|
+
f_set = FilterSet.all[name]
|
85
|
+
f_set.filters.each do | name, filter |
|
86
|
+
custom_filters[name] = filter if filters_to_use.nil? || filters_to_use.include?(name)
|
87
|
+
end
|
88
|
+
f_set.descriptions.each { |desc| @filter_set.describe &desc }
|
77
89
|
end
|
78
90
|
|
79
91
|
def describe &block
|
80
|
-
@
|
92
|
+
@filter_set.describe &block
|
81
93
|
end
|
82
94
|
|
83
95
|
private
|
84
96
|
|
85
97
|
def locate_field(xpath, locator)
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
98
|
+
attr_matchers = XPath.attr(:id).equals(locator) |
|
99
|
+
XPath.attr(:name).equals(locator) |
|
100
|
+
XPath.attr(:placeholder).equals(locator) |
|
101
|
+
XPath.attr(:id).equals(XPath.anywhere(:label)[XPath.string.n.is(locator)].attr(:for))
|
102
|
+
attr_matchers |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
|
103
|
+
|
104
|
+
locate_field = xpath[attr_matchers]
|
90
105
|
locate_field += XPath.descendant(:label)[XPath.string.n.is(locator)].descendant(xpath)
|
91
106
|
locate_field
|
92
107
|
end
|
@@ -105,35 +120,55 @@ Capybara.add_selector(:id) do
|
|
105
120
|
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
106
121
|
end
|
107
122
|
|
123
|
+
Capybara::Selector::FilterSet.add(:_field) do
|
124
|
+
filter(:id) { |node, id| node['id'] == id }
|
125
|
+
filter(:name) { |node, name| node['name'] == name }
|
126
|
+
filter(:placeholder) { |node, placeholder| node['placeholder'] == placeholder }
|
127
|
+
filter(:checked, boolean: true) { |node, value| not(value ^ node.checked?) }
|
128
|
+
filter(:unchecked, boolean: true) { |node, value| (value ^ node.checked?) }
|
129
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
130
|
+
filter(:multiple, boolean: true) { |node, value| !(value ^ node.multiple?) }
|
131
|
+
|
132
|
+
describe do |options|
|
133
|
+
desc, states = String.new, []
|
134
|
+
[:id, :name, :placeholder].each do |opt|
|
135
|
+
desc << " with #{opt.to_s} #{options[opt]}" if options.has_key?(opt)
|
136
|
+
end
|
137
|
+
states << 'checked' if options[:checked] || (options[:unchecked] === false)
|
138
|
+
states << 'not checked' if options[:unchecked] || (options[:checked] === false)
|
139
|
+
states << 'disabled' if options[:disabled] == true
|
140
|
+
desc << " that is #{states.join(' and ')}" unless states.empty?
|
141
|
+
desc << " with the multiple attribute" if options[:multiple] == true
|
142
|
+
desc << " without the multiple attribute" if options[:multiple] === false
|
143
|
+
desc
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
108
147
|
Capybara.add_selector(:field) do
|
109
148
|
xpath do |locator|
|
110
149
|
xpath = XPath.descendant(:input, :textarea, :select)[~XPath.attr(:type).one_of('submit', 'image', 'hidden')]
|
111
150
|
xpath = locate_field(xpath, locator.to_s) unless locator.nil?
|
112
151
|
xpath
|
113
152
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
filter(:readonly, boolean: true) { |node, value| not(value ^ node
|
118
|
-
filter(:with)
|
153
|
+
|
154
|
+
filter_set(:_field)
|
155
|
+
|
156
|
+
filter(:readonly, boolean: true) { |node, value| not(value ^ node.readonly?) }
|
157
|
+
filter(:with) do |node, with|
|
158
|
+
with.is_a?(Regexp) ? node.value =~ with : node.value == with.to_s
|
159
|
+
end
|
119
160
|
filter(:type) do |node, type|
|
161
|
+
type = type.to_s
|
120
162
|
if ['textarea', 'select'].include?(type)
|
121
163
|
node.tag_name == type
|
122
164
|
else
|
123
165
|
node[:type] == type
|
124
166
|
end
|
125
167
|
end
|
126
|
-
filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
|
127
168
|
describe do |options|
|
128
169
|
desc, states = String.new, []
|
129
170
|
desc << " of type #{options[:type].inspect}" if options[:type]
|
130
171
|
desc << " with value #{options[:with].to_s.inspect}" if options.has_key?(:with)
|
131
|
-
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
|
132
|
-
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
|
133
|
-
states << 'disabled' if options[:disabled] == true
|
134
|
-
desc << " that is #{states.join(' and ')}" unless states.empty?
|
135
|
-
desc << " with the multiple attribute" if options[:multiple] == true
|
136
|
-
desc << " without the multiple attribute" if options[:multiple] === false
|
137
172
|
desc
|
138
173
|
end
|
139
174
|
end
|
@@ -151,10 +186,12 @@ Capybara.add_selector(:link) do
|
|
151
186
|
xpath = XPath.descendant(:a)[XPath.attr(:href)]
|
152
187
|
unless locator.nil?
|
153
188
|
locator = locator.to_s
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
189
|
+
matchers = XPath.attr(:id).equals(locator) |
|
190
|
+
XPath.string.n.is(locator) |
|
191
|
+
XPath.attr(:title).is(locator) |
|
192
|
+
XPath.descendant(:img)[XPath.attr(:alt).is(locator)]
|
193
|
+
matchers |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
|
194
|
+
xpath = xpath[matchers]
|
158
195
|
end
|
159
196
|
xpath
|
160
197
|
end
|
@@ -178,9 +215,16 @@ Capybara.add_selector(:button) do
|
|
178
215
|
|
179
216
|
unless locator.nil?
|
180
217
|
locator = locator.to_s
|
181
|
-
|
182
|
-
|
183
|
-
|
218
|
+
locator_matches = XPath.attr(:id).equals(locator) | XPath.attr(:value).is(locator) | XPath.attr(:title).is(locator)
|
219
|
+
locator_matches |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
|
220
|
+
|
221
|
+
input_btn_xpath = input_btn_xpath[locator_matches]
|
222
|
+
|
223
|
+
btn_xpath = btn_xpath[locator_matches | XPath.string.n.is(locator)]
|
224
|
+
|
225
|
+
alt_matches = XPath.attr(:alt).is(locator)
|
226
|
+
alt_matches |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
|
227
|
+
image_btn_xpath = image_btn_xpath[alt_matches]
|
184
228
|
end
|
185
229
|
|
186
230
|
input_btn_xpath + btn_xpath + image_btn_xpath
|
@@ -197,7 +241,7 @@ Capybara.add_selector(:link_or_button) do
|
|
197
241
|
self.class.all.values_at(:link, :button).map {|selector| selector.xpath.call(locator)}.reduce(:+)
|
198
242
|
end
|
199
243
|
|
200
|
-
filter(:disabled, default: false, boolean: true) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
|
244
|
+
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
|
201
245
|
|
202
246
|
describe { |options| " that is disabled" if options[:disabled] }
|
203
247
|
end
|
@@ -210,16 +254,7 @@ Capybara.add_selector(:fillable_field) do
|
|
210
254
|
xpath
|
211
255
|
end
|
212
256
|
|
213
|
-
|
214
|
-
filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
|
215
|
-
|
216
|
-
describe do |options|
|
217
|
-
desc = String.new
|
218
|
-
desc << " that is disabled" if options[:disabled] == true
|
219
|
-
desc << " with the multiple attribute" if options[:multiple] == true
|
220
|
-
desc << " without the multiple attribute" if options[:multiple] === false
|
221
|
-
desc
|
222
|
-
end
|
257
|
+
filter_set(:_field, [:id, :name, :placeholder, :disabled, :multiple])
|
223
258
|
end
|
224
259
|
|
225
260
|
Capybara.add_selector(:radio_button) do
|
@@ -230,18 +265,13 @@ Capybara.add_selector(:radio_button) do
|
|
230
265
|
xpath
|
231
266
|
end
|
232
267
|
|
233
|
-
|
234
|
-
|
268
|
+
filter_set(:_field, [:id, :name, :checked, :unchecked, :disabled])
|
269
|
+
|
235
270
|
filter(:option) { |node, value| node.value == value.to_s }
|
236
|
-
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
237
271
|
|
238
272
|
describe do |options|
|
239
|
-
desc
|
273
|
+
desc = String.new
|
240
274
|
desc << " with value #{options[:option].inspect}" if options[:option]
|
241
|
-
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
|
242
|
-
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
|
243
|
-
states << 'disabled' if options[:disabled] == true
|
244
|
-
desc << " that is #{states.join(' and ')}" unless states.empty?
|
245
275
|
desc
|
246
276
|
end
|
247
277
|
end
|
@@ -253,18 +283,13 @@ Capybara.add_selector(:checkbox) do
|
|
253
283
|
xpath
|
254
284
|
end
|
255
285
|
|
256
|
-
|
257
|
-
|
286
|
+
filter_set(:_field, [:id, :name, :checked, :unchecked, :disabled])
|
287
|
+
|
258
288
|
filter(:option) { |node, value| node.value == value.to_s }
|
259
|
-
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
260
289
|
|
261
290
|
describe do |options|
|
262
|
-
desc
|
291
|
+
desc = String.new
|
263
292
|
desc << " with value #{options[:option].inspect}" if options[:option]
|
264
|
-
states << 'checked' if options[:checked] || (options.has_key?(:unchecked) && !options[:unchecked])
|
265
|
-
states << 'not checked' if options[:unchecked] || (options.has_key?(:checked) && !options[:checked])
|
266
|
-
states << 'disabled' if options[:disabled] == true
|
267
|
-
desc << " that is #{states.join(' and ')}" unless states.empty?
|
268
293
|
desc
|
269
294
|
end
|
270
295
|
end
|
@@ -277,6 +302,8 @@ Capybara.add_selector(:select) do
|
|
277
302
|
xpath
|
278
303
|
end
|
279
304
|
|
305
|
+
filter_set(:_field, [:id, :name, :placeholder, :disabled, :multiple])
|
306
|
+
|
280
307
|
filter(:options) do |node, options|
|
281
308
|
if node.visible?
|
282
309
|
actual = node.all(:xpath, './/option').map { |option| option.text }
|
@@ -296,17 +323,12 @@ Capybara.add_selector(:select) do
|
|
296
323
|
actual = node.all(:xpath, './/option', visible: false).select { |option| option.selected? }.map { |option| option.text(:all) }
|
297
324
|
[selected].flatten.sort == actual.sort
|
298
325
|
end
|
299
|
-
filter(:disabled, default: false, boolean: true, skip_if: :all) { |node, value| not(value ^ node.disabled?) }
|
300
|
-
filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
|
301
326
|
|
302
327
|
describe do |options|
|
303
328
|
desc = String.new
|
304
329
|
desc << " with options #{options[:options].inspect}" if options[:options]
|
305
330
|
desc << " with at least options #{options[:with_options].inspect}" if options[:with_options]
|
306
331
|
desc << " with #{options[:selected].inspect} selected" if options[:selected]
|
307
|
-
desc << " that is disabled" if options[:disabled] == true
|
308
|
-
desc << " that allows multiple selection" if options[:multiple] == true
|
309
|
-
desc << " that only allows single selection" if options[:multiple] === false
|
310
332
|
desc
|
311
333
|
end
|
312
334
|
end
|
@@ -337,16 +359,7 @@ Capybara.add_selector(:file_field) do
|
|
337
359
|
xpath
|
338
360
|
end
|
339
361
|
|
340
|
-
|
341
|
-
filter(:multiple, boolean: true) { |node, value| !(value ^ node[:multiple]) }
|
342
|
-
|
343
|
-
describe do |options|
|
344
|
-
desc = String.new
|
345
|
-
desc << " that is disabled" if options[:disabled] == true
|
346
|
-
desc << " that allows multiple files" if options[:multiple] == true
|
347
|
-
desc << " that only allows a single file" if options[:multiple] === false
|
348
|
-
desc
|
349
|
-
end
|
362
|
+
filter_set(:_field, [:id, :name, :disabled, :multiple])
|
350
363
|
end
|
351
364
|
|
352
365
|
Capybara.add_selector(:label) do
|
@@ -368,6 +381,12 @@ Capybara.add_selector(:label) do
|
|
368
381
|
node[:for] == field_or_value.to_s
|
369
382
|
end
|
370
383
|
end
|
384
|
+
|
385
|
+
describe do |options|
|
386
|
+
desc = String.new
|
387
|
+
desc << " for #{options[:for]}" if options[:for]
|
388
|
+
desc
|
389
|
+
end
|
371
390
|
end
|
372
391
|
|
373
392
|
Capybara.add_selector(:table) do
|
@@ -377,3 +396,11 @@ Capybara.add_selector(:table) do
|
|
377
396
|
xpath
|
378
397
|
end
|
379
398
|
end
|
399
|
+
|
400
|
+
Capybara.add_selector(:frame) do
|
401
|
+
xpath do |locator|
|
402
|
+
xpath = XPath.descendant(:iframe) + XPath.descendant(:frame)
|
403
|
+
xpath = xpath[XPath.attr(:id).equals(locator.to_s) | XPath.attr(:name).equals(locator)] unless locator.nil?
|
404
|
+
xpath
|
405
|
+
end
|
406
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'capybara/selector/filter'
|
3
|
+
|
4
|
+
module Capybara
|
5
|
+
class Selector
|
6
|
+
class FilterSet
|
7
|
+
attr_reader :descriptions
|
8
|
+
|
9
|
+
def initialize(name, &block)
|
10
|
+
@name = name
|
11
|
+
@descriptions = []
|
12
|
+
instance_eval(&block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def filter(name, options={}, &block)
|
16
|
+
filters[name] = Filter.new(name, block, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def describe(&block)
|
20
|
+
descriptions.push block
|
21
|
+
end
|
22
|
+
|
23
|
+
def description(options={})
|
24
|
+
@descriptions.map {|desc| desc.call(options).to_s }.join
|
25
|
+
end
|
26
|
+
|
27
|
+
def filters
|
28
|
+
@filters ||= {}
|
29
|
+
end
|
30
|
+
|
31
|
+
class << self
|
32
|
+
def all
|
33
|
+
@filter_sets ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def add(name, &block)
|
37
|
+
all[name.to_sym] = FilterSet.new(name.to_sym, &block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def remove(name)
|
41
|
+
all.delete(name.to_sym)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -11,6 +11,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
11
11
|
|
12
12
|
def browser
|
13
13
|
unless @browser
|
14
|
+
if options[:browser].to_s == "firefox"
|
15
|
+
options[:desired_capabilities] ||= Selenium::WebDriver::Remote::Capabilities.firefox
|
16
|
+
options[:desired_capabilities].merge!({ unexpectedAlertBehaviour: "ignore" })
|
17
|
+
end
|
18
|
+
|
14
19
|
@browser = Selenium::WebDriver.for(options[:browser], options.reject { |key,val| SPECIAL_OPTIONS.include?(key) })
|
15
20
|
|
16
21
|
main = Process.pid
|
@@ -130,29 +135,22 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
130
135
|
end
|
131
136
|
end
|
132
137
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
yield
|
150
|
-
ensure
|
151
|
-
# would love to use browser.switch_to.parent_frame here
|
152
|
-
# but it has an issue if the current frame is removed from within it
|
153
|
-
@frame_handles[browser.window_handle].pop
|
154
|
-
browser.switch_to.default_content
|
155
|
-
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
138
|
+
def switch_to_frame(frame)
|
139
|
+
case frame
|
140
|
+
when :top
|
141
|
+
@frame_handles[browser.window_handle] = []
|
142
|
+
browser.switch_to.default_content
|
143
|
+
when :parent
|
144
|
+
# would love to use browser.switch_to.parent_frame here
|
145
|
+
# but it has an issue if the current frame is removed from within it
|
146
|
+
@frame_handles[browser.window_handle].pop
|
147
|
+
browser.switch_to.default_content
|
148
|
+
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
149
|
+
else
|
150
|
+
@frame_handles[browser.window_handle] ||= []
|
151
|
+
@frame_handles[browser.window_handle] << frame.native
|
152
|
+
browser.switch_to.frame(frame.native)
|
153
|
+
end
|
156
154
|
end
|
157
155
|
|
158
156
|
def current_window_handle
|
@@ -221,6 +219,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
221
219
|
end
|
222
220
|
|
223
221
|
def accept_modal(type, options={}, &blk)
|
222
|
+
options = options.dup
|
224
223
|
yield if block_given?
|
225
224
|
modal = find_modal(options)
|
226
225
|
modal.send_keys options[:with] if options[:with]
|