capybara 0.4.0 → 0.4.1.rc

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 (46) hide show
  1. data/History.txt +35 -0
  2. data/README.rdoc +60 -19
  3. data/lib/capybara.rb +81 -5
  4. data/lib/capybara/driver/base.rb +1 -6
  5. data/lib/capybara/driver/celerity_driver.rb +19 -9
  6. data/lib/capybara/driver/node.rb +8 -0
  7. data/lib/capybara/driver/rack_test_driver.rb +42 -29
  8. data/lib/capybara/driver/selenium_driver.rb +11 -3
  9. data/lib/capybara/dsl.rb +11 -0
  10. data/lib/capybara/node/actions.rb +4 -14
  11. data/lib/capybara/node/base.rb +47 -0
  12. data/lib/capybara/node/document.rb +17 -0
  13. data/lib/capybara/node/element.rb +178 -0
  14. data/lib/capybara/node/finders.rb +78 -27
  15. data/lib/capybara/node/matchers.rb +40 -11
  16. data/lib/capybara/node/simple.rb +116 -0
  17. data/lib/capybara/rspec.rb +18 -0
  18. data/lib/capybara/server.rb +5 -10
  19. data/lib/capybara/session.rb +7 -16
  20. data/lib/capybara/spec/driver.rb +16 -1
  21. data/lib/capybara/spec/session.rb +1 -0
  22. data/lib/capybara/spec/session/all_spec.rb +5 -0
  23. data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
  24. data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -3
  25. data/lib/capybara/spec/session/find_spec.rb +0 -6
  26. data/lib/capybara/spec/session/first_spec.rb +72 -0
  27. data/lib/capybara/spec/session/has_css_spec.rb +107 -1
  28. data/lib/capybara/spec/session/has_field_spec.rb +60 -0
  29. data/lib/capybara/spec/session/has_select_spec.rb +40 -0
  30. data/lib/capybara/spec/session/javascript.rb +4 -13
  31. data/lib/capybara/spec/session/within_spec.rb +10 -3
  32. data/lib/capybara/spec/test_app.rb +20 -1
  33. data/lib/capybara/spec/views/form.erb +27 -0
  34. data/lib/capybara/spec/views/with_html.erb +21 -5
  35. data/lib/capybara/util/save_and_open_page.rb +8 -5
  36. data/lib/capybara/version.rb +1 -1
  37. data/spec/basic_node_spec.rb +77 -0
  38. data/spec/capybara_spec.rb +18 -0
  39. data/spec/dsl_spec.rb +26 -0
  40. data/spec/rspec_spec.rb +47 -0
  41. data/spec/save_and_open_page_spec.rb +83 -7
  42. data/spec/server_spec.rb +20 -0
  43. data/spec/session/rack_test_session_spec.rb +10 -0
  44. data/spec/string_spec.rb +77 -0
  45. metadata +306 -295
  46. data/lib/capybara/node.rb +0 -221
@@ -25,12 +25,15 @@ module Capybara
25
25
  end
26
26
 
27
27
  def rewrite_css_and_image_references(response_html) # :nodoc:
28
- return response_html unless Capybara.asset_root
29
- directories = Dir.new(Capybara.asset_root).entries.inject([]) do |list, name|
30
- list << name if File.directory?(name) and not name.to_s =~ /^\./
31
- list
28
+ root = Capybara.asset_root
29
+ return response_html unless root
30
+ directories = Dir.new(root).entries.select { |name|
31
+ (root+name).directory? and not name.to_s =~ /^\./
32
+ }
33
+ if not directories.empty?
34
+ response_html.gsub!(/("|')\/(#{directories.join('|')})/, '\1' + root.to_s + '/\2')
32
35
  end
33
- response_html.gsub(/("|')\/(#{directories.join('|')})/, '\1' + Capybara.asset_root.to_s + '/\2')
36
+ return response_html
34
37
  end
35
38
  end
36
39
  end
@@ -1,3 +1,3 @@
1
1
  module Capybara
2
- VERSION = '0.4.0'
2
+ VERSION = '0.4.1.rc'
3
3
  end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara do
4
+ describe '.string' do
5
+ let :string do
6
+ Capybara.string <<-STRING
7
+ <div id="page">
8
+ <div id="content">
9
+ <h1 data="fantastic">Awesome</h1>
10
+ <p>Yes it is</p>
11
+ </div>
12
+
13
+ <div id="footer" style="display: none">
14
+ <p>c2010</p>
15
+ <p>Jonas Nicklas</p>
16
+ <input type="text" name="foo" value="bar"/>
17
+ <select name="animal">
18
+ <option>Monkey</option>
19
+ <option selected="selected">Capybara</option>
20
+ </select>
21
+ </div>
22
+ </div>
23
+ STRING
24
+ end
25
+
26
+ it "allows using matchers" do
27
+ string.should have_css('#page')
28
+ string.should_not have_css('#does-not-exist')
29
+ end
30
+
31
+ it "allows using custom matchers" do
32
+ Capybara.add_selector :lifeform do
33
+ xpath { |name| "//option[contains(.,'#{name}')]" }
34
+ end
35
+ string.should have_selector(:page)
36
+ string.should_not have_selector(:'does-not-exist')
37
+ string.should have_selector(:lifeform, "Monkey")
38
+ string.should_not have_selector(:lifeform, "Gorilla")
39
+ end
40
+
41
+ it "allows using matchers with text option" do
42
+ string.should have_css('h1', :text => 'Awesome')
43
+ string.should_not have_css('h1', :text => 'Not so awesome')
44
+ end
45
+
46
+ it "allows finding only visible nodes" do
47
+ string.all('//p', :text => 'c2010', :visible => true).should be_empty
48
+ string.all('//p', :text => 'c2010', :visible => false).should have(1).element
49
+ end
50
+
51
+ it "allows finding elements and extracting text from them" do
52
+ string.find('//h1').text.should == 'Awesome'
53
+ end
54
+
55
+ it "allows finding elements and extracting attributes from them" do
56
+ string.find('//h1')[:data].should == 'fantastic'
57
+ end
58
+
59
+ it "allows finding elements and extracting the tag name from them" do
60
+ string.find('//h1').tag_name.should == 'h1'
61
+ end
62
+
63
+ it "allows finding elements and extracting the path" do
64
+ string.find('//h1').path.should == '/html/body/div/div[1]/h1'
65
+ end
66
+
67
+ it "allows finding elements and extracting the path" do
68
+ string.find('//input').value.should == 'bar'
69
+ string.find('//select').value.should == 'Capybara'
70
+ end
71
+
72
+ it "allows finding elements and checking if they are visible" do
73
+ string.find('//h1').should be_visible
74
+ string.find('//input').should_not be_visible
75
+ end
76
+ end
77
+ end
@@ -25,4 +25,22 @@ describe Capybara do
25
25
  end
26
26
  end
27
27
 
28
+ describe ".server" do
29
+ after do
30
+ Capybara.server {|app, port| Capybara.run_default_server(app, port)}
31
+ end
32
+
33
+ it "should default to a proc that calls run_default_server" do
34
+ mock_app = mock('app')
35
+ Capybara.should_receive(:run_default_server).with(mock_app, 8000)
36
+ Capybara.server.call(mock_app, 8000)
37
+ end
38
+
39
+ it "should return a custom server proc" do
40
+ server = lambda {|app, port|}
41
+ Capybara.server(&server)
42
+ Capybara.server.should == server
43
+ end
44
+ end
45
+
28
46
  end
data/spec/dsl_spec.rb CHANGED
@@ -56,6 +56,32 @@ describe Capybara do
56
56
  end
57
57
  end
58
58
 
59
+ describe '#using_driver' do
60
+ before do
61
+ Capybara.current_driver.should_not == :selenium
62
+ end
63
+
64
+ it 'should set the driver using Capybara.current_driver=' do
65
+ driver = nil
66
+ Capybara.using_driver(:selenium) { driver = Capybara.current_driver }
67
+ driver.should == :selenium
68
+ end
69
+
70
+ it 'should reset the driver using Capybara.use_default_driver, even if an exception occurs' do
71
+ begin
72
+ Capybara.using_driver(:selenium) { raise "ohnoes!" }
73
+ rescue Exception
74
+ end
75
+ Capybara.current_driver.should == Capybara.default_driver
76
+ end
77
+
78
+ it 'should yield the passed block' do
79
+ called = false
80
+ Capybara.using_driver(:selenium) { called = true }
81
+ called.should == true
82
+ end
83
+ end
84
+
59
85
  describe '#app' do
60
86
  it "should be changeable" do
61
87
  Capybara.app = "foobar"
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'capybara/rspec'
3
+
4
+ Capybara.app = TestApp
5
+
6
+ describe 'capybara/rspec', :type => :acceptance do
7
+ it "should include Capybara in rpsec" do
8
+ visit('/foo')
9
+ page.body.should include('Another World')
10
+ end
11
+
12
+ context "resetting session" do
13
+ it "sets a cookie in one example..." do
14
+ visit('/set_cookie')
15
+ page.body.should include('Cookie set to test_cookie')
16
+ end
17
+
18
+ it "...then it is not availbable in the next" do
19
+ visit('/get_cookie')
20
+ page.body.should_not include('test_cookie')
21
+ end
22
+ end
23
+
24
+ context "setting the current driver" do
25
+ it "sets the current driver in one example..." do
26
+ Capybara.current_driver = :selenium
27
+ end
28
+
29
+ it "...then it has returned to the default in the next example" do
30
+ Capybara.current_driver.should == :rack_test
31
+ end
32
+ end
33
+
34
+ it "switches to the javascript driver when giving it as metadata", :js => true do
35
+ Capybara.current_driver.should == Capybara.javascript_driver
36
+ end
37
+
38
+ it "switches to the given driver when giving it as metadata", :driver => :culerity do
39
+ Capybara.current_driver.should == :culerity
40
+ end
41
+ end
42
+
43
+ describe 'capybara/rspec', :type => :other do
44
+ it "should not include Capybara" do
45
+ expect { visit('/') }.to raise_error(NoMethodError)
46
+ end
47
+ end
@@ -3,7 +3,7 @@ require 'spec_helper'
3
3
  require 'capybara/util/save_and_open_page'
4
4
  require 'launchy'
5
5
  describe Capybara do
6
- describe ".save_save_and_open_page" do
6
+ describe ".save_and_open_page" do
7
7
  before do
8
8
  @time = Time.new.strftime("%Y%m%d%H%M%S")
9
9
 
@@ -14,9 +14,25 @@ describe Capybara do
14
14
  @html = <<-HTML
15
15
  <html>
16
16
  <head>
17
+ <script type="text/javascript" src="/javascripts/prototype.js?123"/>
17
18
  </head>
18
19
  <body>
19
20
  <h1>test</h1>
21
+ <p>
22
+ Some images (note differing whitespace closing tag):
23
+ <img src="/images/image1.jpeg" />
24
+ <img src="/images/image2.jpeg"/>
25
+ </p>
26
+ <p>
27
+ Some more in a non-existent directory:
28
+ <img src="/img/image3.jpeg" />
29
+ <img src="/img/image4.jpeg"/>
30
+ </p>
31
+ <p>
32
+ <a href="/not-here/foo.html">
33
+ A link to a file in a non-existent directory.
34
+ </a>
35
+ </p>
20
36
  </body>
21
37
  <html>
22
38
  HTML
@@ -24,14 +40,18 @@ describe Capybara do
24
40
  Launchy::Browser.stub(:run)
25
41
  end
26
42
 
27
- describe "defaults" do
28
- before do
29
- @name = "capybara-#{@time}.html"
43
+ def default_file_expectations
44
+ @name = "capybara-#{@time}.html"
30
45
 
31
- @temp_file.stub!(:path).and_return(@name)
46
+ @temp_file.stub!(:path).and_return(@name)
32
47
 
33
- File.should_receive(:exist?).and_return true
34
- File.should_receive(:new).and_return @temp_file
48
+ File.should_receive(:exist?).and_return true
49
+ File.should_receive(:new).and_return @temp_file
50
+ end
51
+
52
+ describe "defaults" do
53
+ before do
54
+ default_file_expectations
35
55
  end
36
56
 
37
57
  it "should create a new temporary file" do
@@ -79,5 +99,61 @@ describe Capybara do
79
99
  Capybara.save_and_open_page_path = default_setting
80
100
  end
81
101
  end
102
+
103
+ describe "rewrite_css_and_image_references" do
104
+ before do
105
+ default_file_expectations
106
+ @asset_root_dir = "/path/to/rails/public"
107
+ end
108
+
109
+ def mock_asset_root_with(directories)
110
+ @asset_root = Pathname.new(@asset_root_dir)
111
+ Capybara.should_receive(:asset_root).and_return @asset_root
112
+
113
+ dir = mock('asset_root mock dir')
114
+ Dir.should_receive(:new).with(@asset_root).and_return dir
115
+
116
+ dirents = [ '.', '..', 'file.html' ] + directories
117
+ dir.should_receive(:entries).and_return dirents
118
+
119
+ directories_regexp = directories.join('|')
120
+ FileTest.should_receive(:directory?) \
121
+ .at_least(dirents.size - 2).times \
122
+ .and_return { |dir|
123
+ dir =~ %r!#{@asset_root_dir}/(#{directories_regexp})$!
124
+ }
125
+ end
126
+
127
+ def expected_html_for_asset_root_with(directories)
128
+ mock_asset_root_with(directories)
129
+
130
+ expected_html = @html.clone
131
+ if not directories.empty?
132
+ directories_regexp = directories.join('|')
133
+ expected_html.gsub!(/"(\/(#{directories_regexp})\/)/,
134
+ '"%s\1' % @asset_root_dir)
135
+ end
136
+
137
+ return expected_html
138
+ end
139
+
140
+ def test_with_directories(directories)
141
+ @temp_file.should_receive(:write) \
142
+ .with expected_html_for_asset_root_with(directories)
143
+ Capybara.save_and_open_page @html
144
+ end
145
+
146
+ context "asset_root contains some directories" do
147
+ it "should rewrite relative paths to absolute local paths" do
148
+ test_with_directories([ 'javascripts', 'images' ])
149
+ end
150
+ end
151
+
152
+ context "asset_root path contains no directories" do
153
+ it "should not rewrite any relative paths" do
154
+ test_with_directories([ ])
155
+ end
156
+ end
157
+ end
82
158
  end
83
159
  end
data/spec/server_spec.rb CHANGED
@@ -62,4 +62,24 @@ describe Capybara::Server do
62
62
  @server2a.port.should == @server2b.port
63
63
  end
64
64
 
65
+ it "should wait specified time for the app to boot" do
66
+ @slow_app = proc { |env| sleep(1); [200, {}, "Hello Slow Server!"] }
67
+
68
+ Capybara.server_boot_timeout = 1.5
69
+ @server = Capybara::Server.new(@slow_app).boot
70
+
71
+ @res = Net::HTTP.start(@server.host, @server.port) { |http| http.get('/') }
72
+ @res.body.should include('Hello Slow Server')
73
+ end
74
+
75
+ it "should raise an exception if boot timeout is exceeded" do
76
+ @slow_app = proc { |env| sleep(1); [200, {}, "Hello Slow Server!"] }
77
+
78
+ Capybara.server_boot_timeout = 0.5
79
+ server = Capybara::Server.new(@slow_app)
80
+ server.stub(:exit).and_return(:timeout)
81
+ server.stub(:puts)
82
+ server.boot.should == :timeout
83
+ end
84
+
65
85
  end
@@ -26,6 +26,16 @@ describe Capybara::Session do
26
26
  end
27
27
  end
28
28
 
29
+ describe "#attach_file" do
30
+ context "with multipart form" do
31
+ it "should submit an empty form-data section if no file is submitted" do
32
+ @session.visit("/form")
33
+ @session.click_button("Upload Empty")
34
+ @session.body.should include('Successfully ignored empty file field.')
35
+ end
36
+ end
37
+ end
38
+
29
39
  it_should_behave_like "session"
30
40
  it_should_behave_like "session without javascript support"
31
41
  it_should_behave_like "session with headers support"
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara do
4
+ describe '.string' do
5
+ let :string do
6
+ Capybara.string <<-STRING
7
+ <div id="page">
8
+ <div id="content">
9
+ <h1 data="fantastic">Awesome</h1>
10
+ <p>Yes it is</p>
11
+ </div>
12
+
13
+ <div id="footer" style="display: none">
14
+ <p>c2010</p>
15
+ <p>Jonas Nicklas</p>
16
+ <input type="text" name="foo" value="bar"/>
17
+ <select name="animal">
18
+ <option>Monkey</option>
19
+ <option selected="selected">Capybara</option>
20
+ </select>
21
+ </div>
22
+ </div>
23
+ STRING
24
+ end
25
+
26
+ it "allows using matchers" do
27
+ string.should have_css('#page')
28
+ string.should_not have_css('#does-not-exist')
29
+ end
30
+
31
+ it "allows using custom matchers" do
32
+ Capybara.add_selector :lifeform do
33
+ xpath { |name| "//option[contains(.,'#{name}')]" }
34
+ end
35
+ string.should have_selector(:page)
36
+ string.should_not have_selector(:'does-not-exist')
37
+ string.should have_selector(:lifeform, "Monkey")
38
+ string.should_not have_selector(:lifeform, "Gorilla")
39
+ end
40
+
41
+ it "allows using matchers with text option" do
42
+ string.should have_css('h1', :text => 'Awesome')
43
+ string.should_not have_css('h1', :text => 'Not so awesome')
44
+ end
45
+
46
+ it "allows finding only visible nodes" do
47
+ string.all('//p', :text => 'c2010', :visible => true).should be_empty
48
+ string.all('//p', :text => 'c2010', :visible => false).should have(1).element
49
+ end
50
+
51
+ it "allows finding elements and extracting text from them" do
52
+ string.find('//h1').text.should == 'Awesome'
53
+ end
54
+
55
+ it "allows finding elements and extracting attributes from them" do
56
+ string.find('//h1')[:data].should == 'fantastic'
57
+ end
58
+
59
+ it "allows finding elements and extracting the tag name from them" do
60
+ string.find('//h1').tag_name.should == 'h1'
61
+ end
62
+
63
+ it "allows finding elements and extracting the path" do
64
+ string.find('//h1').path.should == '/html/body/div/div[1]/h1'
65
+ end
66
+
67
+ it "allows finding elements and extracting the path" do
68
+ string.find('//input').value.should == 'bar'
69
+ string.find('//select').value.should == 'Capybara'
70
+ end
71
+
72
+ it "allows finding elements and checking if they are visible" do
73
+ string.find('//h1').should be_visible
74
+ string.find('//input').should_not be_visible
75
+ end
76
+ end
77
+ end