capybara 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
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