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.
- data/History.txt +35 -0
- data/README.rdoc +60 -19
- data/lib/capybara.rb +81 -5
- data/lib/capybara/driver/base.rb +1 -6
- data/lib/capybara/driver/celerity_driver.rb +19 -9
- data/lib/capybara/driver/node.rb +8 -0
- data/lib/capybara/driver/rack_test_driver.rb +42 -29
- data/lib/capybara/driver/selenium_driver.rb +11 -3
- data/lib/capybara/dsl.rb +11 -0
- data/lib/capybara/node/actions.rb +4 -14
- data/lib/capybara/node/base.rb +47 -0
- data/lib/capybara/node/document.rb +17 -0
- data/lib/capybara/node/element.rb +178 -0
- data/lib/capybara/node/finders.rb +78 -27
- data/lib/capybara/node/matchers.rb +40 -11
- data/lib/capybara/node/simple.rb +116 -0
- data/lib/capybara/rspec.rb +18 -0
- data/lib/capybara/server.rb +5 -10
- data/lib/capybara/session.rb +7 -16
- data/lib/capybara/spec/driver.rb +16 -1
- data/lib/capybara/spec/session.rb +1 -0
- data/lib/capybara/spec/session/all_spec.rb +5 -0
- data/lib/capybara/spec/session/attach_file_spec.rb +6 -0
- data/lib/capybara/spec/session/click_link_or_button_spec.rb +2 -3
- data/lib/capybara/spec/session/find_spec.rb +0 -6
- data/lib/capybara/spec/session/first_spec.rb +72 -0
- data/lib/capybara/spec/session/has_css_spec.rb +107 -1
- data/lib/capybara/spec/session/has_field_spec.rb +60 -0
- data/lib/capybara/spec/session/has_select_spec.rb +40 -0
- data/lib/capybara/spec/session/javascript.rb +4 -13
- data/lib/capybara/spec/session/within_spec.rb +10 -3
- data/lib/capybara/spec/test_app.rb +20 -1
- data/lib/capybara/spec/views/form.erb +27 -0
- data/lib/capybara/spec/views/with_html.erb +21 -5
- data/lib/capybara/util/save_and_open_page.rb +8 -5
- data/lib/capybara/version.rb +1 -1
- data/spec/basic_node_spec.rb +77 -0
- data/spec/capybara_spec.rb +18 -0
- data/spec/dsl_spec.rb +26 -0
- data/spec/rspec_spec.rb +47 -0
- data/spec/save_and_open_page_spec.rb +83 -7
- data/spec/server_spec.rb +20 -0
- data/spec/session/rack_test_session_spec.rb +10 -0
- data/spec/string_spec.rb +77 -0
- metadata +306 -295
- 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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
36
|
+
return response_html
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
data/lib/capybara/version.rb
CHANGED
@@ -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
|
data/spec/capybara_spec.rb
CHANGED
@@ -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"
|
data/spec/rspec_spec.rb
ADDED
@@ -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 ".
|
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
|
-
|
28
|
-
|
29
|
-
@name = "capybara-#{@time}.html"
|
43
|
+
def default_file_expectations
|
44
|
+
@name = "capybara-#{@time}.html"
|
30
45
|
|
31
|
-
|
46
|
+
@temp_file.stub!(:path).and_return(@name)
|
32
47
|
|
33
|
-
|
34
|
-
|
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"
|
data/spec/string_spec.rb
ADDED
@@ -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
|