capybara 3.11.1 → 3.12.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.
- checksums.yaml +4 -4
- data/History.md +18 -1
- data/README.md +4 -4
- data/lib/capybara.rb +7 -0
- data/lib/capybara/node/element.rb +7 -1
- data/lib/capybara/node/matchers.rb +0 -18
- data/lib/capybara/queries/base_query.rb +1 -1
- data/lib/capybara/queries/selector_query.rb +24 -39
- data/lib/capybara/result.rb +4 -4
- data/lib/capybara/selector.rb +7 -15
- data/lib/capybara/selector/builders/css_builder.rb +59 -27
- data/lib/capybara/selector/builders/xpath_builder.rb +50 -35
- data/lib/capybara/selector/css.rb +7 -7
- data/lib/capybara/selector/filter.rb +1 -0
- data/lib/capybara/selector/filter_set.rb +17 -15
- data/lib/capybara/selector/filters/locator_filter.rb +19 -0
- data/lib/capybara/selector/regexp_disassembler.rb +104 -61
- data/lib/capybara/selector/selector.rb +14 -5
- data/lib/capybara/selenium/driver.rb +14 -9
- data/lib/capybara/selenium/driver_specializations/{marionette_driver.rb → firefox_driver.rb} +3 -3
- data/lib/capybara/selenium/nodes/{marionette_node.rb → firefox_node.rb} +1 -1
- data/lib/capybara/spec/session/all_spec.rb +8 -1
- data/lib/capybara/spec/session/assert_selector_spec.rb +0 -10
- data/lib/capybara/spec/session/click_button_spec.rb +5 -3
- data/lib/capybara/spec/session/click_link_spec.rb +5 -5
- data/lib/capybara/spec/session/find_spec.rb +1 -1
- data/lib/capybara/spec/session/first_spec.rb +1 -1
- data/lib/capybara/spec/session/has_css_spec.rb +7 -0
- data/lib/capybara/spec/session/has_xpath_spec.rb +17 -0
- data/lib/capybara/spec/session/node_spec.rb +10 -3
- data/lib/capybara/spec/session/window/window_spec.rb +2 -2
- data/lib/capybara/spec/spec_helper.rb +1 -2
- data/lib/capybara/spec/views/obscured.erb +3 -0
- data/lib/capybara/version.rb +1 -1
- data/spec/css_builder_spec.rb +99 -0
- data/spec/result_spec.rb +6 -0
- data/spec/selector_spec.rb +26 -1
- data/spec/selenium_spec_chrome.rb +18 -16
- data/spec/selenium_spec_chrome_remote.rb +0 -2
- data/spec/{selenium_spec_marionette.rb → selenium_spec_firefox.rb} +31 -25
- data/spec/selenium_spec_firefox_remote.rb +4 -6
- data/spec/shared_selenium_session.rb +2 -2
- data/spec/spec_helper.rb +5 -5
- data/spec/xpath_builder_spec.rb +91 -0
- metadata +10 -7
@@ -6,10 +6,10 @@ require 'English'
|
|
6
6
|
class Capybara::Selenium::Driver < Capybara::Driver::Base
|
7
7
|
DEFAULT_OPTIONS = {
|
8
8
|
browser: :firefox,
|
9
|
-
clear_local_storage:
|
10
|
-
clear_session_storage:
|
9
|
+
clear_local_storage: nil,
|
10
|
+
clear_session_storage: nil
|
11
11
|
}.freeze
|
12
|
-
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage].freeze
|
12
|
+
SPECIAL_OPTIONS = %i[browser clear_local_storage clear_session_storage timeout].freeze
|
13
13
|
attr_reader :app, :options
|
14
14
|
|
15
15
|
def self.load_selenium
|
@@ -23,6 +23,9 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
|
|
23
23
|
|
24
24
|
def browser
|
25
25
|
@browser ||= begin
|
26
|
+
if options[:timeout]
|
27
|
+
options[:http_client] ||= Selenium::WebDriver::Remote::Http::Default.new(read_timeout: options[:timeout])
|
28
|
+
end
|
26
29
|
processed_options = options.reject { |key, _val| SPECIAL_OPTIONS.include?(key) }
|
27
30
|
Selenium::WebDriver.for(options[:browser], processed_options).tap do |driver|
|
28
31
|
specialize_driver(driver)
|
@@ -260,15 +263,17 @@ private
|
|
260
263
|
end
|
261
264
|
|
262
265
|
def clear_storage
|
263
|
-
clear_session_storage
|
264
|
-
clear_local_storage
|
266
|
+
clear_session_storage unless options[:clear_session_storage] == false
|
267
|
+
clear_local_storage unless options[:clear_local_storage] == false
|
268
|
+
rescue Selenium::WebDriver::Error::JavascriptError # rubocop:disable Lint/HandleExceptions
|
269
|
+
# session/local storage may not be available if on non-http pages (e.g. about:blank)
|
265
270
|
end
|
266
271
|
|
267
272
|
def clear_session_storage
|
268
273
|
if @browser.respond_to? :session_storage
|
269
274
|
@browser.session_storage.clear
|
270
275
|
else
|
271
|
-
warn 'sessionStorage clear requested but is not
|
276
|
+
warn 'sessionStorage clear requested but is not supported by this driver' unless options[:clear_session_storage].nil?
|
272
277
|
end
|
273
278
|
end
|
274
279
|
|
@@ -276,7 +281,7 @@ private
|
|
276
281
|
if @browser.respond_to? :local_storage
|
277
282
|
@browser.local_storage.clear
|
278
283
|
else
|
279
|
-
warn 'localStorage clear requested but is not
|
284
|
+
warn 'localStorage clear requested but is not supported by this driver' unless options[:clear_local_storage].nil?
|
280
285
|
end
|
281
286
|
end
|
282
287
|
|
@@ -353,7 +358,7 @@ private
|
|
353
358
|
extend ChromeDriver
|
354
359
|
when :firefox
|
355
360
|
require 'capybara/selenium/patches/pause_duration_fix' if pause_broken?(sel_driver)
|
356
|
-
extend
|
361
|
+
extend FirefoxDriver if sel_driver.capabilities.is_a?(::Selenium::WebDriver::Remote::W3C::Capabilities)
|
357
362
|
end
|
358
363
|
end
|
359
364
|
|
@@ -396,4 +401,4 @@ private
|
|
396
401
|
end
|
397
402
|
|
398
403
|
require 'capybara/selenium/driver_specializations/chrome_driver'
|
399
|
-
require 'capybara/selenium/driver_specializations/
|
404
|
+
require 'capybara/selenium/driver_specializations/firefox_driver'
|
data/lib/capybara/selenium/driver_specializations/{marionette_driver.rb → firefox_driver.rb}
RENAMED
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'capybara/selenium/nodes/
|
3
|
+
require 'capybara/selenium/nodes/firefox_node'
|
4
4
|
|
5
|
-
module Capybara::Selenium::Driver::
|
5
|
+
module Capybara::Selenium::Driver::FirefoxDriver
|
6
6
|
def resize_window_to(handle, width, height)
|
7
7
|
within_given_window(handle) do
|
8
8
|
# Don't set the size if already set - See https://github.com/mozilla/geckodriver/issues/643
|
@@ -45,6 +45,6 @@ module Capybara::Selenium::Driver::MarionetteDriver
|
|
45
45
|
private
|
46
46
|
|
47
47
|
def build_node(native_node)
|
48
|
-
::Capybara::Selenium::
|
48
|
+
::Capybara::Selenium::FirefoxNode.new(self, native_node)
|
49
49
|
end
|
50
50
|
end
|
@@ -30,7 +30,7 @@ Capybara::SpecHelper.spec '#all' do
|
|
30
30
|
|
31
31
|
it 'should accept an XPath instance', :exact_false do
|
32
32
|
@session.visit('/form')
|
33
|
-
@xpath = Capybara::Selector
|
33
|
+
@xpath = Capybara::Selector[:fillable_field].call('Name')
|
34
34
|
expect(@xpath).to be_a(::XPath::Union)
|
35
35
|
@result = @session.all(@xpath).map(&:value)
|
36
36
|
expect(@result).to include('Smith', 'John', 'John Smith')
|
@@ -135,6 +135,13 @@ Capybara::SpecHelper.spec '#all' do
|
|
135
135
|
it 'should raise ExpectationNotMet when the number of elements founds does not match the expectation' do
|
136
136
|
expect { @session.all(:css, 'h1, p', between: 0..3) }.to raise_error(Capybara::ExpectationNotMet)
|
137
137
|
end
|
138
|
+
|
139
|
+
eval <<~TEST, binding, __FILE__, __LINE__ + 1 if RUBY_VERSION.to_f > 2.5
|
140
|
+
it'treats an endless range as minimum' do
|
141
|
+
expect { @session.all(:css, 'h1, p', between: 2..) }.not_to raise_error
|
142
|
+
expect { @session.all(:css, 'h1, p', between: 5..) }.to raise_error(Capybara::ExpectationNotMet)
|
143
|
+
end
|
144
|
+
TEST
|
138
145
|
end
|
139
146
|
|
140
147
|
context 'with multiple count filters' do
|
@@ -72,16 +72,6 @@ Capybara::SpecHelper.spec '#assert_selector' do
|
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
Capybara::SpecHelper.spec '#refute_selector', requires: [:driver] do
|
76
|
-
it 'should warn not to use' do
|
77
|
-
@session.visit('/with_html')
|
78
|
-
doc = @session.document
|
79
|
-
allow(doc).to receive(:warn)
|
80
|
-
doc.refute_selector(:xpath, '//abbr')
|
81
|
-
expect(doc).to have_received(:warn)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
75
|
Capybara::SpecHelper.spec '#assert_no_selector' do
|
86
76
|
before do
|
87
77
|
@session.visit('/with_html')
|
@@ -5,10 +5,12 @@ Capybara::SpecHelper.spec '#click_button' do
|
|
5
5
|
@session.visit('/form')
|
6
6
|
end
|
7
7
|
|
8
|
-
it 'should wait for asynchronous load', requires: [:js] do
|
8
|
+
it 'should wait for asynchronous load', :focus_, requires: [:js] do
|
9
9
|
@session.visit('/with_js')
|
10
|
-
@session.
|
11
|
-
|
10
|
+
@session.using_wait_time(1.5) do
|
11
|
+
@session.click_link('Click me')
|
12
|
+
@session.click_button('New Here')
|
13
|
+
end
|
12
14
|
end
|
13
15
|
|
14
16
|
it 'casts to string' do
|
@@ -83,7 +83,7 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should raise error if link wasn't found" do
|
86
|
-
expect { @session.click_link('labore', href: 'invalid_href') }.to raise_error(Capybara::ElementNotFound)
|
86
|
+
expect { @session.click_link('labore', href: 'invalid_href') }.to raise_error(Capybara::ElementNotFound, /with href "invalid_href/)
|
87
87
|
end
|
88
88
|
end
|
89
89
|
|
@@ -104,8 +104,8 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
104
104
|
end
|
105
105
|
|
106
106
|
it "should raise an error if no link's href matched the pattern" do
|
107
|
-
expect { @session.click_link('labore', href: /invalid_pattern/) }.to raise_error(Capybara::ElementNotFound)
|
108
|
-
expect { @session.click_link('labore', href: /.+d+/) }.to raise_error(Capybara::ElementNotFound)
|
107
|
+
expect { @session.click_link('labore', href: /invalid_pattern/) }.to raise_error(Capybara::ElementNotFound, %r{with href matching /invalid_pattern/})
|
108
|
+
expect { @session.click_link('labore', href: /.+d+/) }.to raise_error(Capybara::ElementNotFound, /#{Regexp.quote "with href matching /.+d+/"}/)
|
109
109
|
end
|
110
110
|
|
111
111
|
context 'href: nil' do
|
@@ -114,8 +114,8 @@ Capybara::SpecHelper.spec '#click_link' do
|
|
114
114
|
end
|
115
115
|
|
116
116
|
it 'should raise an error if href attribute exists' do
|
117
|
-
expect { @session.click_link('Blank Href', href: nil) }.to raise_error(Capybara::ElementNotFound)
|
118
|
-
expect { @session.click_link('Normal Anchor', href: nil) }.to raise_error(Capybara::ElementNotFound)
|
117
|
+
expect { @session.click_link('Blank Href', href: nil) }.to raise_error(Capybara::ElementNotFound, /with no href attribute/)
|
118
|
+
expect { @session.click_link('Normal Anchor', href: nil) }.to raise_error(Capybara::ElementNotFound, /with no href attribute/)
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|
@@ -224,7 +224,7 @@ Capybara::SpecHelper.spec '#find' do
|
|
224
224
|
|
225
225
|
it 'should accept an XPath instance' do
|
226
226
|
@session.visit('/form')
|
227
|
-
@xpath = Capybara::Selector
|
227
|
+
@xpath = Capybara::Selector[:fillable_field].call('First Name')
|
228
228
|
expect(@xpath).to be_a(::XPath::Union)
|
229
229
|
expect(@session.find(@xpath).value).to eq('John')
|
230
230
|
end
|
@@ -24,7 +24,7 @@ Capybara::SpecHelper.spec '#first' do
|
|
24
24
|
|
25
25
|
it 'should accept an XPath instance' do
|
26
26
|
@session.visit('/form')
|
27
|
-
@xpath = Capybara::Selector
|
27
|
+
@xpath = Capybara::Selector[:fillable_field].call('First Name')
|
28
28
|
expect(@xpath).to be_a(::XPath::Union)
|
29
29
|
expect(@session.first(@xpath).value).to eq('John')
|
30
30
|
end
|
@@ -27,11 +27,15 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
27
27
|
expect(@session).to have_css('h2', id: 'h2one')
|
28
28
|
expect(@session).to have_css('h2')
|
29
29
|
expect(@session).to have_css('h2', id: /h2o/)
|
30
|
+
expect(@session).to have_css('li', id: /john|paul/)
|
30
31
|
end
|
31
32
|
|
32
33
|
it 'should support :class option' do
|
33
34
|
expect(@session).to have_css('li', class: 'guitarist')
|
34
35
|
expect(@session).to have_css('li', class: /guitar/)
|
36
|
+
expect(@session).to have_css('li', class: /guitar|drummer/)
|
37
|
+
expect(@session).to have_css('li', class: %w[beatle guitarist])
|
38
|
+
expect(@session).to have_css('li', class: /.*/)
|
35
39
|
end
|
36
40
|
|
37
41
|
it 'should support case insensitive :class and :id options' do
|
@@ -111,6 +115,9 @@ Capybara::SpecHelper.spec '#has_css?' do
|
|
111
115
|
expect(@session).to have_css('p', count: 3)
|
112
116
|
expect(@session).to have_css('p a#foo', count: 1)
|
113
117
|
expect(@session).to have_css('p a.doesnotexist', count: 0)
|
118
|
+
expect(@session).to have_css('li', class: /guitar|drummer/, count: 4)
|
119
|
+
expect(@session).to have_css('li', id: /john|paul/, class: /guitar|drummer/, count: 2)
|
120
|
+
expect(@session).to have_css('li', class: %w[beatle guitarist], count: 2)
|
114
121
|
end
|
115
122
|
|
116
123
|
it 'should be false if the content occurs a different number of times than the given' do
|
@@ -11,6 +11,20 @@ Capybara::SpecHelper.spec '#has_xpath?' do
|
|
11
11
|
expect(@session).to have_xpath("//p[contains(.,'est')]")
|
12
12
|
end
|
13
13
|
|
14
|
+
it 'should support :id option' do
|
15
|
+
expect(@session).to have_xpath('//h2', id: 'h2one')
|
16
|
+
expect(@session).to have_xpath('//h2')
|
17
|
+
expect(@session).to have_xpath('//h2', id: /h2o/)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should support :class option' do
|
21
|
+
expect(@session).to have_xpath('//li', class: 'guitarist')
|
22
|
+
expect(@session).to have_xpath('//li', class: /guitar/)
|
23
|
+
expect(@session).to have_xpath('//li', class: /guitar|drummer/)
|
24
|
+
expect(@session).to have_xpath('//li', class: %w[beatle guitarist])
|
25
|
+
expect(@session).to have_xpath('//li', class: /.*/)
|
26
|
+
end
|
27
|
+
|
14
28
|
it 'should be false if the given selector is not on the page' do
|
15
29
|
expect(@session).not_to have_xpath('//abbr')
|
16
30
|
expect(@session).not_to have_xpath("//p//a[@id='doesnotexist']")
|
@@ -43,6 +57,9 @@ Capybara::SpecHelper.spec '#has_xpath?' do
|
|
43
57
|
expect(@session).to have_xpath("//p//a[@id='foo']", count: 1)
|
44
58
|
expect(@session).to have_xpath("//p[contains(.,'est')]", count: 1)
|
45
59
|
expect(@session).to have_xpath("//p//a[@id='doesnotexist']", count: 0)
|
60
|
+
expect(@session).to have_xpath('//li', class: /guitar|drummer/, count: 4)
|
61
|
+
expect(@session).to have_xpath('//li', id: /john|paul/, class: /guitar|drummer/, count: 2)
|
62
|
+
expect(@session).to have_xpath('//li', class: %w[beatle guitarist], count: 2)
|
46
63
|
end
|
47
64
|
|
48
65
|
it 'should be false if the content occurs a different number of times than the given' do
|
@@ -406,6 +406,13 @@ Capybara::SpecHelper.spec 'node' do
|
|
406
406
|
expect(locations[:y].to_f).to be_within(1).of(5)
|
407
407
|
end
|
408
408
|
|
409
|
+
it 'should raise error if both x and y values are not passed' do
|
410
|
+
@session.visit('with_js')
|
411
|
+
el = @session.find(:css, '#click-test')
|
412
|
+
expect { el.click(x: 5) }.to raise_error ArgumentError
|
413
|
+
expect { el.click(x: nil, y: 3) }.to raise_error ArgumentError
|
414
|
+
end
|
415
|
+
|
409
416
|
it 'should be able to click a table row', requires: [:js] do
|
410
417
|
@session.visit('/tables')
|
411
418
|
tr = @session.find(:css, '#agent_table tr:first-child').click
|
@@ -416,7 +423,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
416
423
|
@session.visit('/obscured')
|
417
424
|
obscured = @session.find(:css, '#obscured')
|
418
425
|
@session.execute_script <<~JS
|
419
|
-
setTimeout(function(){ $('#cover').hide(); },
|
426
|
+
setTimeout(function(){ $('#cover').hide(); }, 700)
|
420
427
|
JS
|
421
428
|
expect { obscured.click }.not_to raise_error
|
422
429
|
end
|
@@ -468,7 +475,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
468
475
|
@session.visit('/obscured')
|
469
476
|
obscured = @session.find(:css, '#obscured')
|
470
477
|
@session.execute_script <<~JS
|
471
|
-
setTimeout(function(){ $('#cover').hide(); },
|
478
|
+
setTimeout(function(){ $('#cover').hide(); }, 700)
|
472
479
|
JS
|
473
480
|
expect { obscured.double_click }.not_to raise_error
|
474
481
|
end
|
@@ -502,7 +509,7 @@ Capybara::SpecHelper.spec 'node' do
|
|
502
509
|
@session.visit('/obscured')
|
503
510
|
obscured = @session.find(:css, '#obscured')
|
504
511
|
@session.execute_script <<~JS
|
505
|
-
setTimeout(function(){ $('#cover').hide(); },
|
512
|
+
setTimeout(function(){ $('#cover').hide(); }, 700)
|
506
513
|
JS
|
507
514
|
expect { obscured.right_click }.not_to raise_error
|
508
515
|
end
|
@@ -120,7 +120,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
120
120
|
|
121
121
|
after do
|
122
122
|
@session.current_window.resize_to(*@initial_size)
|
123
|
-
sleep
|
123
|
+
sleep 1
|
124
124
|
end
|
125
125
|
|
126
126
|
it 'should be able to resize window', requires: %i[windows js] do
|
@@ -194,7 +194,7 @@ Capybara::SpecHelper.spec Capybara::Window, requires: [:windows] do
|
|
194
194
|
|
195
195
|
after do
|
196
196
|
@session.current_window.resize_to(*@initial_size)
|
197
|
-
sleep
|
197
|
+
sleep 1
|
198
198
|
end
|
199
199
|
|
200
200
|
it 'should be able to fullscreen the window' do
|
@@ -16,8 +16,7 @@ module Capybara
|
|
16
16
|
config.filter_run_excluding requires: method(:filter).to_proc
|
17
17
|
config.before { Capybara::SpecHelper.reset! }
|
18
18
|
config.after { Capybara::SpecHelper.reset! }
|
19
|
-
|
20
|
-
config.shared_context_metadata_behavior = :apply_to_host_groups if config.respond_to?(:shared_context_metadata_behavior=)
|
19
|
+
config.shared_context_metadata_behavior = :apply_to_host_groups
|
21
20
|
end
|
22
21
|
|
23
22
|
def reset!
|
@@ -3,6 +3,9 @@
|
|
3
3
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
|
4
4
|
<title>with_animation</title>
|
5
5
|
<script src="/jquery.js" type="text/javascript" charset="utf-8"></script>
|
6
|
+
<script>
|
7
|
+
$(document).on('contextmenu', function(e){ e.preventDefault(); })
|
8
|
+
</script>
|
6
9
|
<style>
|
7
10
|
div {
|
8
11
|
width: 400px;
|
data/lib/capybara/version.rb
CHANGED
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Capybara::Selector::CSSBuilder do
|
6
|
+
let :builder do
|
7
|
+
::Capybara::Selector::CSSBuilder.new(@css)
|
8
|
+
end
|
9
|
+
|
10
|
+
context 'add_attribute_conditions' do
|
11
|
+
it 'adds a single string condition to a single selector' do
|
12
|
+
@css = 'div'
|
13
|
+
selector = builder.add_attribute_conditions(random: 'abc')
|
14
|
+
expect(selector).to eq %(div[random='abc'])
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'adds multiple string conditions to a single selector' do
|
18
|
+
@css = 'div'
|
19
|
+
selector = builder.add_attribute_conditions(random: 'abc', other: 'def')
|
20
|
+
expect(selector).to eq %(div[random='abc'][other='def'])
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'adds a single string condition to a multiple selector' do
|
24
|
+
@css = 'div, ul'
|
25
|
+
selector = builder.add_attribute_conditions(random: 'abc')
|
26
|
+
expect(selector).to eq %(div[random='abc'], ul[random='abc'])
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'adds multiple string conditions to a multiple selector' do
|
30
|
+
@css = 'div, ul'
|
31
|
+
selector = builder.add_attribute_conditions(random: 'abc', other: 'def')
|
32
|
+
expect(selector).to eq %(div[random='abc'][other='def'], ul[random='abc'][other='def'])
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'adds simple regexp conditions to a single selector' do
|
36
|
+
@css = 'div'
|
37
|
+
selector = builder.add_attribute_conditions(random: /abc/, other: /def/)
|
38
|
+
expect(selector).to eq %(div[random*='abc'][other*='def'])
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'adds wildcard regexp conditions to a single selector' do
|
42
|
+
@css = 'div'
|
43
|
+
selector = builder.add_attribute_conditions(random: /abc.*def/, other: /def.*ghi/)
|
44
|
+
expect(selector).to eq %(div[random*='abc'][random*='def'][other*='def'][other*='ghi'])
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'adds alternated regexp conditions to a single selector' do
|
48
|
+
@css = 'div'
|
49
|
+
selector = builder.add_attribute_conditions(random: /abc|def/, other: /def|ghi/)
|
50
|
+
expect(selector).to eq %(div[random*='abc'][other*='def'], div[random*='abc'][other*='ghi'], div[random*='def'][other*='def'], div[random*='def'][other*='ghi'])
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'adds alternated regexp conditions to a multiple selector' do
|
54
|
+
@css = 'div,ul'
|
55
|
+
selector = builder.add_attribute_conditions(other: /def.*ghi|jkl/)
|
56
|
+
expect(selector).to eq %(div[other*='def'][other*='ghi'], div[other*='jkl'], ul[other*='def'][other*='ghi'], ul[other*='jkl'])
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns original selector when regexp can't be substringed" do
|
60
|
+
@css = 'div'
|
61
|
+
selector = builder.add_attribute_conditions(other: /.+/)
|
62
|
+
expect(selector).to eq 'div'
|
63
|
+
end
|
64
|
+
|
65
|
+
context ':class' do
|
66
|
+
it 'handles string with CSS .' do
|
67
|
+
@css = 'a'
|
68
|
+
selector = builder.add_attribute_conditions(class: 'my_class')
|
69
|
+
expect(selector).to eq 'a.my_class'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'handles negated string with CSS .' do
|
73
|
+
@css = 'a'
|
74
|
+
selector = builder.add_attribute_conditions(class: '!my_class')
|
75
|
+
expect(selector).to eq 'a:not(.my_class)'
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'handles array of string with CSS .' do
|
79
|
+
@css = 'a'
|
80
|
+
selector = builder.add_attribute_conditions(class: %w[my_class my_other_class])
|
81
|
+
expect(selector).to eq 'a.my_class.my_other_class'
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'handles array of string with CSS . when negated included' do
|
85
|
+
@css = 'a'
|
86
|
+
selector = builder.add_attribute_conditions(class: %w[my_class !my_other_class])
|
87
|
+
expect(selector).to eq 'a.my_class:not(.my_other_class)'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
context ':id' do
|
92
|
+
it 'handles string with CSS #' do
|
93
|
+
@css = 'ul'
|
94
|
+
selector = builder.add_attribute_conditions(id: 'my_id')
|
95
|
+
expect(selector).to eq 'ul#my_id'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|