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.
- data/History.md +82 -0
- data/README.md +57 -52
- 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 +30 -25
- data/lib/capybara/node/base.rb +25 -32
- data/lib/capybara/node/document.rb +6 -2
- data/lib/capybara/node/element.rb +44 -7
- data/lib/capybara/node/finders.rb +49 -22
- data/lib/capybara/node/matchers.rb +38 -21
- data/lib/capybara/node/simple.rb +31 -9
- 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 +91 -35
- data/lib/capybara/rails.rb +0 -1
- 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 -7
- data/lib/capybara/selenium/node.rb +23 -5
- data/lib/capybara/server.rb +1 -1
- data/lib/capybara/session.rb +47 -12
- 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 +26 -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 +264 -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 +48 -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 +7 -2
- 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 +23 -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/lib/capybara.rb +43 -62
- 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 +15 -8
- data/spec/spec_helper.rb +2 -1
- data.tar.gz.sig +0 -0
- metadata +82 -22
- 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(:
|
|
56
|
-
xpath { |name| ".//*[@id='#{name}
|
|
89
|
+
Capybara.add_selector(:beatle) do
|
|
90
|
+
xpath { |name| ".//*[@id='#{name}']" }
|
|
57
91
|
end
|
|
58
|
-
@session.find(:
|
|
59
|
-
@session.find(:
|
|
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(:
|
|
66
|
-
xpath { |num| ".//*[contains(@
|
|
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(:
|
|
70
|
-
@session.find(1).text.should == '
|
|
71
|
-
@session.find(2).text.should == '
|
|
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(:
|
|
79
|
-
xpath { |
|
|
80
|
-
filter(:
|
|
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(:
|
|
86
|
-
@session.find(:
|
|
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(:
|
|
91
|
-
expect { @session.find(:
|
|
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
|
-
|
|
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
|
|
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
|
|