capybara 0.4.0.rc → 0.4.0

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.
@@ -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