capybara 0.4.0.rc → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +16 -1
- data/README.rdoc +16 -7
- data/lib/capybara.rb +41 -1
- data/lib/capybara/driver/celerity_driver.rb +1 -1
- data/lib/capybara/driver/rack_test_driver.rb +1 -0
- data/lib/capybara/driver/selenium_driver.rb +3 -3
- data/lib/capybara/selector.rb +29 -11
- data/lib/capybara/session.rb +1 -1
- data/lib/capybara/spec/session/click_link_spec.rb +12 -7
- data/lib/capybara/spec/session/find_spec.rb +8 -3
- data/lib/capybara/spec/views/with_html.erb +5 -0
- data/lib/capybara/version.rb +1 -1
- metadata +7 -12
data/History.txt
CHANGED
@@ -1,6 +1,21 @@
|
|
1
|
+
# Version 0.4.0
|
2
|
+
|
3
|
+
Release date: 2010-10-22
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
|
7
|
+
* The Selector API was changed slightly, use Capybara.add_selector, see README
|
8
|
+
|
9
|
+
### Fixed
|
10
|
+
|
11
|
+
* Celerity driver is registered properly
|
12
|
+
* has_selector? and has_no_selector? added to DSL
|
13
|
+
* Multiple selects return correct values under C[cu]lerity
|
14
|
+
* Naked query strings are handled correctly by rack-test
|
15
|
+
|
1
16
|
# Version 0.4.0.rc
|
2
17
|
|
3
|
-
Release date:
|
18
|
+
Release date: 2010-10-12
|
4
19
|
|
5
20
|
### Changed
|
6
21
|
|
data/README.rdoc
CHANGED
@@ -382,19 +382,28 @@ Alternatively you can set the default selector to XPath:
|
|
382
382
|
Capybara allows you to add custom selectors, which can be very useful if you
|
383
383
|
find yourself using the same kinds of selectors very often:
|
384
384
|
|
385
|
-
Capybara
|
386
|
-
|
385
|
+
Capybara.add_selector(:id) do
|
386
|
+
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
387
|
+
end
|
388
|
+
|
389
|
+
Capybara.add_selector(:row) do
|
390
|
+
xpath { |num| ".//tbody/tr[#{num}]" }
|
391
|
+
end
|
387
392
|
|
388
|
-
|
389
|
-
generated through the XPath gem. You can now use these
|
393
|
+
The block given to xpath must always return an XPath expression as a String, or
|
394
|
+
an XPath expression generated through the XPath gem. You can now use these
|
395
|
+
selectors like this:
|
390
396
|
|
391
397
|
find(:id, 'post_123')
|
392
398
|
find(:row, 3)
|
393
399
|
|
394
|
-
You can specify an optional
|
395
|
-
selector if it matches the argument
|
400
|
+
You can specify an optional match option which will automatically use the
|
401
|
+
selector if it matches the argument:
|
396
402
|
|
397
|
-
Capybara
|
403
|
+
Capybara.add_selector(:id) do
|
404
|
+
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
405
|
+
match { |value| value.is_a?(Symbol) }
|
406
|
+
end
|
398
407
|
|
399
408
|
Now use it like this:
|
400
409
|
|
data/lib/capybara.rb
CHANGED
@@ -64,6 +64,46 @@ module Capybara
|
|
64
64
|
drivers[name] = block
|
65
65
|
end
|
66
66
|
|
67
|
+
##
|
68
|
+
#
|
69
|
+
# Add a new selector to Capybara. Selectors can be used by various methods in Capybara
|
70
|
+
# to find certain elements on the page in a more convenient way. For example adding a
|
71
|
+
# selector to find certain table rows might look like this:
|
72
|
+
#
|
73
|
+
# Capybara.add_selector(:row) do
|
74
|
+
# xpath { |num| ".//tbody/tr[#{num}]" }
|
75
|
+
# end
|
76
|
+
#
|
77
|
+
# This makes it possible to use this selector in a cariety of ways:
|
78
|
+
#
|
79
|
+
# find(:row, 3)
|
80
|
+
# page.find('table#myTable').find(:row, 3).text
|
81
|
+
# page.find('table#myTable').has_selector?(:row, 3)
|
82
|
+
# within(:row, 3) { page.should have_content('$100.000') }
|
83
|
+
#
|
84
|
+
# It might be convenient to specify that the selector is automatically chosen for certain
|
85
|
+
# values. This way you don't have to explicitely specify that you are looking for a row, or
|
86
|
+
# an id. Let's say we want Capybara to treat any Symbols sent into methods like find to be
|
87
|
+
# treated as though they were element ids. We could achieve this like so:
|
88
|
+
#
|
89
|
+
# Capybara.add_selector(:id) do
|
90
|
+
# xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
91
|
+
# match { |value| value.is_a?(Symbol) }
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# Now we can retrieve elements by id like this:
|
95
|
+
#
|
96
|
+
# find(:post_123)
|
97
|
+
#
|
98
|
+
# Note that this particular selector already ships with Capybara.
|
99
|
+
#
|
100
|
+
# @param [Symbol] name The name of the selector to add
|
101
|
+
# @yield A block executed in the context of the new {Capybara::Selector}
|
102
|
+
#
|
103
|
+
def add_selector(name, &block)
|
104
|
+
Capybara::Selector.add(name, &block)
|
105
|
+
end
|
106
|
+
|
67
107
|
def drivers
|
68
108
|
@drivers ||= {}
|
69
109
|
end
|
@@ -103,7 +143,7 @@ Capybara.register_driver :rack_test do |app|
|
|
103
143
|
end
|
104
144
|
|
105
145
|
Capybara.register_driver :celerity do |app|
|
106
|
-
Capybara::Driver::
|
146
|
+
Capybara::Driver::Celerity.new(app)
|
107
147
|
end
|
108
148
|
|
109
149
|
Capybara.register_driver :culerity do |app|
|
@@ -185,6 +185,7 @@ class Capybara::Driver::RackTest < Capybara::Driver::Base
|
|
185
185
|
|
186
186
|
def process(method, path, attributes = {})
|
187
187
|
return if path.gsub(/^#{request_path}/, '') =~ /^#/
|
188
|
+
path = request_path + path if path =~ /^\?/
|
188
189
|
send(method, to_binary(path), to_binary( attributes ), env)
|
189
190
|
follow_redirects!
|
190
191
|
end
|
@@ -8,7 +8,7 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
|
|
8
8
|
|
9
9
|
def [](name)
|
10
10
|
if name == :value
|
11
|
-
|
11
|
+
value
|
12
12
|
else
|
13
13
|
native.attribute(name.to_s)
|
14
14
|
end
|
@@ -17,10 +17,10 @@ class Capybara::Driver::Selenium < Capybara::Driver::Base
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def value
|
20
|
-
if tag_name == "select" and self[:multiple]
|
20
|
+
if tag_name == "select" and self[:multiple] and not self[:multiple] == "false"
|
21
21
|
native.find_elements(:xpath, ".//option").select { |n| n.selected? }.map { |n| n.value || n.text }
|
22
22
|
else
|
23
|
-
|
23
|
+
native.value
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
data/lib/capybara/selector.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
module Capybara
|
2
2
|
class Selector
|
3
|
-
attr_reader :name
|
3
|
+
attr_reader :name
|
4
4
|
|
5
5
|
class << self
|
6
6
|
def all
|
7
7
|
@selectors ||= {}
|
8
8
|
end
|
9
9
|
|
10
|
-
def add(name,
|
11
|
-
all[name.to_sym] = Capybara::Selector.new(name.to_sym,
|
10
|
+
def add(name, &block)
|
11
|
+
all[name.to_sym] = Capybara::Selector.new(name.to_sym, &block)
|
12
12
|
end
|
13
13
|
|
14
14
|
def remove(name)
|
@@ -31,22 +31,40 @@ module Capybara
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def initialize(name,
|
34
|
+
def initialize(name, &block)
|
35
35
|
@name = name
|
36
|
-
|
37
|
-
|
36
|
+
instance_eval(&block)
|
37
|
+
end
|
38
|
+
|
39
|
+
def xpath(&block)
|
40
|
+
@xpath = block if block
|
41
|
+
@xpath
|
42
|
+
end
|
43
|
+
|
44
|
+
def match(&block)
|
45
|
+
@match = block if block
|
46
|
+
@match
|
38
47
|
end
|
39
48
|
|
40
49
|
def call(locator)
|
41
|
-
@
|
50
|
+
@xpath.call(locator)
|
42
51
|
end
|
43
52
|
|
44
53
|
def match?(locator)
|
45
|
-
@
|
54
|
+
@match and @match.call(locator)
|
46
55
|
end
|
47
56
|
end
|
48
57
|
end
|
49
58
|
|
50
|
-
Capybara
|
51
|
-
|
52
|
-
|
59
|
+
Capybara.add_selector(:xpath) do
|
60
|
+
xpath { |xpath| xpath }
|
61
|
+
end
|
62
|
+
|
63
|
+
Capybara.add_selector(:css) do
|
64
|
+
xpath { |css| XPath.css(css) }
|
65
|
+
end
|
66
|
+
|
67
|
+
Capybara.add_selector(:id) do
|
68
|
+
xpath { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
|
69
|
+
match { |value| value.is_a?(Symbol) }
|
70
|
+
end
|
data/lib/capybara/session.rb
CHANGED
@@ -32,7 +32,7 @@ module Capybara
|
|
32
32
|
:has_no_content?, :has_no_css?, :has_no_xpath?, :has_xpath?, :locate, :save_and_open_page, :select, :source, :uncheck,
|
33
33
|
:visit, :wait_until, :within, :within_fieldset, :within_table, :within_frame, :within_window, :has_link?, :has_no_link?, :has_button?,
|
34
34
|
:has_no_button?, :has_field?, :has_no_field?, :has_checked_field?, :has_unchecked_field?, :has_no_table?, :has_table?,
|
35
|
-
:unselect, :has_select?, :has_no_select?, :current_path, :
|
35
|
+
:unselect, :has_select?, :has_no_select?, :current_path, :click, :has_selector?, :has_no_selector?
|
36
36
|
]
|
37
37
|
|
38
38
|
attr_reader :mode, :app
|
@@ -16,7 +16,7 @@ shared_examples_for "click_link" do
|
|
16
16
|
@session.click_link('labore')
|
17
17
|
@session.body.should include('Bar')
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
it "should accept partial matches" do
|
21
21
|
@session.click_link('abo')
|
22
22
|
@session.body.should include('Bar')
|
@@ -38,7 +38,7 @@ shared_examples_for "click_link" do
|
|
38
38
|
@session.click_link('some tit')
|
39
39
|
@session.body.should include('Bar')
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
it "should prefer exact matches over partial matches" do
|
43
43
|
@session.click_link('a fine link')
|
44
44
|
@session.body.should include('Bar')
|
@@ -74,12 +74,17 @@ shared_examples_for "click_link" do
|
|
74
74
|
@session.click_link('Redirect')
|
75
75
|
@session.body.should include('You landed')
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
it "should follow redirects" do
|
79
79
|
@session.click_link('BackToMyself')
|
80
80
|
@session.body.should include('This is a test')
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
|
+
it "should add query string to current URL with naked query string" do
|
84
|
+
@session.click_link('Naked Query String')
|
85
|
+
@session.body.should include('Query String sent')
|
86
|
+
end
|
87
|
+
|
83
88
|
it "should do nothing on anchor links" do
|
84
89
|
@session.fill_in("test_field", :with => 'blah')
|
85
90
|
@session.click_link('Anchor')
|
@@ -87,18 +92,18 @@ shared_examples_for "click_link" do
|
|
87
92
|
@session.click_link('Blank Anchor')
|
88
93
|
@session.find_field("test_field").value.should == 'blah'
|
89
94
|
end
|
90
|
-
|
95
|
+
|
91
96
|
it "should do nothing on URL+anchor links for the same page" do
|
92
97
|
@session.fill_in("test_field", :with => 'blah')
|
93
98
|
@session.click_link('Anchor on same page')
|
94
99
|
@session.find_field("test_field").value.should == 'blah'
|
95
100
|
end
|
96
|
-
|
101
|
+
|
97
102
|
it "should follow link on URL+anchor links for a different page" do
|
98
103
|
@session.click_link('Anchor on different page')
|
99
104
|
@session.body.should include('Bar')
|
100
105
|
end
|
101
|
-
|
106
|
+
|
102
107
|
it "raise an error with links with no href" do
|
103
108
|
running do
|
104
109
|
@session.click_link('No Href')
|
@@ -64,7 +64,9 @@ shared_examples_for "find" do
|
|
64
64
|
|
65
65
|
context "with custom selector" do
|
66
66
|
it "should use the custom selector" do
|
67
|
-
Capybara
|
67
|
+
Capybara.add_selector(:monkey) do
|
68
|
+
xpath { |name| ".//*[@id='#{name}_monkey']" }
|
69
|
+
end
|
68
70
|
@session.find(:monkey, 'john').text.should == 'Monkey John'
|
69
71
|
@session.find(:monkey, 'paul').text.should == 'Monkey Paul'
|
70
72
|
end
|
@@ -72,7 +74,10 @@ shared_examples_for "find" do
|
|
72
74
|
|
73
75
|
context "with custom selector with :for option" do
|
74
76
|
it "should use the selector when it matches the :for option" do
|
75
|
-
Capybara
|
77
|
+
Capybara.add_selector(:monkey) do
|
78
|
+
xpath { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
|
79
|
+
match { |value| value.is_a?(Fixnum) }
|
80
|
+
end
|
76
81
|
@session.find(:monkey, '2').text.should == 'Monkey Paul'
|
77
82
|
@session.find(1).text.should == 'Monkey John'
|
78
83
|
@session.find(2).text.should == 'Monkey Paul'
|
@@ -115,7 +120,7 @@ shared_examples_for "find" do
|
|
115
120
|
it "should find the first element using the given locator" do
|
116
121
|
@session.within(:xpath, "//div[@id='for_bar']") do
|
117
122
|
@session.find('.//li').text.should =~ /With Simple HTML/
|
118
|
-
end
|
123
|
+
end
|
119
124
|
end
|
120
125
|
end
|
121
126
|
end
|
@@ -35,6 +35,11 @@
|
|
35
35
|
<input type="text" checked="checked" id="checked_field">
|
36
36
|
<a href="/redirect"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="very fine image" /></a>
|
37
37
|
<a href="/with_simple_html"><img src="http://www.foobar.sun/dummy_image.jpg" width="20" height="20" alt="fine image" /></a>
|
38
|
+
|
39
|
+
<a href="?query_string=true">Naked Query String</a>
|
40
|
+
<% if params[:query_string] %>
|
41
|
+
<em>Query String sent</em>
|
42
|
+
<% end %>
|
38
43
|
</p>
|
39
44
|
|
40
45
|
<div id="hidden" style="display: none;">
|
data/lib/capybara/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 4
|
8
8
|
- 0
|
9
|
-
|
10
|
-
version: 0.4.0.rc
|
9
|
+
version: 0.4.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Jonas Nicklas
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-22 00:00:00 +02:00
|
19
18
|
default_executable:
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
@@ -164,9 +163,7 @@ dependencies:
|
|
164
163
|
- 2
|
165
164
|
- 0
|
166
165
|
- 0
|
167
|
-
|
168
|
-
- 22
|
169
|
-
version: 2.0.0.beta.22
|
166
|
+
version: 2.0.0
|
170
167
|
type: :development
|
171
168
|
version_requirements: *id010
|
172
169
|
- !ruby/object:Gem::Dependency
|
@@ -321,13 +318,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
321
318
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
322
319
|
none: false
|
323
320
|
requirements:
|
324
|
-
- - "
|
321
|
+
- - ">="
|
325
322
|
- !ruby/object:Gem::Version
|
326
323
|
segments:
|
327
|
-
-
|
328
|
-
|
329
|
-
- 1
|
330
|
-
version: 1.3.1
|
324
|
+
- 0
|
325
|
+
version: "0"
|
331
326
|
requirements: []
|
332
327
|
|
333
328
|
rubyforge_project: capybara
|