capybara 2.9.0 → 2.9.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 074717523be47e7a162c2d4bc45f5ff49737e6a8
4
- data.tar.gz: 25c95e6c9273c09663933921ba177067e622ea65
3
+ metadata.gz: cc4841dedf9ca38322cb47a786b24f8628e62fd2
4
+ data.tar.gz: be5ea00f82b66a46769eab36218b26be66dda267
5
5
  SHA512:
6
- metadata.gz: d1db39b289e31ac1432a30cbe5ff8ce957867e1b3fd854813d8bfa954af0babb5a89ac1ccfa21ff6d5074b112a69e4b6deb751bc9c054026bad65d9a2f7d6e0d
7
- data.tar.gz: 635c3bfb9e2d366ad8bc87a2abe075f2286e496fd2171bf32e6ef6628a55f8f95dfee2fd8e326819ca81d1dc0c85ac0dfee86d0491c5710e5c53f6e756e50c65
6
+ metadata.gz: 266ef0ca4cec47b1692544d070b6cf467f366d52d4675dae21b2e2cce3985f9ea8a5b268f70d71e290cabe4f0fbf7134b39283e2ea180cabd7610d7c34ec06f7
7
+ data.tar.gz: d4ec85892ef15b4f1fee2b51b8b52a51119baaaf2a09b0abb096621197608e545036c0146cbcb64d860736cf014bb375186fec6d4f13d66e04e79959e174470c
data/History.md CHANGED
@@ -1,3 +1,10 @@
1
+ #Version 2.9.1
2
+ Release date: 2016-09-23
3
+
4
+ ### Fixed
5
+ * allow_label_click option did not work in some cases with Poltergeist - Issue #1762 [Thomas Walpole]
6
+ * matches_selector? should have access to all of a selectors options except the count options [Thomas Walpole]
7
+
1
8
  #Version 2.9.0
2
9
  Release date: 2016-09-19
3
10
 
data/README.md CHANGED
@@ -781,7 +781,7 @@ module MyModule
781
781
  include Capybara::DSL
782
782
 
783
783
  def login!
784
- within("//form[@id='session']") do
784
+ within(:xpath, "//form[@id='session']") do
785
785
  fill_in 'Email', :with => 'user@example.com'
786
786
  fill_in 'Password', :with => 'password'
787
787
  end
@@ -852,7 +852,7 @@ manually.
852
852
  require 'capybara'
853
853
 
854
854
  session = Capybara::Session.new(:webkit, my_rack_app)
855
- session.within("//form[@id='session']") do
855
+ session.within("form#session") do
856
856
  session.fill_in 'Email', :with => 'user@example.com'
857
857
  session.fill_in 'Password', :with => 'password'
858
858
  end
@@ -109,11 +109,12 @@ module Capybara
109
109
  allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
110
110
 
111
111
  begin
112
- find(:radio_button, locator, options).set(true)
113
- rescue Capybara::ElementNotFound => e
114
- raise unless allow_label_click
112
+ radio = find(:radio_button, locator, options)
113
+ radio.set(true)
114
+ rescue => e
115
+ raise unless allow_label_click && catch_error?(e)
115
116
  begin
116
- radio = find(:radio_button, locator, options.merge({wait: 0, visible: :hidden}))
117
+ radio ||= find(:radio_button, locator, options.merge({wait: 0, visible: :all}))
117
118
  label = find(:label, for: radio, wait: 0, visible: true)
118
119
  label.click unless radio.checked?
119
120
  rescue
@@ -145,11 +146,12 @@ module Capybara
145
146
  allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
146
147
 
147
148
  begin
148
- find(:checkbox, locator, options).set(true)
149
- rescue Capybara::ElementNotFound => e
150
- raise unless allow_label_click
149
+ cbox = find(:checkbox, locator, options)
150
+ cbox.set(true)
151
+ rescue => e
152
+ raise unless allow_label_click && catch_error?(e)
151
153
  begin
152
- cbox = find(:checkbox, locator, options.merge({wait: 0, visible: :hidden}))
154
+ cbox ||= find(:checkbox, locator, options.merge({wait: 0, visible: :all}))
153
155
  label = find(:label, for: cbox, wait: 0, visible: true)
154
156
  label.click unless cbox.checked?
155
157
  rescue
@@ -181,11 +183,12 @@ module Capybara
181
183
  allow_label_click = options.delete(:allow_label_click) { Capybara.automatic_label_click }
182
184
 
183
185
  begin
184
- find(:checkbox, locator, options).set(false)
185
- rescue Capybara::ElementNotFound => e
186
- raise unless allow_label_click
186
+ cbox = find(:checkbox, locator, options)
187
+ cbox.set(false)
188
+ rescue => e
189
+ raise unless allow_label_click && catch_error?(e)
187
190
  begin
188
- cbox = find(:checkbox, locator, options.merge({wait: 0, visible: :hidden}))
191
+ cbox ||= find(:checkbox, locator, options.merge({wait: 0, visible: :all}))
189
192
  label = find(:label, for: cbox, wait: 0, visible: true)
190
193
  label.click if cbox.checked?
191
194
  rescue
@@ -1,8 +1,6 @@
1
1
  module Capybara
2
2
  module Queries
3
3
  class MatchQuery < Capybara::Queries::SelectorQuery
4
- VALID_KEYS = [:text, :visible, :exact, :wait]
5
-
6
4
  def visible
7
5
  if options.has_key?(:visible)
8
6
  super
@@ -14,7 +12,7 @@ module Capybara
14
12
  private
15
13
 
16
14
  def valid_keys
17
- VALID_KEYS + @selector.custom_filters.keys
15
+ super - COUNT_KEYS
18
16
  end
19
17
  end
20
18
  end
@@ -4,7 +4,7 @@ module Capybara
4
4
  class SelectorQuery < Queries::BaseQuery
5
5
  attr_accessor :selector, :locator, :options, :expression, :find, :negative
6
6
 
7
- VALID_KEYS = COUNT_KEYS + [:text, :visible, :exact, :match, :wait, :filter_set]
7
+ VALID_KEYS = COUNT_KEYS + [:text, :id, :class, :visible, :exact, :match, :wait, :filter_set]
8
8
  VALID_MATCH = [:first, :smart, :prefer_exact, :one]
9
9
 
10
10
  def initialize(*args)
@@ -39,6 +39,8 @@ module Capybara
39
39
  def description
40
40
  @description = String.new("#{label} #{locator.inspect}")
41
41
  @description << " with text #{options[:text].inspect}" if options[:text]
42
+ @description << " with id #{options[:id]}" if options[:id]
43
+ @description << " with classes #{Array(options[:class]).join(',')}]" if options[:class]
42
44
  @description << selector.description(options)
43
45
  @description
44
46
  end
@@ -92,15 +94,16 @@ module Capybara
92
94
 
93
95
  def xpath(exact=nil)
94
96
  exact = self.exact? if exact.nil?
95
- if @expression.respond_to?(:to_xpath) and exact
97
+ expr = if @expression.respond_to?(:to_xpath) and exact
96
98
  @expression.to_xpath(:exact)
97
99
  else
98
100
  @expression.to_s
99
101
  end
102
+ filtered_xpath(expr)
100
103
  end
101
104
 
102
105
  def css
103
- @expression
106
+ filtered_css(@expression)
104
107
  end
105
108
 
106
109
  # @api private
@@ -141,7 +144,7 @@ module Capybara
141
144
  end
142
145
 
143
146
  def custom_keys
144
- query_filters.keys + @selector.expression_filters
147
+ @custom_keys ||= query_filters.keys + @selector.expression_filters
145
148
  end
146
149
 
147
150
  def assert_valid_keys
@@ -151,6 +154,32 @@ module Capybara
151
154
  end
152
155
  end
153
156
 
157
+ def filtered_xpath(expr)
158
+ if options.has_key?(:id) || options.has_key?(:class)
159
+ expr = "(#{expr})"
160
+ expr = "#{expr}[#{XPath.attr(:id) == options[:id]}]" if options.has_key?(:id) && !custom_keys.include?(:id)
161
+ if options.has_key?(:class) && !custom_keys.include?(:class)
162
+ class_xpath = Array(options[:class]).map do |klass|
163
+ "contains(concat(' ',normalize-space(@class),' '),' #{klass} ')"
164
+ end.join(" and ")
165
+ expr = "#{expr}[#{class_xpath}]"
166
+ end
167
+ end
168
+ expr
169
+ end
170
+
171
+ def filtered_css(expr)
172
+ if options.has_key?(:id) || options.has_key?(:class)
173
+ css_selectors = expr.split(',').map(&:rstrip)
174
+ expr = css_selectors.map do |sel|
175
+ sel += "##{Capybara::Selector::CSS.escape(options[:id])}" if options.has_key?(:id) && !custom_keys.include?(:id)
176
+ sel += Array(options[:class]).map { |k| ".#{Capybara::Selector::CSS.escape(k)}"}.join if options.has_key?(:class) && !custom_keys.include?(:class)
177
+ sel
178
+ end.join(", ")
179
+ end
180
+ expr
181
+ end
182
+
154
183
  def warn_exact_usage
155
184
  if options.has_key?(:exact) && !supports_exact?
156
185
  warn "The :exact option only has an effect on queries using the XPath#is method. Using it with the query \"#{expression.to_s}\" has no effect."
@@ -65,7 +65,7 @@ end
65
65
  # @filter [Boolean] :disabled Match disabled field?
66
66
  # @filter [Boolean] :multiple Match fields that accept multiple values
67
67
  Capybara.add_selector(:field) do
68
- xpath(:id, :name, :placeholder, :type, :class) do |locator, options|
68
+ xpath(:name, :placeholder, :type) do |locator, options|
69
69
  xpath = XPath.descendant(:input, :textarea, :select)[~XPath.attr(:type).one_of('submit', 'image', 'hidden')]
70
70
  if options[:type]
71
71
  type=options[:type].to_s
@@ -105,12 +105,10 @@ end
105
105
  # @filter [String, Array<String>] :class Matches the class(es) provided
106
106
  #
107
107
  Capybara.add_selector(:fieldset) do
108
- xpath(:id, :legend, :class) do |locator, options|
108
+ xpath(:legend) do |locator, options|
109
109
  xpath = XPath.descendant(:fieldset)
110
110
  xpath = xpath[XPath.attr(:id).equals(locator.to_s) | XPath.child(:legend)[XPath.string.n.is(locator.to_s)]] unless locator.nil?
111
- xpath = xpath[XPath.attr(:id).equals(options[:id])] if options[:id]
112
111
  xpath = xpath[XPath.child(:legend)[XPath.string.n.is(options[:legend])]] if options[:legend]
113
- xpath = xpath[find_by_attr(:class, options[:class])]
114
112
  xpath
115
113
  end
116
114
  end
@@ -128,7 +126,7 @@ end
128
126
  # @filter [String, Regexp] :href Matches the normalized href of the link
129
127
  #
130
128
  Capybara.add_selector(:link) do
131
- xpath(:id, :title, :alt, :class) do |locator, options={}|
129
+ xpath(:title, :alt) do |locator, options={}|
132
130
  xpath = XPath.descendant(:a)[XPath.attr(:href)]
133
131
  unless locator.nil?
134
132
  locator = locator.to_s
@@ -139,7 +137,7 @@ Capybara.add_selector(:link) do
139
137
  matchers |= XPath.attr(:'aria-label').is(locator) if Capybara.enable_aria_label
140
138
  xpath = xpath[matchers]
141
139
  end
142
- xpath = [:id, :title, :class].inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
140
+ xpath = [:title].inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
143
141
  xpath = xpath[XPath.descendant(:img)[XPath.attr(:alt).equals(options[:alt])]] if options[:alt]
144
142
  xpath
145
143
  end
@@ -167,7 +165,7 @@ end
167
165
  # @filter [String] :value Matches the value of an input button
168
166
  #
169
167
  Capybara.add_selector(:button) do
170
- xpath(:id, :value, :title, :class) do |locator, options={}|
168
+ xpath(:value, :title) do |locator, options={}|
171
169
  input_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).one_of('submit', 'reset', 'image', 'button')]
172
170
  btn_xpath = XPath.descendant(:button)
173
171
  image_btn_xpath = XPath.descendant(:input)[XPath.attr(:type).equals('image')]
@@ -233,7 +231,7 @@ end
233
231
  #
234
232
  Capybara.add_selector(:fillable_field) do
235
233
  label "field"
236
- xpath(:id, :name, :placeholder, :class) do |locator, options|
234
+ xpath(:name, :placeholder) do |locator, options|
237
235
  xpath = XPath.descendant(:input, :textarea)[~XPath.attr(:type).one_of('submit', 'image', 'radio', 'checkbox', 'hidden', 'file')]
238
236
  locate_field(xpath, locator, options)
239
237
  end
@@ -267,7 +265,7 @@ end
267
265
  #
268
266
  Capybara.add_selector(:radio_button) do
269
267
  label "radio button"
270
- xpath(:id, :name, :class) do |locator, options|
268
+ xpath(:name) do |locator, options|
271
269
  xpath = XPath.descendant(:input)[XPath.attr(:type).equals('radio')]
272
270
  locate_field(xpath, locator, options)
273
271
  end
@@ -298,7 +296,7 @@ end
298
296
  # @filter [String] :option Match the value
299
297
  #
300
298
  Capybara.add_selector(:checkbox) do
301
- xpath(:id, :name, :class) do |locator, options|
299
+ xpath(:name) do |locator, options|
302
300
  xpath = XPath.descendant(:input)[XPath.attr(:type).equals('checkbox')]
303
301
  locate_field(xpath, locator, options)
304
302
  end
@@ -332,7 +330,7 @@ end
332
330
  #
333
331
  Capybara.add_selector(:select) do
334
332
  label "select box"
335
- xpath(:id, :name, :placeholder, :class) do |locator, options|
333
+ xpath(:name, :placeholder) do |locator, options|
336
334
  xpath = XPath.descendant(:select)
337
335
  locate_field(xpath, locator, options)
338
336
  end
@@ -408,7 +406,7 @@ end
408
406
  #
409
407
  Capybara.add_selector(:file_field) do
410
408
  label "file field"
411
- xpath(:id, :name, :class) do |locator, options|
409
+ xpath(:name) do |locator, options|
412
410
  xpath = XPath.descendant(:input)[XPath.attr(:type).equals('file')]
413
411
  locate_field(xpath, locator, options)
414
412
  end
@@ -466,17 +464,15 @@ end
466
464
  # @filter [String, Array<String>] :class Matches the class(es) provided
467
465
  #
468
466
  Capybara.add_selector(:table) do
469
- xpath(:id, :caption, :class) do |locator, options|
467
+ xpath(:caption) do |locator, options|
470
468
  xpath = XPath.descendant(:table)
471
469
  xpath = xpath[XPath.attr(:id).equals(locator.to_s) | XPath.descendant(:caption).is(locator.to_s)] unless locator.nil?
472
470
  xpath = xpath[XPath.descendant(:caption).equals(options[:caption])] if options[:caption]
473
- xpath = [:id, :class].inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
474
471
  xpath
475
472
  end
476
473
 
477
474
  describe do |options|
478
475
  desc = String.new
479
- desc << " with id #{options[:id]}" if options[:id]
480
476
  desc << " with caption #{options[:caption]}" if options[:caption]
481
477
  desc
482
478
  end
@@ -492,7 +488,7 @@ end
492
488
  # @filter [String, Array<String>] :class Matches the class(es) provided
493
489
  #
494
490
  Capybara.add_selector(:frame) do
495
- xpath(:id, :name, :class) do |locator, options|
491
+ xpath(:name) do |locator, options|
496
492
  xpath = XPath.descendant(:iframe) + XPath.descendant(:frame)
497
493
  xpath = xpath[XPath.attr(:id).equals(locator.to_s) | XPath.attr(:name).equals(locator)] unless locator.nil?
498
494
  xpath = expression_filters.inject(xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
@@ -501,7 +497,6 @@ Capybara.add_selector(:frame) do
501
497
 
502
498
  describe do |options|
503
499
  desc = String.new
504
- desc << " with id #{options[:id]}" if options[:id]
505
500
  desc << " with name #{options[:name]}" if options[:name]
506
501
  desc
507
502
  end
@@ -0,0 +1,30 @@
1
+ module Capybara
2
+ class Selector
3
+ class CSS
4
+ def self.escape(str)
5
+ out = String.new("")
6
+ value = str.dup
7
+ out << value.slice!(0...1) if value =~ /^[-_]/
8
+ out << if value[0] =~ NMSTART
9
+ value.slice!(0...1)
10
+ else
11
+ escape_char(value.slice!(0...1))
12
+ end
13
+ out << value.gsub(/[^a-zA-Z0-9_-]/) {|c| escape_char c}
14
+ out
15
+ end
16
+
17
+ def self.escape_char(c)
18
+ return "\\%06x" % c.ord() unless c =~ %r{[ -/:-~]}
19
+ "\\#{c}"
20
+ end
21
+
22
+ S = '\u{80}-\u{D7FF}\u{E000}-\u{FFFD}\u{10000}-\u{10FFFF}'
23
+ H = /[0-9a-fA-F]/
24
+ UNICODE = /\\#{H}{1,6}[ \t\r\n\f]?/
25
+ NONASCII = /[#{S}]/
26
+ ESCAPE = /#{UNICODE}|\\[ -~#{S}]/
27
+ NMSTART = /[_a-zA-Z]|#{NONASCII}|#{ESCAPE}/
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require 'capybara/selector/filter_set'
3
+ require 'capybara/selector/css'
3
4
  require 'xpath'
4
5
 
5
6
  #Patch XPath to allow a nil condition in where
@@ -201,7 +202,7 @@ module Capybara
201
202
  locate_xpath += XPath.descendant(:label)[XPath.string.n.is(locator)].descendant(xpath)
202
203
  end
203
204
 
204
- locate_xpath = [:id, :name, :placeholder, :class].inject(locate_xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
205
+ locate_xpath = [:name, :placeholder].inject(locate_xpath) { |memo, ef| memo[find_by_attr(ef, options[ef])] }
205
206
  locate_xpath
206
207
  end
207
208
 
@@ -161,11 +161,20 @@ Capybara::SpecHelper.spec "#check" do
161
161
  expect{@session.check('form_cars_mclaren')}.to raise_error(Capybara::ElementNotFound, 'Unable to find checkbox "form_cars_mclaren"')
162
162
  end
163
163
 
164
- it "should check via the label if allow_label_click == true" do
165
- expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be
166
- @session.check('form_cars_tesla', allow_label_click: true)
167
- @session.click_button('awesome')
168
- expect(extract_results(@session)['cars']).to include('tesla')
164
+ context "with allow_label_click == true" do
165
+ it "should check via the label if input is hidden" do
166
+ expect(@session.find(:checkbox, 'form_cars_tesla', unchecked: true, visible: :hidden)).to be
167
+ @session.check('form_cars_tesla', allow_label_click: true)
168
+ @session.click_button('awesome')
169
+ expect(extract_results(@session)['cars']).to include('tesla')
170
+ end
171
+
172
+ it "should check via the label if input is moved off the left edge of the page" do
173
+ expect(@session.find(:checkbox, 'form_cars_pagani', unchecked: true, visible: :all)).to be
174
+ @session.check('form_cars_pagani', allow_label_click: true)
175
+ @session.click_button('awesome')
176
+ expect(extract_results(@session)['cars']).to include('pagani')
177
+ end
169
178
  end
170
179
  end
171
180
  end
@@ -42,6 +42,12 @@ Capybara::SpecHelper.spec '#match_selector?' do
42
42
  expect(@element.matches_xpath?("//span", text: '42')).to be true
43
43
  expect(@element.matches_xpath?("//span", text: 'Nope')).to be false
44
44
  end
45
+
46
+ it 'should accept selector filters' do
47
+ @session.visit('/form')
48
+ cbox = @session.find(:css, '#form_pets_dog')
49
+ expect(cbox.matches_selector?(:checkbox, id: 'form_pets_dog', option: 'dog', name: 'form[pets][]', checked: true)).to be true
50
+ end
45
51
  end
46
52
 
47
53
  Capybara::SpecHelper.spec '#not_matches_selector?' do
@@ -33,7 +33,7 @@ Capybara::SpecHelper.spec Capybara::Selector do
33
33
  end
34
34
  end
35
35
 
36
- describe "locate_field selectors" do
36
+ describe "field selectors" do
37
37
  it "can find specifically by id" do
38
38
  expect(@session.find(:field, id: 'customer_email').value).to eq "ben@ben.com"
39
39
  end
@@ -5,9 +5,9 @@
5
5
 
6
6
  <p>
7
7
  <label for="form_title">Title</label>
8
- <select name="form[title]" id="form_title">
9
- <option>Mrs</option>
10
- <option>Mr</option>
8
+ <select name="form[title]" id="form_title" class="title">
9
+ <option class="title">Mrs</option>
10
+ <option class="title">Mr</option>
11
11
  <option>Miss</option>
12
12
  <option disabled="disabled">Other</option>
13
13
  </select>
@@ -183,6 +183,8 @@ New line after and before textarea tag
183
183
  <label for="form_cars_tesla">Tesla</label>
184
184
  <input type="checkbox" value="ferrari" name="form[cars][]" id="form_cars_ferrari" checked="checked" style="display: none"/>
185
185
  <label for="form_cars_ferrari">Ferrari</label>
186
+ <input type="checkbox" value="pagani" name="form[cars][]" id="form_cars_pagani" style="position: absolute; left: -9999px"/>
187
+ <label for="form_cars_pagani">Pagani</label>
186
188
  <input type="checkbox" value="ariel" name="form[cars][]" id="form_cars_ariel" style="display: none"/>
187
189
  <label>
188
190
  McLaren
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Capybara
3
- VERSION = '2.9.0'
3
+ VERSION = '2.9.1'
4
4
  end
@@ -18,10 +18,13 @@ RSpec.describe Capybara do
18
18
  <p class="b">Some Content</p>
19
19
  <p class="b"></p>
20
20
  </div>
21
- <input type="checkbox"/>
21
+ <div id="#special">
22
+ </div>
23
+ <input id="2checkbox" class="2checkbox" type="checkbox"/>
22
24
  <input type="radio"/>
23
- <input type="text"/>
24
- <input type="file"/>
25
+ <label for="my_text_input">My Text Input</label>
26
+ <input type="text" name="form[my_text_input]" placeholder="my text" id="my_text_input"/>
27
+ <input type="file" id="file" class=".special file"/>
25
28
  <a href="#">link</a>
26
29
  <fieldset></fieldset>
27
30
  <select>
@@ -42,6 +45,10 @@ RSpec.describe Capybara do
42
45
  css { |css_class| "div.#{css_class}" }
43
46
  filter(:not_empty, boolean: true, default: true, skip_if: :all) { |node, value| value ^ (node.text == '') }
44
47
  end
48
+
49
+ Capybara.add_selector :custom_css_selector do
50
+ css { |selector| selector }
51
+ end
45
52
  end
46
53
 
47
54
  describe "modify_selector" do
@@ -89,6 +96,77 @@ RSpec.describe Capybara do
89
96
  end
90
97
  end
91
98
 
99
+ context "with :id option" do
100
+ it "works with compound css selectors" do
101
+ expect(string.all(:custom_css_selector, "div, h1", id: 'page').size).to eq 1
102
+ expect(string.all(:custom_css_selector, "h1, div", id: 'page').size).to eq 1
103
+ end
104
+
105
+ it "works with 'special' characters" do
106
+ skip "We support old Nokogiris but they have their limits" if Gem::Version.new(Nokogiri::VERSION) < Gem::Version.new('1.6.8')
107
+ expect(string.find(:custom_css_selector, "div", id: "#special")[:id]).to eq '#special'
108
+ expect(string.find(:custom_css_selector, "input", id: "2checkbox")[:id]).to eq '2checkbox'
109
+ end
110
+ end
111
+
112
+ context "with :class option" do
113
+ it "works with compound css selectors" do
114
+ expect(string.all(:custom_css_selector, "div, h1", class: 'a').size).to eq 2
115
+ expect(string.all(:custom_css_selector, "h1, div", class: 'a').size).to eq 2
116
+ end
117
+
118
+ it "works with 'special' characters" do
119
+ skip "We support old Nokogiris but they have their limits" if Gem::Version.new(Nokogiri::VERSION) < Gem::Version.new('1.6.8')
120
+ expect(string.find(:custom_css_selector, "input", class: ".special")[:id]).to eq 'file'
121
+ expect(string.find(:custom_css_selector, "input", class: "2checkbox")[:id]).to eq '2checkbox'
122
+ end
123
+ end
124
+
125
+ # :css, :xpath, :id, :field, :fieldset, :link, :button, :link_or_button, :fillable_field, :radio_button, :checkbox, :select,
126
+ # :option, :file_field, :label, :table, :frame
127
+
128
+ describe ":css selector" do
129
+ it "finds by CSS locator" do
130
+ expect(string.find(:css, "input#my_text_input")[:name]).to eq 'form[my_text_input]'
131
+ end
132
+ end
133
+
134
+ describe ":xpath selector" do
135
+ it "finds by XPath locator" do
136
+ expect(string.find(:xpath, './/input[@id="my_text_input"]')[:name]).to eq 'form[my_text_input]'
137
+ end
138
+ end
139
+
140
+ describe ":id selector" do
141
+ it "finds by locator" do
142
+ expect(string.find(:id, "my_text_input")[:name]).to eq 'form[my_text_input]'
143
+ end
144
+ end
145
+
146
+ describe ":field selector" do
147
+ it "finds by locator" do
148
+ expect(string.find(:field, 'My Text Input')[:id]).to eq 'my_text_input'
149
+ expect(string.find(:field, 'my_text_input')[:id]).to eq 'my_text_input'
150
+ expect(string.find(:field, 'form[my_text_input]')[:id]).to eq 'my_text_input'
151
+ end
152
+
153
+ it "finds by id" do
154
+ expect(string.find(:field, id: 'my_text_input')[:name]).to eq 'form[my_text_input]'
155
+ end
156
+
157
+ it "finds by name" do
158
+ expect(string.find(:field, name: 'form[my_text_input]')[:id]).to eq 'my_text_input'
159
+ end
160
+
161
+ it "finds by placeholder" do
162
+ expect(string.find(:field, placeholder: 'my text')[:id]).to eq 'my_text_input'
163
+ end
164
+
165
+ it "finds by type" do
166
+ expect(string.find(:field, type: 'file')[:id]).to eq 'file'
167
+ end
168
+ end
169
+
92
170
  describe ":option selector" do
93
171
  it "finds disabled options" do
94
172
  expect(string.find(:option, disabled: true).value).to eq 'b'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capybara
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.0
4
+ version: 2.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Walpole
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain:
12
12
  - gem-public_cert.pem
13
- date: 2016-09-19 00:00:00.000000000 Z
13
+ date: 2016-09-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -284,6 +284,7 @@ files:
284
284
  - lib/capybara/rspec/features.rb
285
285
  - lib/capybara/rspec/matchers.rb
286
286
  - lib/capybara/selector.rb
287
+ - lib/capybara/selector/css.rb
287
288
  - lib/capybara/selector/filter.rb
288
289
  - lib/capybara/selector/filter_set.rb
289
290
  - lib/capybara/selector/selector.rb