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