capybara 2.3.0 → 2.4.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +21 -0
  3. data/README.md +50 -12
  4. data/lib/capybara.rb +8 -1
  5. data/lib/capybara/driver/base.rb +28 -0
  6. data/lib/capybara/driver/node.rb +3 -2
  7. data/lib/capybara/helpers.rb +2 -3
  8. data/lib/capybara/node/actions.rb +5 -2
  9. data/lib/capybara/node/base.rb +10 -0
  10. data/lib/capybara/node/document.rb +2 -0
  11. data/lib/capybara/node/document_matchers.rb +68 -0
  12. data/lib/capybara/node/element.rb +17 -2
  13. data/lib/capybara/node/finders.rb +5 -20
  14. data/lib/capybara/node/matchers.rb +101 -71
  15. data/lib/capybara/node/simple.rb +9 -15
  16. data/lib/capybara/queries/base_query.rb +29 -0
  17. data/lib/capybara/queries/text_query.rb +56 -0
  18. data/lib/capybara/queries/title_query.rb +40 -0
  19. data/lib/capybara/query.rb +30 -20
  20. data/lib/capybara/rack_test/node.rb +11 -3
  21. data/lib/capybara/result.rb +1 -1
  22. data/lib/capybara/rspec/features.rb +38 -21
  23. data/lib/capybara/rspec/matchers.rb +53 -38
  24. data/lib/capybara/selector.rb +68 -14
  25. data/lib/capybara/selenium/driver.rb +54 -6
  26. data/lib/capybara/selenium/node.rb +4 -2
  27. data/lib/capybara/session.rb +109 -35
  28. data/lib/capybara/spec/public/test.js +34 -1
  29. data/lib/capybara/spec/session/accept_alert_spec.rb +57 -0
  30. data/lib/capybara/spec/session/accept_confirm_spec.rb +19 -0
  31. data/lib/capybara/spec/session/accept_prompt_spec.rb +49 -0
  32. data/lib/capybara/spec/session/assert_text.rb +195 -0
  33. data/lib/capybara/spec/session/assert_title.rb +69 -0
  34. data/lib/capybara/spec/session/dismiss_confirm_spec.rb +35 -0
  35. data/lib/capybara/spec/session/dismiss_prompt_spec.rb +19 -0
  36. data/lib/capybara/spec/session/find_field_spec.rb +6 -0
  37. data/lib/capybara/spec/session/has_text_spec.rb +1 -1
  38. data/lib/capybara/spec/session/node_spec.rb +16 -1
  39. data/lib/capybara/spec/session/save_and_open_screenshot_spec.rb +1 -1
  40. data/lib/capybara/spec/session/visit_spec.rb +5 -0
  41. data/lib/capybara/spec/views/with_html.erb +4 -0
  42. data/lib/capybara/spec/views/with_js.erb +17 -0
  43. data/lib/capybara/version.rb +1 -1
  44. data/spec/dsl_spec.rb +3 -1
  45. data/spec/rack_test_spec.rb +12 -1
  46. data/spec/rspec/features_spec.rb +1 -1
  47. data/spec/rspec/matchers_spec.rb +113 -20
  48. data/spec/selenium_spec.rb +10 -1
  49. metadata +13 -2
@@ -0,0 +1,195 @@
1
+ Capybara::SpecHelper.spec '#assert_text' do
2
+ it "should be true if the given text is on the page" do
3
+ @session.visit('/with_html')
4
+ expect(@session.assert_text('est')).to eq(true)
5
+ expect(@session.assert_text('Lorem')).to eq(true)
6
+ expect(@session.assert_text('Redirect')).to eq(true)
7
+ expect(@session.assert_text(:'Redirect')).to eq(true)
8
+ expect(@session.assert_text('text with whitespace')).to eq(true)
9
+ expect(@session.assert_text("text with \n\n whitespace")).to eq(true)
10
+ end
11
+
12
+ it "should take scopes into account" do
13
+ @session.visit('/with_html')
14
+ @session.within("//a[@title='awesome title']") do
15
+ expect(@session.assert_text('labore')).to eq(true)
16
+ end
17
+ end
18
+
19
+ it "should raise if scoped to an element which does not have the text" do
20
+ @session.visit('/with_html')
21
+ @session.within("//a[@title='awesome title']") do
22
+ expect do
23
+ @session.assert_text('monkey')
24
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected to find text "monkey" in "labore"')
25
+ end
26
+ end
27
+
28
+ it "should be true if :all given and text is invisible." do
29
+ @session.visit('/with_html')
30
+ expect(@session.assert_text(:all, 'Some of this text is hidden!')).to eq(true)
31
+ end
32
+
33
+ it "should be true if `Capybara.ignore_hidden_elements = true` and text is invisible." do
34
+ Capybara.ignore_hidden_elements = false
35
+ @session.visit('/with_html')
36
+ expect(@session.assert_text('Some of this text is hidden!')).to eq(true)
37
+ end
38
+
39
+ it "should be true if the text in the page matches given regexp" do
40
+ @session.visit('/with_html')
41
+ expect(@session.assert_text(/Lorem/)).to eq(true)
42
+ end
43
+
44
+ it "should be raise error if the text in the page doesn't match given regexp" do
45
+ @session.visit('/with_html')
46
+ expect do
47
+ @session.assert_text(/xxxxyzzz/)
48
+ end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected to find text matching \/xxxxyzzz\/ in "This is a test Header Class(.+)"\Z/)
49
+ end
50
+
51
+ it "should escape any characters that would have special meaning in a regexp" do
52
+ @session.visit('/with_html')
53
+ expect do
54
+ @session.assert_text('.orem')
55
+ end.to raise_error(Capybara::ExpectationNotMet)
56
+ end
57
+
58
+ it "should wait for text to appear", :requires => [:js] do
59
+ @session.visit('/with_js')
60
+ @session.click_link('Click me')
61
+ expect(@session.assert_text('Has been clicked')).to eq(true)
62
+ end
63
+
64
+ context "with between" do
65
+ it "should be true if the text occurs within the range given" do
66
+ @session.visit('/with_count')
67
+ expect(@session.assert_text('count', between: 1..3)).to eq(true)
68
+ end
69
+
70
+ it "should be false if the text occurs more or fewer times than range" do
71
+ @session.visit('/with_html')
72
+ expect do
73
+ @session.find(:css, '.number').assert_text(/\d/, between: 0..1)
74
+ end.to raise_error(Capybara::ExpectationNotMet, "expected to find text matching /\\d/ between 0 and 1 times but found 2 times in \"42\"")
75
+ end
76
+ end
77
+
78
+ context "with wait", :requires => [:js] do
79
+ it "should find element if it appears before given wait duration" do
80
+ Capybara.using_wait_time(0) do
81
+ @session.visit('/with_js')
82
+ @session.find(:css, '#reload-list').click
83
+ @session.find(:css, '#the-list').assert_text('Foo Bar', wait: 0.9)
84
+ end
85
+ end
86
+
87
+ it "should raise error if it appears after given wait duration" do
88
+ Capybara.using_wait_time(0) do
89
+ @session.visit('/with_js')
90
+ @session.find(:css, '#reload-list').click
91
+ el = @session.find(:css, '#the-list', visible: false)
92
+ expect do
93
+ el.assert_text(:all, 'Foo Bar', wait: 0.3)
94
+ end.to raise_error(Capybara::ExpectationNotMet)
95
+ end
96
+ end
97
+ end
98
+
99
+ context 'with multiple count filters' do
100
+ before(:each) do
101
+ @session.visit('/with_html')
102
+ end
103
+
104
+ it 'ignores other filters when :count is specified' do
105
+ o = {:count => 5,
106
+ :minimum => 6,
107
+ :maximum => 0,
108
+ :between => 0..4}
109
+ expect { @session.assert_text('Header', o) }.not_to raise_error
110
+ end
111
+ context 'with no :count expectation' do
112
+ it 'fails if :minimum is not met' do
113
+ o = {:minimum => 6,
114
+ :maximum => 5,
115
+ :between => 2..7}
116
+ expect { @session.assert_text('Header', o) }.to raise_error(Capybara::ExpectationNotMet)
117
+ end
118
+ it 'fails if :maximum is not met' do
119
+ o = {:minimum => 0,
120
+ :maximum => 0,
121
+ :between => 2..7}
122
+ expect { @session.assert_text('Header', o) }.to raise_error(Capybara::ExpectationNotMet)
123
+ end
124
+ it 'fails if :between is not met' do
125
+ o = {:minimum => 0,
126
+ :maximum => 5,
127
+ :between => 0..4}
128
+ expect { @session.assert_text('Header', o) }.to raise_error(Capybara::ExpectationNotMet)
129
+ end
130
+ it 'succeeds if all combineable expectations are met' do
131
+ o = {:minimum => 0,
132
+ :maximum => 5,
133
+ :between => 2..7}
134
+ expect { @session.assert_text('Header', o) }.not_to raise_error
135
+ end
136
+ end
137
+ end
138
+ end
139
+
140
+ Capybara::SpecHelper.spec '#assert_no_text' do
141
+ it "should raise error if the given text is on the page at least once" do
142
+ @session.visit('/with_html')
143
+ expect do
144
+ @session.assert_no_text('Lorem')
145
+ end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected not to find text "Lorem" in "This is a test Header Class.+"\Z/)
146
+ end
147
+
148
+ it "should be true if scoped to an element which does not have the text" do
149
+ @session.visit('/with_html')
150
+ @session.within("//a[@title='awesome title']") do
151
+ expect(@session.assert_no_text('monkey')).to eq(true)
152
+ end
153
+ end
154
+
155
+ it "should be true if the given text is on the page but not visible" do
156
+ @session.visit('/with_html')
157
+ expect(@session.assert_no_text('Inside element with hidden ancestor')).to eq(true)
158
+ end
159
+
160
+ it "should raise error if :all given and text is invisible." do
161
+ @session.visit('/with_html')
162
+ el = @session.find(:css, '#hidden-text', visible: false)
163
+ expect do
164
+ el.assert_no_text(:all, 'Some of this text is hidden!')
165
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected not to find text "Some of this text is hidden!" in "Some of this text is hidden!"')
166
+ end
167
+
168
+ it "should be true if the text in the page doesn't match given regexp" do
169
+ @session.visit('/with_html')
170
+ @session.assert_no_text(/xxxxyzzz/)
171
+ end
172
+
173
+ context "with count" do
174
+ it "should be true if the text occurs within the range given" do
175
+ @session.visit('/with_count')
176
+ expect(@session.assert_text('count', count: 2)).to eq(true)
177
+ end
178
+
179
+ it "should be false if the text occurs more or fewer times than range" do
180
+ @session.visit('/with_html')
181
+ expect do
182
+ @session.find(:css, '.number').assert_text(/\d/, count: 1)
183
+ end.to raise_error(Capybara::ExpectationNotMet, "expected to find text matching /\\d/ 1 time but found 2 times in \"42\"")
184
+ end
185
+ end
186
+
187
+ context "with wait", :requires => [:js] do
188
+ it "should not find element if it appears after given wait duration" do
189
+ @session.visit('/with_js')
190
+ @session.click_link('Click me')
191
+ @session.find(:css, '#reload-list').click
192
+ @session.find(:css, '#the-list').assert_no_text('Foo Bar', :wait => 0.4)
193
+ end
194
+ end
195
+ end
@@ -0,0 +1,69 @@
1
+ Capybara::SpecHelper.spec '#assert_title' do
2
+ before do
3
+ @session.visit('/with_js')
4
+ end
5
+
6
+ it "should be true if the page's title contains the given string" do
7
+ expect(@session.assert_title('js')).to eq(true)
8
+ end
9
+
10
+ it "should be true when given an empty string" do
11
+ expect(@session.assert_title('')).to eq(true)
12
+ end
13
+
14
+ it "should allow regexp matches" do
15
+ expect(@session.assert_title(/w[a-z]{3}_js/)).to eq(true)
16
+ expect do
17
+ @session.assert_title(/w[a-z]{10}_js/)
18
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to match /w[a-z]{10}_js/')
19
+ end
20
+
21
+ it "should wait for title", :requires => [:js] do
22
+ @session.click_link("Change title")
23
+ expect(@session.assert_title("changed title")).to eq(true)
24
+ end
25
+
26
+ it "should raise error if the title doesn't contain the given string" do
27
+ expect do
28
+ @session.assert_title('monkey')
29
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "monkey"')
30
+ end
31
+
32
+ it "should normalize given title" do
33
+ @session.assert_title(' with_js ')
34
+ end
35
+
36
+ it "should normalize given title in error message" do
37
+ expect do
38
+ @session.assert_title(2)
39
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "2"')
40
+ end
41
+ end
42
+
43
+ Capybara::SpecHelper.spec '#assert_no_title' do
44
+ before do
45
+ @session.visit('/with_js')
46
+ end
47
+
48
+ it "should raise error if the title contains the given string" do
49
+ expect do
50
+ @session.assert_no_title('with_j')
51
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" not to include "with_j"')
52
+ end
53
+
54
+ it "should allow regexp matches" do
55
+ expect do
56
+ @session.assert_no_title(/w[a-z]{3}_js/)
57
+ end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" not to match /w[a-z]{3}_js/')
58
+ @session.assert_no_title(/monkey/)
59
+ end
60
+
61
+ it "should wait for title to disappear", :requires => [:js] do
62
+ @session.click_link("Change title")
63
+ expect(@session.assert_no_title('with_js')).to eq(true)
64
+ end
65
+
66
+ it "should be true if the title doesn't contain the given string" do
67
+ expect(@session.assert_no_title('monkey')).to eq(true)
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ Capybara::SpecHelper.spec '#dismiss_confirm', :requires => [:modals] do
2
+ before do
3
+ @session.visit('/with_js')
4
+ end
5
+
6
+ it "should dismiss the confirm" do
7
+ @session.dismiss_confirm do
8
+ @session.click_link('Open confirm')
9
+ end
10
+ expect(@session).to have_xpath("//a[@id='open-confirm' and @confirmed='false']")
11
+ end
12
+
13
+ it "should dismiss the confirm if the message matches" do
14
+ @session.dismiss_confirm 'Confirm opened' do
15
+ @session.click_link('Open confirm')
16
+ end
17
+ expect(@session).to have_xpath("//a[@id='open-confirm' and @confirmed='false']")
18
+ end
19
+
20
+ it "should not dismiss the confirm if the message doesn't match" do
21
+ expect do
22
+ @session.dismiss_confirm 'Incorrect Text' do
23
+ @session.click_link('Open confirm')
24
+ end
25
+ end.to raise_error(Capybara::ModalNotFound)
26
+ end
27
+
28
+
29
+ it "should return the message presented" do
30
+ message = @session.dismiss_confirm do
31
+ @session.click_link('Open confirm')
32
+ end
33
+ expect(message).to eq('Confirm opened')
34
+ end
35
+ end
@@ -0,0 +1,19 @@
1
+ Capybara::SpecHelper.spec '#dismiss_prompt', :requires => [:modals] do
2
+ before do
3
+ @session.visit('/with_js')
4
+ end
5
+
6
+ it "should dismiss the prompt" do
7
+ @session.dismiss_prompt do
8
+ @session.click_link('Open prompt')
9
+ end
10
+ expect(@session).to have_xpath("//a[@id='open-prompt' and @response='dismissed']")
11
+ end
12
+
13
+ it "should return the message presented" do
14
+ message = @session.dismiss_prompt do
15
+ @session.click_link('Open prompt')
16
+ end
17
+ expect(message).to eq('Prompt opened')
18
+ end
19
+ end
@@ -19,6 +19,12 @@ Capybara::SpecHelper.spec '#find_field' do
19
19
  end.to raise_error(Capybara::ElementNotFound)
20
20
  end
21
21
 
22
+ it "should warn if filter option is invalid" do
23
+ expect_any_instance_of(Kernel).to receive(:warn).
24
+ with('Invalid value nil passed to filter disabled')
25
+ @session.find_field('Dog', disabled: nil)
26
+ end
27
+
22
28
  it "should be aliased as 'field_labeled' for webrat compatibility" do
23
29
  expect(@session.field_labeled('Dog').value).to eq('dog')
24
30
  expect do
@@ -106,7 +106,7 @@ Capybara::SpecHelper.spec '#has_text?' do
106
106
  end
107
107
 
108
108
  it "should be true when passed nil" do
109
- # Historical behavior; no particular reason other than compatibility.
109
+ # nil is converted to '' when to_s is invoked
110
110
  @session.visit('/with_html')
111
111
  expect(@session).to have_text(nil)
112
112
  end
@@ -97,6 +97,10 @@ Capybara::SpecHelper.spec "node" do
97
97
  @session.first('//input[@readonly]').set('changed')
98
98
  expect(@session.first('//input[@readonly]').value).to eq('should not change')
99
99
  end
100
+
101
+ it "should raise if the text field is readonly" do
102
+ expect(@session.first('//input[@readonly]').set('changed')).to raise_error(Capybara::ReadOnlyElementError)
103
+ end if Capybara::VERSION.to_f > 3.0
100
104
 
101
105
  it "should not set if the textarea is readonly" do
102
106
  expect(@session.first('//textarea[@readonly]').value).to eq('textarea should not change')
@@ -104,6 +108,10 @@ Capybara::SpecHelper.spec "node" do
104
108
  expect(@session.first('//textarea[@readonly]').value).to eq('textarea should not change')
105
109
  end
106
110
 
111
+ it "should raise if the text field is readonly" do
112
+ expect(@session.first('//textarea[@readonly]').set('changed')).to raise_error(Capybara::ReadOnlyElementError)
113
+ end if Capybara::VERSION.to_f > 3.0
114
+
107
115
  it 'should allow me to change the contents of a contenteditable element', :requires => [:js] do
108
116
  @session.visit('/with_js')
109
117
  @session.find(:css,'#existing_content_editable').set('WYSIWYG')
@@ -221,6 +229,13 @@ Capybara::SpecHelper.spec "node" do
221
229
  end
222
230
  end
223
231
 
232
+ describe '#click' do
233
+ it "should not follow a link if no href" do
234
+ @session.find(:css, '#link_placeholder').click
235
+ expect(@session.current_url).to match(%r{/with_html$})
236
+ end
237
+ end
238
+
224
239
  describe '#double_click', :requires => [:js] do
225
240
  it "should double click an element" do
226
241
  @session.visit('/with_js')
@@ -230,7 +245,7 @@ Capybara::SpecHelper.spec "node" do
230
245
  end
231
246
 
232
247
  describe '#right_click', :requires => [:js] do
233
- it "should double click an element" do
248
+ it "should right click an element" do
234
249
  @session.visit('/with_js')
235
250
  @session.find(:css, '#click-test').right_click
236
251
  expect(@session.find(:css, '#has-been-right-clicked')).to be
@@ -6,7 +6,7 @@ Capybara::SpecHelper.spec '#save_and_open_screenshot' do
6
6
  end
7
7
 
8
8
  it 'opens file from the default directory', :requires => [:screenshot] do
9
- expected_file_regex = %r{capybara/capybara-\d+\.png}
9
+ expected_file_regex = %r{capybara-\d+\.png}
10
10
  allow(@session.driver).to receive(:save_screenshot)
11
11
  allow(Launchy).to receive(:open)
12
12
 
@@ -33,6 +33,11 @@ Capybara::SpecHelper.spec '#visit' do
33
33
  end.to raise_error(TestApp::TestAppError)
34
34
  end
35
35
 
36
+ it "should be able to open non-http url", requires: [:about_scheme] do
37
+ @session.visit("about:blank")
38
+ @session.assert_no_selector :xpath, "/html/body/*"
39
+ end
40
+
36
41
  context "when Capybara.always_include_port is true" do
37
42
 
38
43
  let(:root_uri) do
@@ -107,3 +107,7 @@ banana</textarea>
107
107
  </div>
108
108
 
109
109
  <input type="text" disabled="disabled" name="disabled_text" value="This is disabled"/>
110
+
111
+ <div>
112
+ <a id="link_placeholder">No href</a>
113
+ </div>
@@ -72,6 +72,23 @@
72
72
 
73
73
  <p id="click-test">Click me</p>
74
74
 
75
+ <p>
76
+ <a href="#" id="open-alert">Open alert</a>
77
+ </p>
78
+
79
+ <p>
80
+ <a href="#" id="open-delayed-alert">Open delayed alert</a>
81
+ <a href="#" id="open-slow-alert">Open slow alert</a>
82
+ </p>
83
+
84
+ <p>
85
+ <a href="#" id="open-confirm">Open confirm</a>
86
+ </p>
87
+
88
+ <p>
89
+ <a href="#" id="open-prompt">Open prompt</a>
90
+ </p>
91
+
75
92
  <script type="text/javascript">
76
93
  // a javascript comment
77
94
  var aVar = 123;
@@ -1,3 +1,3 @@
1
1
  module Capybara
2
- VERSION = '2.3.0'
2
+ VERSION = '2.4.0'
3
3
  end