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.
@@ -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
 
@@ -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::Selector.add(:id) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
386
- Capybara::Selector.add(:row) { |num| ".//tbody/tr[#{num}]" }
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
- These must always return an XPath expression as a String, or an XPath expression
389
- generated through the XPath gem. You can now use these selectors like this:
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 :for option which will automatically use the
395
- selector if it matches the argument to find using ===:
400
+ You can specify an optional match option which will automatically use the
401
+ selector if it matches the argument:
396
402
 
397
- Capybara::Selector.add(:id, :for => Symbol) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
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
 
@@ -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::Culerity.new(app)
146
+ Capybara::Driver::Celerity.new(app)
107
147
  end
108
148
 
109
149
  Capybara.register_driver :culerity do |app|
@@ -15,7 +15,7 @@ class Capybara::Driver::Celerity < Capybara::Driver::Base
15
15
 
16
16
  def value
17
17
  if tag_name == "select" and native.multiple?
18
- native.selected_options
18
+ find(".//option[@selected]").map { |n| n.value || n.text }
19
19
  else
20
20
  self[:value]
21
21
  end
@@ -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
- native.value
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
- self[:value]
23
+ native.value
24
24
  end
25
25
  end
26
26
 
@@ -1,14 +1,14 @@
1
1
  module Capybara
2
2
  class Selector
3
- attr_reader :name, :options, :block
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, options={}, &block)
11
- all[name.to_sym] = Capybara::Selector.new(name.to_sym, options, &block)
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, options={}, &block)
34
+ def initialize(name, &block)
35
35
  @name = name
36
- @options = options
37
- @block = block
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
- @block.call(locator)
50
+ @xpath.call(locator)
42
51
  end
43
52
 
44
53
  def match?(locator)
45
- @options[:for] and @options[:for] === locator
54
+ @match and @match.call(locator)
46
55
  end
47
56
  end
48
57
  end
49
58
 
50
- Capybara::Selector.add(:xpath) { |xpath| xpath }
51
- Capybara::Selector.add(:css) { |css| XPath.css(css) }
52
- Capybara::Selector.add(:id, :for => Symbol) { |id| XPath.descendant[XPath.attr(:id) == id.to_s] }
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
@@ -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, :scope_to, :click
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::Selector.add(:monkey) { |name| ".//*[@id='#{name}_monkey']" }
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::Selector.add(:monkey, :for => Fixnum) { |num| ".//*[contains(@id, 'monkey')][#{num}]" }
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;">
@@ -1,3 +1,3 @@
1
1
  module Capybara
2
- VERSION = '0.4.0.rc'
2
+ VERSION = '0.4.0'
3
3
  end
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: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 0
7
7
  - 4
8
8
  - 0
9
- - rc
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-12 00:00:00 +02:00
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
- - beta
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
- - 1
328
- - 3
329
- - 1
330
- version: 1.3.1
324
+ - 0
325
+ version: "0"
331
326
  requirements: []
332
327
 
333
328
  rubyforge_project: capybara