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.
Files changed (81) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.md +73 -0
  3. data/README.md +52 -5
  4. data/lib/capybara.rb +44 -62
  5. data/lib/capybara/cucumber.rb +4 -1
  6. data/lib/capybara/driver/base.rb +13 -9
  7. data/lib/capybara/driver/node.rb +18 -6
  8. data/lib/capybara/helpers.rb +111 -22
  9. data/lib/capybara/node/actions.rb +24 -19
  10. data/lib/capybara/node/base.rb +25 -32
  11. data/lib/capybara/node/document.rb +6 -2
  12. data/lib/capybara/node/element.rb +45 -7
  13. data/lib/capybara/node/finders.rb +48 -21
  14. data/lib/capybara/node/matchers.rb +38 -21
  15. data/lib/capybara/node/simple.rb +29 -7
  16. data/lib/capybara/query.rb +72 -26
  17. data/lib/capybara/rack_test/browser.rb +11 -3
  18. data/lib/capybara/rack_test/css_handlers.rb +8 -0
  19. data/lib/capybara/rack_test/driver.rb +11 -3
  20. data/lib/capybara/rack_test/form.rb +8 -1
  21. data/lib/capybara/rack_test/node.rb +92 -36
  22. data/lib/capybara/rails.rb +1 -2
  23. data/lib/capybara/result.rb +21 -37
  24. data/lib/capybara/rspec/matchers.rb +60 -31
  25. data/lib/capybara/selector.rb +46 -13
  26. data/lib/capybara/selenium/driver.rb +42 -6
  27. data/lib/capybara/selenium/node.rb +23 -5
  28. data/lib/capybara/session.rb +46 -11
  29. data/lib/capybara/spec/public/test.js +12 -0
  30. data/lib/capybara/spec/session/all_spec.rb +9 -8
  31. data/lib/capybara/spec/session/attach_file_spec.rb +14 -0
  32. data/lib/capybara/spec/session/check_spec.rb +14 -0
  33. data/lib/capybara/spec/session/choose_spec.rb +14 -0
  34. data/lib/capybara/spec/session/click_button_spec.rb +77 -1
  35. data/lib/capybara/spec/session/click_link_or_button_spec.rb +65 -0
  36. data/lib/capybara/spec/session/click_link_spec.rb +24 -0
  37. data/lib/capybara/spec/session/current_scope_spec.rb +29 -0
  38. data/lib/capybara/spec/session/fill_in_spec.rb +14 -0
  39. data/lib/capybara/spec/session/find_button_spec.rb +12 -0
  40. data/lib/capybara/spec/session/find_by_id_spec.rb +12 -1
  41. data/lib/capybara/spec/session/find_field_spec.rb +30 -0
  42. data/lib/capybara/spec/session/find_link_spec.rb +12 -0
  43. data/lib/capybara/spec/session/find_spec.rb +258 -16
  44. data/lib/capybara/spec/session/first_spec.rb +25 -8
  45. data/lib/capybara/spec/session/has_css_spec.rb +2 -2
  46. data/lib/capybara/spec/session/has_field_spec.rb +10 -2
  47. data/lib/capybara/spec/session/has_selector_spec.rb +9 -0
  48. data/lib/capybara/spec/session/has_text_spec.rb +96 -0
  49. data/lib/capybara/spec/session/has_title_spec.rb +47 -0
  50. data/lib/capybara/spec/session/node_spec.rb +43 -0
  51. data/lib/capybara/spec/session/reset_session_spec.rb +10 -2
  52. data/lib/capybara/spec/session/save_page_spec.rb +30 -0
  53. data/lib/capybara/spec/session/select_spec.rb +65 -0
  54. data/lib/capybara/spec/session/text_spec.rb +31 -0
  55. data/lib/capybara/spec/session/title_spec.rb +16 -0
  56. data/lib/capybara/spec/session/uncheck_spec.rb +14 -0
  57. data/lib/capybara/spec/session/unselect_spec.rb +42 -0
  58. data/lib/capybara/spec/session/visit_spec.rb +3 -3
  59. data/lib/capybara/spec/session/within_frame_spec.rb +14 -0
  60. data/lib/capybara/spec/session/within_spec.rb +3 -3
  61. data/lib/capybara/spec/spec_helper.rb +6 -1
  62. data/lib/capybara/spec/views/form.erb +39 -2
  63. data/lib/capybara/spec/views/frame_child.erb +9 -0
  64. data/lib/capybara/spec/views/frame_parent.erb +8 -0
  65. data/lib/capybara/spec/views/with_base_tag.erb +10 -0
  66. data/lib/capybara/spec/views/with_count.erb +7 -0
  67. data/lib/capybara/spec/views/with_hover.erb +17 -0
  68. data/lib/capybara/spec/views/with_html.erb +21 -2
  69. data/lib/capybara/spec/views/with_js.erb +5 -0
  70. data/lib/capybara/spec/views/with_scope.erb +6 -1
  71. data/lib/capybara/spec/views/with_title.erb +1 -0
  72. data/lib/capybara/spec/views/within_frames.erb +1 -0
  73. data/lib/capybara/version.rb +1 -1
  74. data/spec/basic_node_spec.rb +75 -24
  75. data/spec/dsl_spec.rb +2 -1
  76. data/spec/rack_test_spec.rb +4 -3
  77. data/spec/rspec/matchers_spec.rb +105 -17
  78. data/spec/server_spec.rb +8 -8
  79. data/spec/spec_helper.rb +2 -1
  80. metadata +83 -23
  81. metadata.gz.sig +0 -0
@@ -66,6 +66,17 @@ Capybara::SpecHelper.spec '#click_link' do
66
66
  end
67
67
  end
68
68
 
69
+ context "with :href option given" do
70
+ it "should find links with valid href" do
71
+ @session.click_link('labore', :href => '/with_simple_html')
72
+ @session.should have_content('Bar')
73
+ end
74
+
75
+ it "should raise error if link wasn't found" do
76
+ expect { @session.click_link('labore', :href => 'invalid_href') }.to raise_error(Capybara::ElementNotFound)
77
+ end
78
+ end
79
+
69
80
  it "should follow relative links" do
70
81
  @session.visit('/')
71
82
  @session.click_link('Relative')
@@ -116,4 +127,17 @@ Capybara::SpecHelper.spec '#click_link' do
116
127
  @session.click_link('No Href')
117
128
  end.to raise_error(Capybara::ElementNotFound)
118
129
  end
130
+
131
+ context "with :exact option" do
132
+ it "should accept partial matches when false" do
133
+ @session.click_link('abo', :exact => false)
134
+ @session.should have_content('Bar')
135
+ end
136
+
137
+ it "should not accept partial matches when true" do
138
+ expect do
139
+ @session.click_link('abo', :exact => true)
140
+ end.to raise_error(Capybara::ElementNotFound)
141
+ end
142
+ end
119
143
  end
@@ -0,0 +1,29 @@
1
+ Capybara::SpecHelper.spec '#current_scope' do
2
+ before do
3
+ @session.visit('/with_scope')
4
+ end
5
+
6
+ context "when not in a #within block" do
7
+ it "should return the document" do
8
+ @session.current_scope.should be_kind_of Capybara::Node::Document
9
+ end
10
+ end
11
+
12
+ context "when in a #within block" do
13
+ it "should return the element in scope" do
14
+ @session.within(:css, "#simple_first_name") do
15
+ @session.current_scope[:name].should eq 'first_name'
16
+ end
17
+ end
18
+ end
19
+
20
+ context "when in a nested #within block" do
21
+ it "should return the element in scope" do
22
+ @session.within("//div[@id='for_bar']") do
23
+ @session.within(".//input[@value='Peter']") do
24
+ @session.current_scope[:name].should eq 'form[first_name]'
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -138,4 +138,18 @@ Capybara::SpecHelper.spec "#fill_in" do
138
138
  end.to raise_error(Capybara::ElementNotFound)
139
139
  end
140
140
  end
141
+
142
+ context "with :exact option" do
143
+ it "should accept partial matches when false" do
144
+ @session.fill_in("Explanation", :with => "Dude", :exact => false)
145
+ @session.click_button("awesome")
146
+ extract_results(@session)["name_explanation"].should == "Dude"
147
+ end
148
+
149
+ it "should not accept partial matches when true" do
150
+ expect do
151
+ @session.fill_in("Explanation", :with => "Dude", :exact => true)
152
+ end.to raise_error(Capybara::ElementNotFound)
153
+ end
154
+ end
141
155
  end
@@ -17,4 +17,16 @@ Capybara::SpecHelper.spec '#find_button' do
17
17
  @session.find_button('Does not exist')
18
18
  end.to raise_error(Capybara::ElementNotFound)
19
19
  end
20
+
21
+ context "with :exact option" do
22
+ it "should accept partial matches when false" do
23
+ @session.find_button('What an Awesome', :exact => false)[:value].should == "awesome"
24
+ end
25
+
26
+ it "should not accept partial matches when true" do
27
+ expect do
28
+ @session.find_button('What an Awesome', :exact => true)
29
+ end.to raise_error(Capybara::ElementNotFound)
30
+ end
31
+ end
20
32
  end
@@ -5,7 +5,6 @@ Capybara::SpecHelper.spec '#find_by_id' do
5
5
 
6
6
  it "should find any element by id" do
7
7
  @session.find_by_id('red').tag_name.should == 'a'
8
- @session.find_by_id('hidden_via_ancestor').tag_name.should == 'div'
9
8
  end
10
9
 
11
10
  it "casts to string" do
@@ -17,4 +16,16 @@ Capybara::SpecHelper.spec '#find_by_id' do
17
16
  @session.find_by_id('nothing_with_this_id')
18
17
  end.to raise_error(Capybara::ElementNotFound)
19
18
  end
19
+
20
+ context "with :visible option" do
21
+ it "finds invisible elements when `false`" do
22
+ @session.find_by_id("hidden_via_ancestor", :visible => false).text(:all).should =~ /with hidden ancestor/
23
+ end
24
+
25
+ it "finds invisible elements when `false`" do
26
+ expect do
27
+ @session.find_by_id("hidden_via_ancestor", :visible => true)
28
+ end.to raise_error(Capybara::ElementNotFound)
29
+ end
30
+ end
20
31
  end
@@ -25,4 +25,34 @@ Capybara::SpecHelper.spec '#find_field' do
25
25
  @session.field_labeled('Does not exist')
26
26
  end.to raise_error(Capybara::ElementNotFound)
27
27
  end
28
+
29
+ context "with :exact option" do
30
+ it "should accept partial matches when false" do
31
+ @session.find_field("Explanation", :exact => false)[:name].should == "form[name_explanation]"
32
+ end
33
+
34
+ it "should not accept partial matches when true" do
35
+ expect do
36
+ @session.find_field("Explanation", :exact => true)
37
+ end.to raise_error(Capybara::ElementNotFound)
38
+ end
39
+ end
40
+
41
+ context "with :disabled option" do
42
+ it "should find disabled fields when true" do
43
+ @session.find_field("Disabled Checkbox", :disabled => true)[:name].should == "form[disabled_checkbox]"
44
+ end
45
+
46
+ it "should not find disabled fields when false" do
47
+ expect do
48
+ @session.find_field("Disabled Checkbox", :disabled => false)
49
+ end.to raise_error(Capybara::ElementNotFound)
50
+ end
51
+
52
+ it "should not find disabled fields by default" do
53
+ expect do
54
+ @session.find_field("Disabled Checkbox")
55
+ end.to raise_error(Capybara::ElementNotFound)
56
+ end
57
+ end
28
58
  end
@@ -17,4 +17,16 @@ Capybara::SpecHelper.spec '#find_link' do
17
17
  @session.find_link('Does not exist')
18
18
  end.to raise_error(Capybara::ElementNotFound)
19
19
  end
20
+
21
+ context "with :exact option" do
22
+ it "should accept partial matches when false" do
23
+ @session.find_link('abo', :exact => false).text.should == "labore"
24
+ end
25
+
26
+ it "should not accept partial matches when true" do
27
+ expect do
28
+ @session.find_link('abo', :exact => true)
29
+ end.to raise_error(Capybara::ElementNotFound)
30
+ end
31
+ end
20
32
  end
@@ -27,6 +27,30 @@ Capybara::SpecHelper.spec '#find' do
27
27
  @session.find(:css, "a#has-been-clicked").text.should include('Has been clicked')
28
28
  end
29
29
 
30
+ context "with :wait option", :requires => [:js] do
31
+ it "should not wait for asynchronous load when `false` given" do
32
+ @session.visit('/with_js')
33
+ @session.click_link('Click me')
34
+ expect do
35
+ @session.find(:css, "a#has-been-clicked", :wait => false)
36
+ end.to raise_error(Capybara::ElementNotFound)
37
+ end
38
+
39
+ it "should not find element if it appears after given wait duration" do
40
+ @session.visit('/with_js')
41
+ @session.click_link('Slowly')
42
+ expect do
43
+ @session.find(:css, "a#slow-clicked", :wait => 0.2)
44
+ end.to raise_error(Capybara::ElementNotFound)
45
+ end
46
+
47
+ it "should find element if it appears before given wait duration" do
48
+ @session.visit('/with_js')
49
+ @session.click_link('Click me')
50
+ @session.find(:css, "a#has-been-clicked", :wait => 0.9).text.should include('Has been clicked')
51
+ end
52
+ end
53
+
30
54
  context "with frozen time", :requires => [:js] do
31
55
  it "raises an error suggesting that Capybara is stuck in time" do
32
56
  @session.visit('/with_js')
@@ -41,6 +65,10 @@ Capybara::SpecHelper.spec '#find' do
41
65
  @session.find(:css, 'h1').text.should == 'This is a test'
42
66
  @session.find(:css, "input[id='test_field']")[:value].should == 'monkey'
43
67
  end
68
+
69
+ it "should support pseudo selectors" do
70
+ @session.find(:css, 'input:disabled').value.should == 'This is disabled'
71
+ end
44
72
  end
45
73
 
46
74
  context "with xpath selectors" do
@@ -52,43 +80,72 @@ Capybara::SpecHelper.spec '#find' do
52
80
 
53
81
  context "with custom selector" do
54
82
  it "should use the custom selector" do
55
- Capybara.add_selector(:monkey) do
56
- xpath { |name| ".//*[@id='#{name}_monkey']" }
83
+ Capybara.add_selector(:beatle) do
84
+ xpath { |name| ".//*[@id='#{name}']" }
57
85
  end
58
- @session.find(:monkey, 'john').text.should == 'Monkey John'
59
- @session.find(:monkey, 'paul').text.should == 'Monkey Paul'
86
+ @session.find(:beatle, 'john').text.should == 'John'
87
+ @session.find(:beatle, 'paul').text.should == 'Paul'
60
88
  end
61
89
  end
62
90
 
63
91
  context "with custom selector with :for option" do
64
92
  it "should use the selector when it matches the :for option" do
65
- Capybara.add_selector(:monkey) do
66
- xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
93
+ Capybara.add_selector(:beatle) do
94
+ xpath { |num| ".//*[contains(@class, 'beatle')][#{num}]" }
67
95
  match { |value| value.is_a?(Fixnum) }
68
96
  end
69
- @session.find(:monkey, '2').text.should == 'Monkey Paul'
70
- @session.find(1).text.should == 'Monkey John'
71
- @session.find(2).text.should == 'Monkey Paul'
97
+ @session.find(:beatle, '2').text.should == 'Paul'
98
+ @session.find(1).text.should == 'John'
99
+ @session.find(2).text.should == 'Paul'
72
100
  @session.find('//h1').text.should == 'This is a test'
73
101
  end
74
102
  end
75
103
 
76
104
  context "with custom selector with custom filter" do
77
105
  before do
78
- Capybara.add_selector(:monkey) do
79
- xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
80
- filter(:name) { |node, name| node.text == name }
106
+ Capybara.add_selector(:beatle) do
107
+ xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
108
+ filter(:type) { |node, type| node[:class].split(/\s+/).include?(type) }
109
+ end
110
+ end
111
+
112
+ it "should find elements that match the filter" do
113
+ @session.find(:beatle, 'Paul', :type => 'drummer').text.should == 'Paul'
114
+ @session.find(:beatle, 'Ringo', :type => 'drummer').text.should == 'Ringo'
115
+ end
116
+
117
+ it "ignores filter when it is not given" do
118
+ @session.find(:beatle, 'Paul').text.should == 'Paul'
119
+ @session.find(:beatle, 'John').text.should == 'John'
120
+ end
121
+
122
+ it "should not find elements that don't match the filter" do
123
+ expect { @session.find(:beatle, 'John', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
124
+ expect { @session.find(:beatle, 'George', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
125
+ end
126
+ end
127
+
128
+ context "with custom selector with custom filter and default" do
129
+ before do
130
+ Capybara.add_selector(:beatle) do
131
+ xpath { |name| ".//li[contains(@class, 'beatle')][contains(text(), '#{name}')]" }
132
+ filter(:type, :default => "drummer") { |node, type| node[:class].split(/\s+/).include?(type) }
81
133
  end
82
134
  end
83
135
 
84
136
  it "should find elements that match the filter" do
85
- @session.find(:monkey, '1', :name => 'Monkey John').text.should == 'Monkey John'
86
- @session.find(:monkey, '2', :name => 'Monkey Paul').text.should == 'Monkey Paul'
137
+ @session.find(:beatle, 'Paul', :type => 'drummer').text.should == 'Paul'
138
+ @session.find(:beatle, 'Ringo', :type => 'drummer').text.should == 'Ringo'
139
+ end
140
+
141
+ it "should use default value when filter is not given" do
142
+ @session.find(:beatle, 'Paul').text.should == 'Paul'
143
+ expect { @session.find(:beatle, 'John') }.to raise_error(Capybara::ElementNotFound)
87
144
  end
88
145
 
89
146
  it "should not find elements that don't match the filter" do
90
- expect { @session.find(:monkey, '2', :name => 'Monkey John') }.to raise_error(Capybara::ElementNotFound)
91
- expect { @session.find(:monkey, '1', :name => 'Monkey Paul') }.to raise_error(Capybara::ElementNotFound)
147
+ expect { @session.find(:beatle, 'John', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
148
+ expect { @session.find(:beatle, 'George', :type => 'drummer') }.to raise_error(Capybara::ElementNotFound)
92
149
  end
93
150
  end
94
151
 
@@ -113,6 +170,185 @@ Capybara::SpecHelper.spec '#find' do
113
170
  @session.find(@xpath).value.should == 'John'
114
171
  end
115
172
 
173
+ context "with :exact option" do
174
+ it "matches exactly when true" do
175
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], :exact => true).value.should == "monkey"
176
+ expect do
177
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], :exact => true)
178
+ end.to raise_error(Capybara::ElementNotFound)
179
+ end
180
+
181
+ it "matches loosely when false" do
182
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("test_field")], :exact => false).value.should == "monkey"
183
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")], :exact => false).value.should == "monkey"
184
+ end
185
+
186
+ it "defaults to `Capybara.exact`" do
187
+ Capybara.exact = true
188
+ expect do
189
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
190
+ end.to raise_error(Capybara::ElementNotFound)
191
+ Capybara.exact = false
192
+ @session.find(:xpath, XPath.descendant(:input)[XPath.attr(:id).is("est_fiel")])
193
+ end
194
+ end
195
+
196
+ context "with :match option" do
197
+ context "when set to `one`" do
198
+ it "raises an error when multiple matches exist" do
199
+ expect do
200
+ @session.find(:css, ".multiple", :match => :one)
201
+ end.to raise_error(Capybara::Ambiguous)
202
+ end
203
+ it "raises an error even if there the match is exact and the others are inexact" do
204
+ expect do
205
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :exact => false, :match => :one)
206
+ end.to raise_error(Capybara::Ambiguous)
207
+ end
208
+ it "returns the element if there is only one" do
209
+ @session.find(:css, ".singular", :match => :one).text.should == "singular"
210
+ end
211
+ it "raises an error if there is no match" do
212
+ expect do
213
+ @session.find(:css, ".does-not-exist", :match => :one)
214
+ end.to raise_error(Capybara::ElementNotFound)
215
+ end
216
+ end
217
+
218
+ context "when set to `first`" do
219
+ it "returns the first matched element" do
220
+ @session.find(:css, ".multiple", :match => :first).text.should == "multiple one"
221
+ end
222
+ it "raises an error if there is no match" do
223
+ expect do
224
+ @session.find(:css, ".does-not-exist", :match => :first)
225
+ end.to raise_error(Capybara::ElementNotFound)
226
+ end
227
+ end
228
+
229
+ context "when set to `smart`" do
230
+ context "and `exact` set to `false`" do
231
+ it "raises an error when there are multiple exact matches" do
232
+ expect do
233
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :smart, :exact => false)
234
+ end.to raise_error(Capybara::Ambiguous)
235
+ end
236
+ it "finds a single exact match when there also are inexact matches" do
237
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :smart, :exact => false)
238
+ result.text.should == "almost singular"
239
+ end
240
+ it "raises an error when there are multiple inexact matches" do
241
+ expect do
242
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :smart, :exact => false)
243
+ end.to raise_error(Capybara::Ambiguous)
244
+ end
245
+ it "finds a single inexact match" do
246
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :smart, :exact => false)
247
+ result.text.should == "almost singular but not quite"
248
+ end
249
+ it "raises an error if there is no match" do
250
+ expect do
251
+ @session.find(:css, ".does-not-exist", :match => :smart, :exact => false)
252
+ end.to raise_error(Capybara::ElementNotFound)
253
+ end
254
+ end
255
+
256
+ context "with `exact` set to `true`" do
257
+ it "raises an error when there are multiple exact matches" do
258
+ expect do
259
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :smart, :exact => true)
260
+ end.to raise_error(Capybara::Ambiguous)
261
+ end
262
+ it "finds a single exact match when there also are inexact matches" do
263
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :smart, :exact => true)
264
+ result.text.should == "almost singular"
265
+ end
266
+ it "raises an error when there are multiple inexact matches" do
267
+ expect do
268
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :smart, :exact => true)
269
+ end.to raise_error(Capybara::ElementNotFound)
270
+ end
271
+ it "raises an error when there is a single inexact matches" do
272
+ expect do
273
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :smart, :exact => true)
274
+ end.to raise_error(Capybara::ElementNotFound)
275
+ end
276
+ it "raises an error if there is no match" do
277
+ expect do
278
+ @session.find(:css, ".does-not-exist", :match => :smart, :exact => true)
279
+ end.to raise_error(Capybara::ElementNotFound)
280
+ end
281
+ end
282
+ end
283
+
284
+ context "when set to `prefer_exact`" do
285
+ context "and `exact` set to `false`" do
286
+ it "picks the first one when there are multiple exact matches" do
287
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :prefer_exact, :exact => false)
288
+ result.text.should == "multiple one"
289
+ end
290
+ it "finds a single exact match when there also are inexact matches" do
291
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :prefer_exact, :exact => false)
292
+ result.text.should == "almost singular"
293
+ end
294
+ it "picks the first one when there are multiple inexact matches" do
295
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :prefer_exact, :exact => false)
296
+ result.text.should == "almost singular but not quite"
297
+ end
298
+ it "finds a single inexact match" do
299
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :prefer_exact, :exact => false)
300
+ result.text.should == "almost singular but not quite"
301
+ end
302
+ it "raises an error if there is no match" do
303
+ expect do
304
+ @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => false)
305
+ end.to raise_error(Capybara::ElementNotFound)
306
+ end
307
+ end
308
+
309
+ context "with `exact` set to `true`" do
310
+ it "picks the first one when there are multiple exact matches" do
311
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("multiple")], :match => :prefer_exact, :exact => true)
312
+ result.text.should == "multiple one"
313
+ end
314
+ it "finds a single exact match when there also are inexact matches" do
315
+ result = @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular")], :match => :prefer_exact, :exact => true)
316
+ result.text.should == "almost singular"
317
+ end
318
+ it "raises an error if there are multiple inexact matches" do
319
+ expect do
320
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singul")], :match => :prefer_exact, :exact => true)
321
+ end.to raise_error(Capybara::ElementNotFound)
322
+ end
323
+ it "raises an error if there is a single inexact match" do
324
+ expect do
325
+ @session.find(:xpath, XPath.descendant[XPath.attr(:class).is("almost_singular but")], :match => :prefer_exact, :exact => true)
326
+ end.to raise_error(Capybara::ElementNotFound)
327
+ end
328
+ it "raises an error if there is no match" do
329
+ expect do
330
+ @session.find(:css, ".does-not-exist", :match => :prefer_exact, :exact => true)
331
+ end.to raise_error(Capybara::ElementNotFound)
332
+ end
333
+ end
334
+ end
335
+
336
+ it "defaults to `Capybara.match`" do
337
+ Capybara.match = :one
338
+ expect do
339
+ @session.find(:css, ".multiple")
340
+ end.to raise_error(Capybara::Ambiguous)
341
+ Capybara.match = :first
342
+ @session.find(:css, ".multiple").text.should == "multiple one"
343
+ end
344
+
345
+ it "raises an error when unknown option given" do
346
+ expect do
347
+ @session.find(:css, ".singular", :match => :schmoo)
348
+ end.to raise_error(ArgumentError)
349
+ end
350
+ end
351
+
116
352
  context "within a scope" do
117
353
  before do
118
354
  @session.visit('/with_scope')
@@ -123,5 +359,11 @@ Capybara::SpecHelper.spec '#find' do
123
359
  @session.find('.//li[1]').text.should =~ /With Simple HTML/
124
360
  end
125
361
  end
362
+
363
+ it "should support pseudo selectors" do
364
+ @session.within(:xpath, "//div[@id='for_bar']") do
365
+ @session.find(:css, 'input:disabled').value.should == 'James'
366
+ end
367
+ end
126
368
  end
127
369
  end