capybara 0.3.9 → 0.4.0.rc

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/History.txt +43 -1
  2. data/README.rdoc +168 -98
  3. data/lib/capybara.rb +77 -15
  4. data/lib/capybara/driver/base.rb +21 -16
  5. data/lib/capybara/driver/celerity_driver.rb +39 -41
  6. data/lib/capybara/driver/culerity_driver.rb +2 -1
  7. data/lib/capybara/driver/node.rb +66 -0
  8. data/lib/capybara/driver/rack_test_driver.rb +66 -67
  9. data/lib/capybara/driver/selenium_driver.rb +43 -47
  10. data/lib/capybara/dsl.rb +44 -6
  11. data/lib/capybara/node.rb +185 -24
  12. data/lib/capybara/node/actions.rb +170 -0
  13. data/lib/capybara/node/finders.rb +150 -0
  14. data/lib/capybara/node/matchers.rb +360 -0
  15. data/lib/capybara/rails.rb +1 -0
  16. data/lib/capybara/selector.rb +52 -0
  17. data/lib/capybara/server.rb +68 -87
  18. data/lib/capybara/session.rb +221 -207
  19. data/lib/capybara/spec/driver.rb +45 -35
  20. data/lib/capybara/spec/public/test.js +1 -1
  21. data/lib/capybara/spec/session.rb +28 -53
  22. data/lib/capybara/spec/session/all_spec.rb +7 -3
  23. data/lib/capybara/spec/session/check_spec.rb +50 -52
  24. data/lib/capybara/spec/session/click_button_spec.rb +9 -0
  25. data/lib/capybara/spec/session/click_link_or_button_spec.rb +37 -0
  26. data/lib/capybara/spec/session/current_url_spec.rb +7 -0
  27. data/lib/capybara/spec/session/find_button_spec.rb +4 -2
  28. data/lib/capybara/spec/session/find_by_id_spec.rb +4 -2
  29. data/lib/capybara/spec/session/find_field_spec.rb +7 -3
  30. data/lib/capybara/spec/session/find_link_spec.rb +5 -3
  31. data/lib/capybara/spec/session/find_spec.rb +71 -6
  32. data/lib/capybara/spec/session/has_field_spec.rb +1 -1
  33. data/lib/capybara/spec/session/has_selector_spec.rb +129 -0
  34. data/lib/capybara/spec/session/has_xpath_spec.rb +4 -4
  35. data/lib/capybara/spec/session/javascript.rb +25 -5
  36. data/lib/capybara/spec/session/select_spec.rb +16 -2
  37. data/lib/capybara/spec/session/unselect_spec.rb +8 -1
  38. data/lib/capybara/spec/session/within_spec.rb +5 -5
  39. data/lib/capybara/spec/views/form.erb +65 -1
  40. data/lib/capybara/spec/views/popup_one.erb +8 -0
  41. data/lib/capybara/spec/views/popup_two.erb +8 -0
  42. data/lib/capybara/spec/views/with_html.erb +5 -0
  43. data/lib/capybara/spec/views/within_popups.erb +25 -0
  44. data/lib/capybara/{save_and_open_page.rb → util/save_and_open_page.rb} +3 -3
  45. data/lib/capybara/util/timeout.rb +27 -0
  46. data/lib/capybara/version.rb +1 -1
  47. data/spec/capybara_spec.rb +18 -8
  48. data/spec/driver/celerity_driver_spec.rb +10 -14
  49. data/spec/driver/culerity_driver_spec.rb +4 -3
  50. data/spec/driver/rack_test_driver_spec.rb +39 -2
  51. data/spec/driver/remote_culerity_driver_spec.rb +5 -7
  52. data/spec/driver/remote_selenium_driver_spec.rb +7 -10
  53. data/spec/driver/selenium_driver_spec.rb +3 -2
  54. data/spec/dsl_spec.rb +5 -14
  55. data/spec/save_and_open_page_spec.rb +19 -19
  56. data/spec/server_spec.rb +22 -10
  57. data/spec/session/celerity_session_spec.rb +17 -21
  58. data/spec/session/culerity_session_spec.rb +3 -3
  59. data/spec/session/rack_test_session_spec.rb +2 -2
  60. data/spec/session/selenium_session_spec.rb +2 -2
  61. data/spec/spec_helper.rb +27 -6
  62. data/spec/{wait_until_spec.rb → timeout_spec.rb} +14 -14
  63. metadata +88 -46
  64. data/lib/capybara/searchable.rb +0 -54
  65. data/lib/capybara/spec/session/click_spec.rb +0 -24
  66. data/lib/capybara/spec/session/locate_spec.rb +0 -65
  67. data/lib/capybara/wait_until.rb +0 -28
  68. data/lib/capybara/xpath.rb +0 -179
  69. data/spec/searchable_spec.rb +0 -66
  70. data/spec/xpath_spec.rb +0 -180
@@ -1,9 +1,5 @@
1
1
  require 'capybara/spec/test_app'
2
2
 
3
- Dir[File.dirname(__FILE__)+'/driver/*'].each { |group|
4
- require group
5
- }
6
-
7
3
  shared_examples_for 'driver' do
8
4
 
9
5
  describe '#visit' do
@@ -18,11 +14,6 @@ shared_examples_for 'driver' do
18
14
  @driver.visit('/foo')
19
15
  @driver.current_url.should include('/foo')
20
16
  end
21
-
22
- it 'should show the correct location' do
23
- @driver.visit('/foo')
24
- @driver.current_path.should == '/foo'
25
- end
26
17
  end
27
18
 
28
19
  describe '#body' do
@@ -49,11 +40,8 @@ shared_examples_for 'driver' do
49
40
  end
50
41
 
51
42
  it "should extract node attributes" do
52
- @driver.find('//a')[0][:href].should == '/with_simple_html'
53
43
  @driver.find('//a')[0][:class].should == 'simple'
54
- @driver.find('//a')[1][:href].should == '/foo'
55
44
  @driver.find('//a')[1][:id].should == 'foo'
56
- @driver.find('//a')[1][:rel].should be_nil
57
45
  end
58
46
 
59
47
  it "should extract boolean node attributes" do
@@ -84,26 +72,6 @@ shared_examples_for 'driver' do
84
72
  end
85
73
  end
86
74
  end
87
-
88
- describe "node relative searching" do
89
- before do
90
- @driver.visit('/tables')
91
- @node = @driver.find('//body').first
92
- end
93
-
94
- it "should be able to navigate/search child node" do
95
- @node.all('//table').size.should == 5
96
- @node.find('//form').all('.//table').size.should == 1
97
- @node.find('//form').find('.//table//caption').text.should == 'Agent'
98
- if @driver.class == Capybara::Driver::Selenium
99
- pending("Selenium gets this wrong, see http://code.google.com/p/selenium/issues/detail?id=403") do
100
- @node.find('//form').all('//table').size.should == 5
101
- end
102
- else
103
- @node.find('//form').all('//table').size.should == 5
104
- end
105
- end
106
- end
107
75
  end
108
76
 
109
77
  shared_examples_for "driver with javascript support" do
@@ -117,10 +85,11 @@ shared_examples_for "driver with javascript support" do
117
85
 
118
86
  describe '#drag_to' do
119
87
  it "should drag and drop an object" do
88
+ pending "drag/drop is currently broken under celerity/culerity" if @driver.is_a?(Capybara::Driver::Celerity)
120
89
  draggable = @driver.find('//div[@id="drag"]').first
121
90
  droppable = @driver.find('//div[@id="drop"]').first
122
91
  draggable.drag_to(droppable)
123
- @driver.find('//div[contains(., "Dropped!")]').should_not be_nil
92
+ @driver.find('//div[contains(., "Dropped!")]').should_not be_empty
124
93
  end
125
94
  end
126
95
 
@@ -185,8 +154,49 @@ shared_examples_for "driver with frame support" do
185
154
  end
186
155
  end
187
156
 
157
+ shared_examples_for "driver with support for window switching" do
158
+ describe '#within_window' do
159
+ before(:each) do
160
+ @driver.visit('/within_popups')
161
+ end
162
+ after(:each) do
163
+ @driver.within_window("firstPopup") do
164
+ @driver.evaluate_script('window.close()')
165
+ end
166
+ @driver.within_window("secondPopup") do
167
+ @driver.evaluate_script('window.close()')
168
+ end
169
+ end
170
+
171
+ it "should find the div in firstPopup" do
172
+ @driver.within_window("firstPopup") do
173
+ @driver.find("//*[@id='divInPopupOne']")[0].text.should eql 'This is the text of divInPopupOne'
174
+ end
175
+ end
176
+ it "should find the div in secondPopup" do
177
+ @driver.within_window("secondPopup") do
178
+ @driver.find("//*[@id='divInPopupTwo']")[0].text.should eql 'This is the text of divInPopupTwo'
179
+ end
180
+ end
181
+ it "should find the divs in both popups" do
182
+ @driver.within_window("secondPopup") do
183
+ @driver.find("//*[@id='divInPopupTwo']")[0].text.should eql 'This is the text of divInPopupTwo'
184
+ end
185
+ @driver.within_window("firstPopup") do
186
+ @driver.find("//*[@id='divInPopupOne']")[0].text.should eql 'This is the text of divInPopupOne'
187
+ end
188
+ end
189
+ it "should find the div in the main window after finding a div in a popup" do
190
+ @driver.within_window("secondPopup") do
191
+ @driver.find("//*[@id='divInPopupTwo']")[0].text.should eql 'This is the text of divInPopupTwo'
192
+ end
193
+ @driver.find("//*[@id='divInMainWindow']")[0].text.should eql 'This is the text for divInMainWindow'
194
+ end
195
+ end
196
+ end
197
+
188
198
  shared_examples_for "driver with cookies support" do
189
- describe "#cleanup" do
199
+ describe "#reset!" do
190
200
  it "should set and clean cookies" do
191
201
  @driver.visit('/get_cookie')
192
202
  @driver.body.should_not include('test_cookie')
@@ -197,7 +207,7 @@ shared_examples_for "driver with cookies support" do
197
207
  @driver.visit('/get_cookie')
198
208
  @driver.body.should include('test_cookie')
199
209
 
200
- @driver.cleanup!
210
+ @driver.reset!
201
211
  @driver.visit('/get_cookie')
202
212
  @driver.body.should_not include('test_cookie')
203
213
  end
@@ -11,7 +11,7 @@ $(function() {
11
11
  $('#clickable').click(function() {
12
12
  var link = $(this);
13
13
  setTimeout(function() {
14
- $(link).after('<a href="#">Has been clicked</a>');
14
+ $(link).after('<a id="has-been-clicked" href="#">Has been clicked</a>');
15
15
  $(link).after('<input type="submit" value="New Here">');
16
16
  $(link).after('<input type="text" id="new_field">');
17
17
  $('#change').remove();
@@ -1,15 +1,17 @@
1
1
  require 'capybara/spec/test_app'
2
2
  require 'nokogiri'
3
3
 
4
- Dir[File.dirname(__FILE__)+'/session/*'].each { |group|
5
- require group
6
- }
4
+ Dir[File.dirname(__FILE__)+'/session/*'].each { |group| require group }
7
5
 
8
6
  shared_examples_for "session" do
9
7
  def extract_results(session)
10
8
  YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.text
11
9
  end
12
10
 
11
+ after do
12
+ @session.reset!
13
+ end
14
+
13
15
  describe '#app' do
14
16
  it "should remember the application" do
15
17
  @session.app.should == TestApp
@@ -24,14 +26,14 @@ shared_examples_for "session" do
24
26
  @session.body.should include('Another World')
25
27
  end
26
28
  end
27
-
29
+
28
30
  describe '#body' do
29
31
  it "should return the unmodified page body" do
30
32
  @session.visit('/')
31
33
  @session.body.should include('Hello world!')
32
34
  end
33
35
  end
34
-
36
+
35
37
  describe '#source' do
36
38
  it "should return the unmodified page source" do
37
39
  @session.visit('/')
@@ -39,57 +41,11 @@ shared_examples_for "session" do
39
41
  end
40
42
  end
41
43
 
42
- describe '#scope_to' do
43
- let(:scope) { @session.scope_to("//p[@id='first']") }
44
- let(:more_scope) { scope.scope_to("//a[@id='foo']") }
45
-
46
- before do
47
- @session.visit('/with_html')
48
- end
49
-
50
- it 'has a simple link' do
51
- scope.should have_xpath("//a[@class='simple']")
52
- end
53
-
54
- it 'does not have a redirect link' do
55
- scope.should have_no_xpath("//a[@id='red']")
56
- end
57
-
58
- it 'does have a redirect link' do
59
- @session.should have_xpath("//a[@id='red']")
60
- end
61
-
62
- it 'does not share scopes' do
63
- @session.should have_xpath("//a[@id='red']")
64
- scope.should have_no_xpath("//a[@id='red']")
65
- @session.should have_xpath("//a[@id='red']")
66
- end
67
-
68
- context 'more_scope' do
69
- it 'has the text for foo' do
70
- more_scope.should have_content('ullamco')
71
- end
72
-
73
- it 'does not have a simple link' do
74
- more_scope.should have_no_xpath("//a[@class='simple']")
75
- end
76
-
77
- it 'has not overridden scope' do
78
- scope.should have_xpath("//a[@class='simple']")
79
- end
80
-
81
- it 'has not overridden session' do
82
- @session.should have_xpath("//p[@id='second']")
83
- end
84
- end
85
-
86
- end
87
-
88
44
  it_should_behave_like "all"
89
45
  it_should_behave_like "attach_file"
90
46
  it_should_behave_like "check"
91
47
  it_should_behave_like "choose"
92
- it_should_behave_like "click"
48
+ it_should_behave_like "click_link_or_button"
93
49
  it_should_behave_like "click_button"
94
50
  it_should_behave_like "click_link"
95
51
  it_should_behave_like "fill_in"
@@ -101,6 +57,7 @@ shared_examples_for "session" do
101
57
  it_should_behave_like "has_content"
102
58
  it_should_behave_like "has_css"
103
59
  it_should_behave_like "has_css"
60
+ it_should_behave_like "has_selector"
104
61
  it_should_behave_like "has_xpath"
105
62
  it_should_behave_like "has_link"
106
63
  it_should_behave_like "has_button"
@@ -110,9 +67,27 @@ shared_examples_for "session" do
110
67
  it_should_behave_like "select"
111
68
  it_should_behave_like "uncheck"
112
69
  it_should_behave_like "unselect"
113
- it_should_behave_like "locate"
114
70
  it_should_behave_like "within"
115
71
  it_should_behave_like "current_url"
72
+
73
+ it "should encode complex field names, like array[][value]" do
74
+ @session.visit('/form')
75
+ @session.fill_in('address1_city', :with =>'Paris')
76
+ @session.fill_in('address1_street', :with =>'CDG')
77
+ @session.fill_in('address2_city', :with => 'Mikolaiv')
78
+ @session.fill_in('address2_street', :with => 'PGS')
79
+ @session.click_button "awesome"
80
+
81
+ addresses=extract_results(@session)["addresses"]
82
+ addresses.should have(2).addresses
83
+
84
+ addresses[0]["street"].should == 'CDG'
85
+ addresses[0]["city"].should == 'Paris'
86
+
87
+ addresses[1]["street"].should == 'PGS'
88
+ addresses[1]["city"].should == 'Mikolaiv'
89
+ end
90
+
116
91
  end
117
92
 
118
93
 
@@ -16,16 +16,20 @@ shared_examples_for "all" do
16
16
 
17
17
  it "should accept an XPath instance" do
18
18
  @session.visit('/form')
19
- @xpath = Capybara::XPath.text_field('Name')
19
+ @xpath = XPath::HTML.fillable_field('Name')
20
20
  @result = @session.all(@xpath).map { |r| r.value }
21
21
  @result.should include('Smith', 'John', 'John Smith')
22
22
  end
23
23
 
24
24
  context "with css selectors" do
25
- it "should find the first element using the given locator" do
25
+ it "should find all elements using the given selector" do
26
26
  @session.all(:css, 'h1').first.text.should == 'This is a test'
27
27
  @session.all(:css, "input[id='test_field']").first[:value].should == 'monkey'
28
28
  end
29
+
30
+ it "should find all elements when given a list of selectors" do
31
+ @session.all(:css, 'h1, p').should have(4).elements
32
+ end
29
33
  end
30
34
 
31
35
  context "with xpath selectors" do
@@ -61,7 +65,7 @@ shared_examples_for "all" do
61
65
 
62
66
  it "should find any element using the given locator" do
63
67
  @session.within(:xpath, "//div[@id='for_bar']") do
64
- @session.all('//li').should have(2).elements
68
+ @session.all('.//li').should have(2).elements
65
69
  end
66
70
  end
67
71
  end
@@ -1,67 +1,65 @@
1
- module CheckSpec
2
- shared_examples_for "check" do
3
-
4
- describe "#check" do
5
- before do
6
- @session.visit('/form')
1
+ shared_examples_for "check" do
2
+
3
+ describe "#check" do
4
+ before do
5
+ @session.visit('/form')
6
+ end
7
+
8
+ describe "'checked' attribute" do
9
+ it "should be true if checked" do
10
+ @session.check("Terms of Use")
11
+ @session.find(:xpath, "//input[@id='form_terms_of_use']")['checked'].should be_true
7
12
  end
8
13
 
9
- describe "'checked' attribute" do
10
- it "should be true if checked" do
11
- @session.check("Terms of Use")
12
- @session.find(:xpath, "//input[@id='form_terms_of_use']")['checked'].should be_true
13
- end
14
-
15
- it "should be false if unchecked" do
16
- @session.find(:xpath, "//input[@id='form_terms_of_use']")['checked'].should be_false
17
- end
14
+ it "should be false if unchecked" do
15
+ @session.find(:xpath, "//input[@id='form_terms_of_use']")['checked'].should be_false
18
16
  end
17
+ end
19
18
 
20
- describe "checking" do
21
- it "should not change an already checked checkbox" do
22
- @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_true
23
- @session.check('form_pets_dog')
24
- @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_true
25
- end
26
-
27
- it "should check an unchecked checkbox" do
28
- @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_false
29
- @session.check('form_pets_cat')
30
- @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_true
31
- end
19
+ describe "checking" do
20
+ it "should not change an already checked checkbox" do
21
+ @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_true
22
+ @session.check('form_pets_dog')
23
+ @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_true
32
24
  end
33
25
 
34
- describe "unchecking" do
35
- it "should not change an already unchecked checkbox" do
36
- @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_false
37
- @session.uncheck('form_pets_cat')
38
- @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_false
39
- end
40
-
41
- it "should uncheck a checked checkbox" do
42
- @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_true
43
- @session.uncheck('form_pets_dog')
44
- @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_false
45
- end
26
+ it "should check an unchecked checkbox" do
27
+ @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_false
28
+ @session.check('form_pets_cat')
29
+ @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_true
46
30
  end
31
+ end
47
32
 
48
- it "should check a checkbox by id" do
49
- @session.check("form_pets_cat")
50
- @session.click_button('awesome')
51
- extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
33
+ describe "unchecking" do
34
+ it "should not change an already unchecked checkbox" do
35
+ @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_false
36
+ @session.uncheck('form_pets_cat')
37
+ @session.find(:xpath, "//input[@id='form_pets_cat']")['checked'].should be_false
52
38
  end
53
39
 
54
- it "should check a checkbox by label" do
55
- @session.check("Cat")
56
- @session.click_button('awesome')
57
- extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
40
+ it "should uncheck a checked checkbox" do
41
+ @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_true
42
+ @session.uncheck('form_pets_dog')
43
+ @session.find(:xpath, "//input[@id='form_pets_dog']")['checked'].should be_false
58
44
  end
45
+ end
46
+
47
+ it "should check a checkbox by id" do
48
+ @session.check("form_pets_cat")
49
+ @session.click_button('awesome')
50
+ extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
51
+ end
52
+
53
+ it "should check a checkbox by label" do
54
+ @session.check("Cat")
55
+ @session.click_button('awesome')
56
+ extract_results(@session)['pets'].should include('dog', 'cat', 'hamster')
57
+ end
59
58
 
60
- context "with a locator that doesn't exist" do
61
- it "should raise an error" do
62
- running { @session.check('does not exist') }.should raise_error(Capybara::ElementNotFound)
63
- end
59
+ context "with a locator that doesn't exist" do
60
+ it "should raise an error" do
61
+ running { @session.check('does not exist') }.should raise_error(Capybara::ElementNotFound)
64
62
  end
65
63
  end
66
64
  end
67
- end
65
+ end
@@ -99,6 +99,15 @@ shared_examples_for "click_button" do
99
99
  it "should not serialize a select tag without options" do
100
100
  @results['tendency'].should be_nil
101
101
  end
102
+
103
+ it "should not submit disabled fields" do
104
+ @results['disabled_text_field'].should be_nil
105
+ @results['disabled_textarea'].should be_nil
106
+ @results['disabled_checkbox'].should be_nil
107
+ @results['disabled_radio'].should be_nil
108
+ @results['disabled_select'].should be_nil
109
+ @results['disabled_file'].should be_nil
110
+ end
102
111
  end
103
112
  end
104
113
 
@@ -0,0 +1,37 @@
1
+ shared_examples_for "click_link_or_button" do
2
+ describe '#click' do
3
+ it "should click on a link" do
4
+ @session.visit('/with_html')
5
+ @session.click_link_or_button('labore')
6
+ @session.body.should include('Bar')
7
+ end
8
+
9
+ it "should click on a button" do
10
+ @session.visit('/form')
11
+ @session.click_link_or_button('awe123')
12
+ extract_results(@session)['first_name'].should == 'John'
13
+ end
14
+
15
+ it "should click on a button with no type attribute" do
16
+ @session.visit('/form')
17
+ @session.click_link_or_button('no_type')
18
+ extract_results(@session)['first_name'].should == 'John'
19
+ end
20
+
21
+ it "should be aliased as click for backward compatibility" do
22
+ Capybara.should_receive(:deprecate).with("click", "click_link_or_button")
23
+ @session.visit('/form')
24
+ @session.click('awe123')
25
+ extract_results(@session)['first_name'].should == 'John'
26
+ end
27
+
28
+ context "with a locator that doesn't exist" do
29
+ it "should raise an error" do
30
+ @session.visit('/with_html')
31
+ running do
32
+ @session.click_link_or_button('does not exist')
33
+ end.should raise_error(Capybara::ElementNotFound)
34
+ end
35
+ end
36
+ end
37
+ end