capybara 2.0.3 → 2.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/History.md +73 -0
- data/README.md +52 -5
- data/lib/capybara.rb +44 -62
- data/lib/capybara/cucumber.rb +4 -1
- data/lib/capybara/driver/base.rb +13 -9
- data/lib/capybara/driver/node.rb +18 -6
- data/lib/capybara/helpers.rb +111 -22
- data/lib/capybara/node/actions.rb +24 -19
- data/lib/capybara/node/base.rb +25 -32
- data/lib/capybara/node/document.rb +6 -2
- data/lib/capybara/node/element.rb +45 -7
- data/lib/capybara/node/finders.rb +48 -21
- data/lib/capybara/node/matchers.rb +38 -21
- data/lib/capybara/node/simple.rb +29 -7
- data/lib/capybara/query.rb +72 -26
- data/lib/capybara/rack_test/browser.rb +11 -3
- data/lib/capybara/rack_test/css_handlers.rb +8 -0
- data/lib/capybara/rack_test/driver.rb +11 -3
- data/lib/capybara/rack_test/form.rb +8 -1
- data/lib/capybara/rack_test/node.rb +92 -36
- data/lib/capybara/rails.rb +1 -2
- data/lib/capybara/result.rb +21 -37
- data/lib/capybara/rspec/matchers.rb +60 -31
- data/lib/capybara/selector.rb +46 -13
- data/lib/capybara/selenium/driver.rb +42 -6
- data/lib/capybara/selenium/node.rb +23 -5
- data/lib/capybara/session.rb +46 -11
- data/lib/capybara/spec/public/test.js +12 -0
- data/lib/capybara/spec/session/all_spec.rb +9 -8
- data/lib/capybara/spec/session/attach_file_spec.rb +14 -0
- data/lib/capybara/spec/session/check_spec.rb +14 -0
- data/lib/capybara/spec/session/choose_spec.rb +14 -0
- data/lib/capybara/spec/session/click_button_spec.rb +77 -1
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +65 -0
- data/lib/capybara/spec/session/click_link_spec.rb +24 -0
- data/lib/capybara/spec/session/current_scope_spec.rb +29 -0
- data/lib/capybara/spec/session/fill_in_spec.rb +14 -0
- data/lib/capybara/spec/session/find_button_spec.rb +12 -0
- data/lib/capybara/spec/session/find_by_id_spec.rb +12 -1
- data/lib/capybara/spec/session/find_field_spec.rb +30 -0
- data/lib/capybara/spec/session/find_link_spec.rb +12 -0
- data/lib/capybara/spec/session/find_spec.rb +258 -16
- data/lib/capybara/spec/session/first_spec.rb +25 -8
- data/lib/capybara/spec/session/has_css_spec.rb +2 -2
- data/lib/capybara/spec/session/has_field_spec.rb +10 -2
- data/lib/capybara/spec/session/has_selector_spec.rb +9 -0
- data/lib/capybara/spec/session/has_text_spec.rb +96 -0
- data/lib/capybara/spec/session/has_title_spec.rb +47 -0
- data/lib/capybara/spec/session/node_spec.rb +43 -0
- data/lib/capybara/spec/session/reset_session_spec.rb +10 -2
- data/lib/capybara/spec/session/save_page_spec.rb +30 -0
- data/lib/capybara/spec/session/select_spec.rb +65 -0
- data/lib/capybara/spec/session/text_spec.rb +31 -0
- data/lib/capybara/spec/session/title_spec.rb +16 -0
- data/lib/capybara/spec/session/uncheck_spec.rb +14 -0
- data/lib/capybara/spec/session/unselect_spec.rb +42 -0
- data/lib/capybara/spec/session/visit_spec.rb +3 -3
- data/lib/capybara/spec/session/within_frame_spec.rb +14 -0
- data/lib/capybara/spec/session/within_spec.rb +3 -3
- data/lib/capybara/spec/spec_helper.rb +6 -1
- data/lib/capybara/spec/views/form.erb +39 -2
- data/lib/capybara/spec/views/frame_child.erb +9 -0
- data/lib/capybara/spec/views/frame_parent.erb +8 -0
- data/lib/capybara/spec/views/with_base_tag.erb +10 -0
- data/lib/capybara/spec/views/with_count.erb +7 -0
- data/lib/capybara/spec/views/with_hover.erb +17 -0
- data/lib/capybara/spec/views/with_html.erb +21 -2
- data/lib/capybara/spec/views/with_js.erb +5 -0
- data/lib/capybara/spec/views/with_scope.erb +6 -1
- data/lib/capybara/spec/views/with_title.erb +1 -0
- data/lib/capybara/spec/views/within_frames.erb +1 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/basic_node_spec.rb +75 -24
- data/spec/dsl_spec.rb +2 -1
- data/spec/rack_test_spec.rb +4 -3
- data/spec/rspec/matchers_spec.rb +105 -17
- data/spec/server_spec.rb +8 -8
- data/spec/spec_helper.rb +2 -1
- metadata +83 -23
- metadata.gz.sig +0 -0
data/lib/capybara/rails.rb
CHANGED
@@ -3,7 +3,7 @@ require 'capybara/dsl'
|
|
3
3
|
|
4
4
|
Capybara.app = Rack::Builder.new do
|
5
5
|
map "/" do
|
6
|
-
if
|
6
|
+
if Rails.version.to_f >= 3.0
|
7
7
|
run Rails.application
|
8
8
|
else # Rails 2
|
9
9
|
use Rails::Rack::Static
|
@@ -12,7 +12,6 @@ Capybara.app = Rack::Builder.new do
|
|
12
12
|
end
|
13
13
|
end.to_app
|
14
14
|
|
15
|
-
Capybara.asset_root = Rails.root.join('public')
|
16
15
|
Capybara.save_and_open_page_path = Rails.root.join('tmp/capybara')
|
17
16
|
|
18
17
|
# Override default rack_test driver to respect data-method attributes.
|
data/lib/capybara/result.rb
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
|
3
3
|
module Capybara
|
4
|
+
|
5
|
+
##
|
6
|
+
# A {Capybara::Result} represents a collection of {Capybara::Element} on the page. It is possible to interact with this
|
7
|
+
# collection similar to an Array because it implements Enumerable and offers the following Array methods through delegation:
|
8
|
+
#
|
9
|
+
# * []
|
10
|
+
# * each()
|
11
|
+
# * at()
|
12
|
+
# * size()
|
13
|
+
# * count()
|
14
|
+
# * length()
|
15
|
+
# * first()
|
16
|
+
# * last()
|
17
|
+
# * empty?()
|
18
|
+
#
|
19
|
+
# @see Capybara::Element
|
20
|
+
#
|
4
21
|
class Result
|
5
22
|
include Enumerable
|
6
23
|
extend Forwardable
|
@@ -15,36 +32,13 @@ module Capybara
|
|
15
32
|
def_delegators :@result, :each, :[], :at, :size, :count, :length, :first, :last, :empty?
|
16
33
|
|
17
34
|
def matches_count?
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
def find!
|
22
|
-
raise find_error if @result.size != 1
|
23
|
-
@result.first
|
24
|
-
end
|
25
|
-
|
26
|
-
def find_error
|
27
|
-
if @result.size == 0
|
28
|
-
Capybara::ElementNotFound.new("Unable to find #{@query.description}")
|
29
|
-
elsif @result.size > 1
|
30
|
-
Capybara::Ambiguous.new("Ambiguous match, found #{size} elements matching #{@query.description}")
|
31
|
-
end
|
35
|
+
Capybara::Helpers.matches_count?(@result.size, @query.options)
|
32
36
|
end
|
33
37
|
|
34
38
|
def failure_message
|
35
|
-
message =
|
36
|
-
"expected #{@query.description} to be found #{@query.options[:count]} #{declension("time", "times", @query.options[:count])}"
|
37
|
-
elsif @query.options[:between]
|
38
|
-
"expected #{@query.description} to be found between #{@query.options[:between].first} and #{@query.options[:between].last} times"
|
39
|
-
elsif @query.options[:maximum]
|
40
|
-
"expected #{@query.description} to be found at most #{@query.options[:maximum]} #{declension("time", "times", @query.options[:maximum])}"
|
41
|
-
elsif @query.options[:minimum]
|
42
|
-
"expected #{@query.description} to be found at least #{@query.options[:minimum]} #{declension("time", "times", @query.options[:minimum])}"
|
43
|
-
else
|
44
|
-
"expected to find #{@query.description}"
|
45
|
-
end
|
39
|
+
message = Capybara::Helpers.failure_message(@query.description, @query.options)
|
46
40
|
if count > 0
|
47
|
-
message << ", found #{count} #{declension("match", "matches")}: " << @result.map(&:text).map(&:inspect).join(", ")
|
41
|
+
message << ", found #{count} #{Capybara::Helpers.declension("match", "matches", count)}: " << @result.map(&:text).map(&:inspect).join(", ")
|
48
42
|
else
|
49
43
|
message << " but there were no matches"
|
50
44
|
end
|
@@ -56,17 +50,7 @@ module Capybara
|
|
56
50
|
end
|
57
51
|
|
58
52
|
def negative_failure_message
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
private
|
63
|
-
|
64
|
-
def declension(singular, plural, count=count)
|
65
|
-
if count == 1
|
66
|
-
singular
|
67
|
-
else
|
68
|
-
plural
|
69
|
-
end
|
53
|
+
failure_message.sub(/(to be found|to find)/, 'not \1')
|
70
54
|
end
|
71
55
|
end
|
72
56
|
end
|
@@ -1,6 +1,16 @@
|
|
1
1
|
module Capybara
|
2
2
|
module RSpecMatchers
|
3
|
-
class
|
3
|
+
class Matcher
|
4
|
+
def wrap(actual)
|
5
|
+
if actual.respond_to?("has_selector?")
|
6
|
+
actual
|
7
|
+
else
|
8
|
+
Capybara.string(actual.to_s)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class HaveSelector < Matcher
|
4
14
|
def initialize(*args)
|
5
15
|
@args = args
|
6
16
|
end
|
@@ -17,59 +27,77 @@ module Capybara
|
|
17
27
|
"have #{query.description}"
|
18
28
|
end
|
19
29
|
|
20
|
-
def wrap(actual)
|
21
|
-
if actual.respond_to?("has_selector?")
|
22
|
-
actual
|
23
|
-
else
|
24
|
-
Capybara.string(actual.to_s)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
30
|
def query
|
29
31
|
@query ||= Capybara::Query.new(*@args)
|
30
32
|
end
|
31
33
|
end
|
32
34
|
|
33
|
-
class HaveText
|
34
|
-
attr_reader :
|
35
|
+
class HaveText < Matcher
|
36
|
+
attr_reader :type, :content, :options
|
35
37
|
|
36
|
-
def initialize(
|
37
|
-
@
|
38
|
+
def initialize(*args)
|
39
|
+
@type = args.shift if args.first.is_a?(Symbol)
|
40
|
+
@content = args.shift
|
41
|
+
@options = (args.first.is_a?(Hash))? args.first : {}
|
38
42
|
end
|
39
43
|
|
40
44
|
def matches?(actual)
|
41
45
|
@actual = wrap(actual)
|
42
|
-
@actual.has_text?(
|
46
|
+
@actual.has_text?(type, content, options)
|
43
47
|
end
|
44
48
|
|
45
49
|
def does_not_match?(actual)
|
46
50
|
@actual = wrap(actual)
|
47
|
-
@actual.has_no_text?(
|
51
|
+
@actual.has_no_text?(type, content, options)
|
48
52
|
end
|
49
53
|
|
50
54
|
def failure_message_for_should
|
51
|
-
|
55
|
+
message = Capybara::Helpers.failure_message(description, options)
|
56
|
+
message << " in #{format(@actual.text(type))}"
|
57
|
+
message
|
52
58
|
end
|
53
59
|
|
54
60
|
def failure_message_for_should_not
|
55
|
-
|
61
|
+
failure_message_for_should.sub(/(to find)/, 'not \1')
|
56
62
|
end
|
57
63
|
|
58
64
|
def description
|
59
|
-
"
|
65
|
+
"text #{format(content)}"
|
60
66
|
end
|
61
67
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
+
def format(content)
|
69
|
+
content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
|
70
|
+
content.inspect
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class HaveTitle < Matcher
|
75
|
+
attr_reader :title
|
76
|
+
|
77
|
+
def initialize(title)
|
78
|
+
@title = title
|
68
79
|
end
|
69
80
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
81
|
+
def matches?(actual)
|
82
|
+
@actual = wrap(actual)
|
83
|
+
@actual.has_title?(title)
|
84
|
+
end
|
85
|
+
|
86
|
+
def does_not_match?(actual)
|
87
|
+
@actual = wrap(actual)
|
88
|
+
@actual.has_no_title?(title)
|
89
|
+
end
|
90
|
+
|
91
|
+
def failure_message_for_should
|
92
|
+
"expected there to be title #{title.inspect} in #{@actual.title.inspect}"
|
93
|
+
end
|
94
|
+
|
95
|
+
def failure_message_for_should_not
|
96
|
+
"expected there not to be title #{title.inspect} in #{@actual.title.inspect}"
|
97
|
+
end
|
98
|
+
|
99
|
+
def description
|
100
|
+
"have title #{title.inspect}"
|
73
101
|
end
|
74
102
|
end
|
75
103
|
|
@@ -85,12 +113,13 @@ module Capybara
|
|
85
113
|
HaveSelector.new(:css, css, options)
|
86
114
|
end
|
87
115
|
|
88
|
-
def
|
89
|
-
HaveText.new(
|
116
|
+
def have_text(*args)
|
117
|
+
HaveText.new(*args)
|
90
118
|
end
|
119
|
+
alias_method :have_content, :have_text
|
91
120
|
|
92
|
-
def
|
93
|
-
|
121
|
+
def have_title(title)
|
122
|
+
HaveTitle.new(title)
|
94
123
|
end
|
95
124
|
|
96
125
|
def have_link(locator, options={})
|
data/lib/capybara/selector.rb
CHANGED
@@ -1,7 +1,26 @@
|
|
1
1
|
module Capybara
|
2
2
|
class Selector
|
3
|
-
|
3
|
+
class Filter
|
4
|
+
def initialize(name, block, options={})
|
5
|
+
@name = name
|
6
|
+
@block = block
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
def default?
|
11
|
+
@options.has_key?(:default)
|
12
|
+
end
|
13
|
+
|
14
|
+
def default
|
15
|
+
@options[:default]
|
16
|
+
end
|
17
|
+
|
18
|
+
def matches?(node, value)
|
19
|
+
@block.call(node, value)
|
20
|
+
end
|
21
|
+
end
|
4
22
|
|
23
|
+
attr_reader :name, :custom_filters, :format
|
5
24
|
|
6
25
|
class << self
|
7
26
|
def all
|
@@ -27,16 +46,16 @@ module Capybara
|
|
27
46
|
end
|
28
47
|
|
29
48
|
def xpath(&block)
|
49
|
+
@format = :xpath
|
30
50
|
@xpath = block if block
|
31
51
|
@xpath
|
32
52
|
end
|
33
53
|
|
34
54
|
# Same as xpath, but wrap in XPath.css().
|
35
55
|
def css(&block)
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
@xpath
|
56
|
+
@format = :css
|
57
|
+
@css = block if block
|
58
|
+
@css
|
40
59
|
end
|
41
60
|
|
42
61
|
def match(&block)
|
@@ -50,15 +69,19 @@ module Capybara
|
|
50
69
|
end
|
51
70
|
|
52
71
|
def call(locator)
|
53
|
-
@
|
72
|
+
if @format==:css
|
73
|
+
@css.call(locator)
|
74
|
+
else
|
75
|
+
@xpath.call(locator)
|
76
|
+
end
|
54
77
|
end
|
55
78
|
|
56
79
|
def match?(locator)
|
57
80
|
@match and @match.call(locator)
|
58
81
|
end
|
59
82
|
|
60
|
-
def filter(name, &block)
|
61
|
-
@custom_filters[name] = block
|
83
|
+
def filter(name, options={}, &block)
|
84
|
+
@custom_filters[name] = Filter.new(name, block, options)
|
62
85
|
end
|
63
86
|
end
|
64
87
|
end
|
@@ -79,8 +102,15 @@ Capybara.add_selector(:field) do
|
|
79
102
|
xpath { |locator| XPath::HTML.field(locator) }
|
80
103
|
filter(:checked) { |node, value| not(value ^ node.checked?) }
|
81
104
|
filter(:unchecked) { |node, value| (value ^ node.checked?) }
|
105
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
82
106
|
filter(:with) { |node, with| node.value == with }
|
83
|
-
filter(:type)
|
107
|
+
filter(:type) do |node, type|
|
108
|
+
if ['textarea', 'select'].include?(type)
|
109
|
+
node.tag_name == type
|
110
|
+
else
|
111
|
+
node[:type] == type
|
112
|
+
end
|
113
|
+
end
|
84
114
|
end
|
85
115
|
|
86
116
|
Capybara.add_selector(:fieldset) do
|
@@ -90,6 +120,7 @@ end
|
|
90
120
|
Capybara.add_selector(:link_or_button) do
|
91
121
|
label "link or button"
|
92
122
|
xpath { |locator| XPath::HTML.link_or_button(locator) }
|
123
|
+
filter(:disabled, :default => false) { |node, value| node.tag_name == "a" or not(value ^ node.disabled?) }
|
93
124
|
end
|
94
125
|
|
95
126
|
Capybara.add_selector(:link) do
|
@@ -101,11 +132,13 @@ end
|
|
101
132
|
|
102
133
|
Capybara.add_selector(:button) do
|
103
134
|
xpath { |locator| XPath::HTML.button(locator) }
|
135
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
104
136
|
end
|
105
137
|
|
106
138
|
Capybara.add_selector(:fillable_field) do
|
107
139
|
label "field"
|
108
140
|
xpath { |locator| XPath::HTML.fillable_field(locator) }
|
141
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
109
142
|
end
|
110
143
|
|
111
144
|
Capybara.add_selector(:radio_button) do
|
@@ -113,12 +146,14 @@ Capybara.add_selector(:radio_button) do
|
|
113
146
|
xpath { |locator| XPath::HTML.radio_button(locator) }
|
114
147
|
filter(:checked) { |node, value| not(value ^ node.checked?) }
|
115
148
|
filter(:unchecked) { |node, value| (value ^ node.checked?) }
|
149
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
116
150
|
end
|
117
151
|
|
118
152
|
Capybara.add_selector(:checkbox) do
|
119
153
|
xpath { |locator| XPath::HTML.checkbox(locator) }
|
120
154
|
filter(:checked) { |node, value| not(value ^ node.checked?) }
|
121
155
|
filter(:unchecked) { |node, value| (value ^ node.checked?) }
|
156
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
122
157
|
end
|
123
158
|
|
124
159
|
Capybara.add_selector(:select) do
|
@@ -133,6 +168,7 @@ Capybara.add_selector(:select) do
|
|
133
168
|
actual = node.all(:xpath, './/option').select { |option| option.selected? }.map { |option| option.text }
|
134
169
|
[selected].flatten.sort == actual.sort
|
135
170
|
end
|
171
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
136
172
|
end
|
137
173
|
|
138
174
|
Capybara.add_selector(:option) do
|
@@ -142,10 +178,7 @@ end
|
|
142
178
|
Capybara.add_selector(:file_field) do
|
143
179
|
label "file field"
|
144
180
|
xpath { |locator| XPath::HTML.file_field(locator) }
|
145
|
-
|
146
|
-
|
147
|
-
Capybara.add_selector(:content) do
|
148
|
-
xpath { |content| XPath::HTML.content(content) }
|
181
|
+
filter(:disabled, :default => false) { |node, value| not(value ^ node.disabled?) }
|
149
182
|
end
|
150
183
|
|
151
184
|
Capybara.add_selector(:table) do
|
@@ -1,4 +1,13 @@
|
|
1
|
-
|
1
|
+
begin
|
2
|
+
require 'selenium-webdriver'
|
3
|
+
rescue LoadError => e
|
4
|
+
if e.message =~ /selenium-webdriver/
|
5
|
+
raise LoadError, "Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler."
|
6
|
+
else
|
7
|
+
raise e
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
2
11
|
|
3
12
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
4
13
|
DEFAULT_OPTIONS = {
|
@@ -27,6 +36,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
27
36
|
@app = app
|
28
37
|
@browser = nil
|
29
38
|
@exit_status = nil
|
39
|
+
@frame_handles = {}
|
30
40
|
@options = DEFAULT_OPTIONS.merge(options)
|
31
41
|
end
|
32
42
|
|
@@ -38,14 +48,22 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
38
48
|
browser.page_source
|
39
49
|
end
|
40
50
|
|
51
|
+
def title
|
52
|
+
browser.title
|
53
|
+
end
|
54
|
+
|
41
55
|
def current_url
|
42
56
|
browser.current_url
|
43
57
|
end
|
44
58
|
|
45
|
-
def
|
59
|
+
def find_xpath(selector)
|
46
60
|
browser.find_elements(:xpath, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
|
47
61
|
end
|
48
62
|
|
63
|
+
def find_css(selector)
|
64
|
+
browser.find_elements(:css, selector).map { |node| Capybara::Selenium::Node.new(self, node) }
|
65
|
+
end
|
66
|
+
|
49
67
|
def wait?; true; end
|
50
68
|
def needs_server?; true; end
|
51
69
|
|
@@ -74,12 +92,29 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
74
92
|
end
|
75
93
|
end
|
76
94
|
|
77
|
-
|
78
|
-
|
79
|
-
|
95
|
+
##
|
96
|
+
#
|
97
|
+
# Webdriver supports frame name, id, index(zero-based) or {Capybara::Element} to find iframe
|
98
|
+
#
|
99
|
+
# @overload within_frame(index)
|
100
|
+
# @param [Integer] index index of a frame
|
101
|
+
# @overload within_frame(name_or_id)
|
102
|
+
# @param [String] name_or_id name or id of a frame
|
103
|
+
# @overload within_frame(element)
|
104
|
+
# @param [Capybara::Node::Base] a_node frame element
|
105
|
+
#
|
106
|
+
def within_frame(frame_handle)
|
107
|
+
@frame_handles[browser.window_handle] ||= []
|
108
|
+
frame_handle = frame_handle.native if frame_handle.is_a?(Capybara::Node::Base)
|
109
|
+
@frame_handles[browser.window_handle] << frame_handle
|
110
|
+
a=browser.switch_to.frame(frame_handle)
|
80
111
|
yield
|
81
112
|
ensure
|
82
|
-
|
113
|
+
# There doesnt appear to be any way in Webdriver to move back to a parent frame
|
114
|
+
# other than going back to the root and then reiterating down
|
115
|
+
@frame_handles[browser.window_handle].pop
|
116
|
+
browser.switch_to.default_content
|
117
|
+
@frame_handles[browser.window_handle].each { |fh| browser.switch_to.frame(fh) }
|
83
118
|
end
|
84
119
|
|
85
120
|
def find_window( selector )
|
@@ -111,4 +146,5 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
111
146
|
def invalid_element_errors
|
112
147
|
[Selenium::WebDriver::Error::StaleElementReferenceError, Selenium::WebDriver::Error::UnhandledError, Selenium::WebDriver::Error::ElementNotVisibleError]
|
113
148
|
end
|
149
|
+
|
114
150
|
end
|