capybara 3.0.0.rc1 → 3.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/History.md +18 -2
  3. data/README.md +1 -0
  4. data/lib/capybara/driver/base.rb +10 -0
  5. data/lib/capybara/helpers.rb +5 -3
  6. data/lib/capybara/node/matchers.rb +4 -2
  7. data/lib/capybara/queries/ancestor_query.rb +7 -1
  8. data/lib/capybara/queries/base_query.rb +4 -1
  9. data/lib/capybara/queries/text_query.rb +3 -6
  10. data/lib/capybara/queries/title_query.rb +2 -2
  11. data/lib/capybara/rack_test/node.rb +23 -7
  12. data/lib/capybara/rspec/matchers.rb +0 -1
  13. data/lib/capybara/selector/filter_set.rb +1 -1
  14. data/lib/capybara/selector/selector.rb +1 -1
  15. data/lib/capybara/selenium/driver.rb +11 -0
  16. data/lib/capybara/selenium/node.rb +50 -4
  17. data/lib/capybara/session.rb +1 -1
  18. data/lib/capybara/spec/public/test.js +0 -1
  19. data/lib/capybara/spec/session/ancestor_spec.rb +4 -4
  20. data/lib/capybara/spec/session/assert_text.rb +5 -6
  21. data/lib/capybara/spec/session/assert_title.rb +12 -3
  22. data/lib/capybara/spec/session/attach_file_spec.rb +29 -18
  23. data/lib/capybara/spec/session/current_url_spec.rb +10 -0
  24. data/lib/capybara/spec/session/fill_in_spec.rb +24 -0
  25. data/lib/capybara/spec/session/find_field_spec.rb +1 -1
  26. data/lib/capybara/spec/session/frame/frame_title_spec.rb +23 -0
  27. data/lib/capybara/spec/session/frame/frame_url_spec.rb +23 -0
  28. data/lib/capybara/spec/session/has_text_spec.rb +3 -8
  29. data/lib/capybara/spec/session/node_spec.rb +1 -1
  30. data/lib/capybara/spec/session/refresh_spec.rb +3 -1
  31. data/lib/capybara/spec/session/reset_session_spec.rb +18 -0
  32. data/lib/capybara/spec/session/save_screenshot_spec.rb +2 -2
  33. data/lib/capybara/spec/session/text_spec.rb +16 -3
  34. data/lib/capybara/spec/session/title_spec.rb +10 -0
  35. data/lib/capybara/spec/session/window/within_window_spec.rb +2 -3
  36. data/lib/capybara/spec/spec_helper.rb +4 -0
  37. data/lib/capybara/spec/test_app.rb +9 -0
  38. data/lib/capybara/spec/views/form.erb +6 -0
  39. data/lib/capybara/spec/views/with_html.erb +20 -0
  40. data/lib/capybara/version.rb +1 -1
  41. data/spec/selenium_spec_chrome.rb +2 -0
  42. data/spec/selenium_spec_edge.rb +27 -0
  43. data/spec/selenium_spec_ie.rb +27 -0
  44. data/spec/selenium_spec_marionette.rb +2 -0
  45. data/spec/server_spec.rb +1 -1
  46. data/spec/shared_selenium_session.rb +9 -0
  47. data/spec/spec_helper.rb +2 -2
  48. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 21f91a983551012c790ae444974b24f9d0349d79c36706d4a9143523b2827605
4
- data.tar.gz: 54de192348948696b54e66ff9fc7622311b88fd7d71e842b0737be060bfdc59a
3
+ metadata.gz: d9b394cb5aaa7d6849ba4fd9e486b7fae2298a64f6a5e2f88fd80abea82a2ba6
4
+ data.tar.gz: eeca1e3b972c9efb89224fb701a1612a5d503621327af3fb77bf1a028a21761d
5
5
  SHA512:
6
- metadata.gz: 62ab87128fa70c43cfa688d55c9ae208095b632999cbd44969971cfcbefed37b4719e8c8e2c0350e13dd69a2e35ec5799d1f7f105cd717cfa277b091b42041db
7
- data.tar.gz: 3c013b9add97330680def4a948246360ccf0bbc520e8b8573b0bdee4dfcbde751d7f9626268fe682aa613975d4ad126e776cba7075a50259769e120bec09b61d
6
+ metadata.gz: 615f9400b993c2408414f886a5cfdd41272e29cb9c3fa1763758888416d3e9c5f42d4d179686f8ac56b185610503aef904be6a508e5e8b7d703760ff85a498a0
7
+ data.tar.gz: 0045d33244fdc1cd6615cac65760399088330bc1751781c1ea2c0107570f096f52766841ad2f1a40efb595127e9e78b5c4b1d9341dcd146721eedba0e588062a
data/History.md CHANGED
@@ -1,3 +1,19 @@
1
+ # Version 3.0.0.rc2
2
+ Release date: 2018-03-23
3
+
4
+ ### Changed
5
+
6
+ * Drivers are now expected to return visible text more in line with the WebDriver spec for visible text
7
+ * Drivers are expected to close extra windows when resetting the session
8
+ * Selenium driver supports Date/Time when filling in date/time/datetime-local inputs
9
+ * `current_url` returns the url for the top level browsing context
10
+ * `title` returns the title for the top level browsing context
11
+
12
+ ### Added
13
+
14
+ * `Driver#frame_url` returns the url for the current frame
15
+ * `Driver#frame_title` returns the title for the current frame
16
+
1
17
  # Version 3.0.0.rc1
2
18
  Release date: 2018-03-02
3
19
 
@@ -6,7 +22,7 @@ Release date: 2018-03-02
6
22
 
7
23
  ### Changed
8
24
 
9
- * `first` now raises ElementNotFound, by default, instead of returning nil, when no matches are found - Issue #1507
25
+ * `first` now raises ElementNotFound, by default, instead of returning nil when no matches are found - Issue #1507
10
26
  * 'all' now waits for at least one matching element by default. Pass `wait: false` if you want the previous
11
27
  behavior where an empty result would be returned immediately if no matching elements exist yet.
12
28
  * ArgumentError raised if extra parameters passed to selector queries
@@ -19,7 +35,7 @@ Release date: 2018-03-02
19
35
  * RSpec 2.x support
20
36
  * selenium-webdriver 2.x support
21
37
  * Nokogiri < 1.8 support
22
- * `field_labeled` alaias for `find_field`
38
+ * `field_labeled` alias for `find_field`
23
39
 
24
40
  # Version 2.18.0
25
41
  Release date: 2018-02-12
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Capybara
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/teamcapybara/capybara.svg)](https://travis-ci.org/teamcapybara/capybara)
4
+ [![Build Status](https://ci.appveyor.com/api/projects/status/github/teamcapybara/capybara?svg=true)](https://ci.appveyor.com/api/projects/github/teamcapybara/capybara)
4
5
  [![Dependency Status](https://gemnasium.com/teamcapybara/capybara.svg)](https://gemnasium.com/teamcapybara/capybara)
5
6
  [![Code Climate](https://codeclimate.com/github/teamcapybara/capybara.svg)](https://codeclimate.com/github/teamcapybara/capybara)
6
7
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/jnicklas/capybara?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
@@ -67,6 +67,16 @@ class Capybara::Driver::Base
67
67
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#switch_to_frame'
68
68
  end
69
69
 
70
+ def frame_title
71
+ find_xpath('/html/head/title').map(&:all_text).first.to_s
72
+ end
73
+
74
+ def frame_url
75
+ evaluate_script('document.location.href')
76
+ rescue Capybara::NotSupportedByDriverError
77
+ raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#frame_title'
78
+ end
79
+
70
80
  def current_window_handle
71
81
  raise Capybara::NotSupportedByDriverError, 'Capybara::Driver::Base#current_window_handle'
72
82
  end
@@ -6,7 +6,7 @@ module Capybara
6
6
  extend self
7
7
 
8
8
  ##
9
- #
9
+ # @deprecated
10
10
  # Normalizes whitespace space by stripping leading and trailing
11
11
  # whitespace and replacing sequences of whitespace characters
12
12
  # with a single space.
@@ -15,6 +15,7 @@ module Capybara
15
15
  # @return [String] Normalized text
16
16
  #
17
17
  def normalize_whitespace(text)
18
+ warn "DEPRECATED: Capybara::Helpers::normalize_whitespace is deprecated, please update your driver"
18
19
  text.to_s.gsub(/[[:space:]]+/, ' ').strip
19
20
  end
20
21
 
@@ -28,10 +29,11 @@ module Capybara
28
29
  # @param [Fixnum, Boolean, nil] options Options passed to Regexp.new when creating the Regexp
29
30
  # @return [Regexp] Regexp to match the passed in text and options
30
31
  #
31
- def to_regexp(text, exact: false, options: nil)
32
+ def to_regexp(text, exact: false, all_whitespace: false, options: nil)
32
33
  return text if text.is_a?(Regexp)
33
34
 
34
- escaped = Regexp.escape(normalize_whitespace(text))
35
+ escaped = Regexp.escape(text)
36
+ escaped = escaped.gsub("\\ ", "[[:blank:]]") if all_whitespace
35
37
  escaped = "\\A#{escaped}\\z" if exact
36
38
  Regexp.new(escaped, options)
37
39
  end
@@ -112,7 +112,8 @@ module Capybara
112
112
  #
113
113
  # @overload assert_all_of_selectors([kind = Capybara.default_selector], *locators, options = {})
114
114
  #
115
- def assert_all_of_selectors(*args, wait: session_options.default_max_wait_time, **options, &optional_filter_block)
115
+ def assert_all_of_selectors(*args, wait: nil, **options, &optional_filter_block)
116
+ wait = session_options.default_max_wait_time if wait.nil?
116
117
  selector = args.first.is_a?(Symbol) ? args.shift : session_options.default_selector
117
118
  synchronize(wait) do
118
119
  args.each do |locator|
@@ -136,7 +137,8 @@ module Capybara
136
137
  #
137
138
  # @overload assert_none_of_selectors([kind = Capybara.default_selector], *locators, options = {})
138
139
  #
139
- def assert_none_of_selectors(*args, wait: session_options.default_max_wait_time, **options, &optional_filter_block)
140
+ def assert_none_of_selectors(*args, wait: nil, **options, &optional_filter_block)
141
+ wait = session_options.default_max_wait_time if wait.nil?
140
142
  selector = args.first.is_a?(Symbol) ? args.shift : session_options.default_selector
141
143
  synchronize(wait) do
142
144
  args.each do |locator|
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Capybara
4
4
  module Queries
5
- class AncestorQuery < MatchQuery
5
+ class AncestorQuery < Capybara::Queries::SelectorQuery
6
6
  # @api private
7
7
  def resolve_for(node, exact = nil)
8
8
  @child_node = node
@@ -18,6 +18,12 @@ module Capybara
18
18
  desc += " that is an ancestor of #{child_query.description}" if child_query
19
19
  desc
20
20
  end
21
+
22
+ private
23
+
24
+ def valid_keys
25
+ super - COUNT_KEYS
26
+ end
21
27
  end
22
28
  end
23
29
  end
@@ -22,7 +22,10 @@ module Capybara
22
22
  end
23
23
 
24
24
  def self.wait(options, default = Capybara.default_max_wait_time)
25
- options.fetch(:wait, default) || 0
25
+ # if no value or nil for the :wait option is passed it should default to the default
26
+ w = options.fetch(:wait, nil)
27
+ w = default if w.nil?
28
+ w || 0
26
29
  end
27
30
 
28
31
  ##
@@ -10,11 +10,8 @@ module Capybara
10
10
  else
11
11
  type
12
12
  end
13
- @expected_text = if expected_text.is_a?(Regexp)
14
- expected_text
15
- else
16
- Capybara::Helpers.normalize_whitespace(expected_text)
17
- end
13
+
14
+ @expected_text = expected_text.is_a?(Regexp) ? expected_text : expected_text.to_s
18
15
  @options = options
19
16
  super(@options)
20
17
  self.session_options = session_options
@@ -94,7 +91,7 @@ module Capybara
94
91
  end
95
92
 
96
93
  def text(node, query_type)
97
- Capybara::Helpers.normalize_whitespace(node.text(query_type))
94
+ node.text(query_type)
98
95
  end
99
96
  end
100
97
  end
@@ -5,10 +5,10 @@ module Capybara
5
5
  module Queries
6
6
  class TitleQuery < BaseQuery
7
7
  def initialize(expected_title, **options)
8
- @expected_title = expected_title.is_a?(Regexp) ? expected_title : Capybara::Helpers.normalize_whitespace(expected_title)
8
+ @expected_title = expected_title.is_a?(Regexp) ? expected_title : expected_title.to_s
9
9
  @options = options
10
10
  super(@options)
11
- @search_regexp = Capybara::Helpers.to_regexp(@expected_title, exact: options.fetch(:exact, false))
11
+ @search_regexp = Capybara::Helpers.to_regexp(@expected_title, all_whitespace: true, exact: options.fetch(:exact, false))
12
12
  assert_valid_keys
13
13
  end
14
14
 
@@ -1,12 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Capybara::RackTest::Node < Capybara::Driver::Node
4
+ BLOCK_ELEMENTS = %w[p h1 h2 h3 h4 h5 h6 ol ul pre address blockquote dl div fieldset form hr noscript table].freeze
5
+
4
6
  def all_text
5
- Capybara::Helpers.normalize_whitespace(native.text)
7
+ native.text
8
+ .gsub(/[\u200b\u200e\u200f]/, '')
9
+ .gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
10
+ .gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
11
+ .gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
12
+ .tr("\u00a0", ' ')
6
13
  end
7
14
 
8
15
  def visible_text
9
- Capybara::Helpers.normalize_whitespace(unnormalized_text)
16
+ displayed_text.gsub(/\ +/, ' ')
17
+ .gsub(/[\ \n]*\n[\ \n]*/, "\n")
18
+ .gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
19
+ .gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
20
+ .tr("\u00a0", ' ')
10
21
  end
11
22
 
12
23
  def [](name)
@@ -103,15 +114,20 @@ class Capybara::RackTest::Node < Capybara::Driver::Node
103
114
 
104
115
  protected
105
116
 
106
- def unnormalized_text(check_ancestor_visibility = true)
107
- if !string_node.visible?(check_ancestor_visibility)
117
+ # @api private
118
+ def displayed_text(check_ancestor: true)
119
+ if !string_node.visible?(check_ancestor)
108
120
  ''
109
121
  elsif native.text?
110
122
  native.text
123
+ .gsub(/[\u200b\u200e\u200f]/, '')
124
+ .gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
111
125
  elsif native.element?
112
- native.children.map do |child|
113
- Capybara::RackTest::Node.new(driver, child).unnormalized_text(false)
114
- end.join
126
+ text = native.children.map do |child|
127
+ Capybara::RackTest::Node.new(driver, child).displayed_text(check_ancestor: false)
128
+ end.join || ''
129
+ text = "\n#{text}\n" if BLOCK_ELEMENTS.include?(tag_name)
130
+ text
115
131
  else
116
132
  ''
117
133
  end
@@ -154,7 +154,6 @@ module Capybara
154
154
  end
155
155
 
156
156
  def format(content)
157
- content = Capybara::Helpers.normalize_whitespace(content) unless content.is_a? Regexp
158
157
  content.inspect
159
158
  end
160
159
  end
@@ -46,7 +46,7 @@ module Capybara
46
46
 
47
47
  class << self
48
48
  def all
49
- @filter_sets ||= {}
49
+ @filter_sets ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
50
50
  end
51
51
 
52
52
  def add(name, &block)
@@ -25,7 +25,7 @@ module Capybara
25
25
 
26
26
  class << self
27
27
  def all
28
- @selectors ||= {}
28
+ @selectors ||= {} # rubocop:disable Naming/MemoizedInstanceVariableName
29
29
  end
30
30
 
31
31
  def add(name, &block)
@@ -26,6 +26,8 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
26
26
  @w3c = ((defined?(Selenium::WebDriver::Remote::W3CCapabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3CCapabilities)) ||
27
27
  (defined?(Selenium::WebDriver::Remote::W3C::Capabilities) && @browser.capabilities.is_a?(Selenium::WebDriver::Remote::W3C::Capabilities)))
28
28
  main = Process.pid
29
+ @primary_window_handle = current_window_handle
30
+
29
31
  at_exit do
30
32
  # Store the exit status of the test run since it goes away after calling the at_exit proc...
31
33
  @exit_status = $ERROR_INFO.status if $ERROR_INFO.is_a?(SystemExit)
@@ -108,6 +110,9 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
108
110
  # Use instance variable directly so we avoid starting the browser just to reset the session
109
111
  return unless @browser
110
112
 
113
+ switch_to_window(@primary_window_handle)
114
+ window_handles.reject { |handle| handle == @primary_window_handle }.each { |win| close_window(win) }
115
+
111
116
  navigated = false
112
117
  start_time = Capybara::Helpers.monotonic_time
113
118
  begin
@@ -205,6 +210,7 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
205
210
  end
206
211
 
207
212
  def close_window(handle)
213
+ raise ArgumentError, "Not allowed to close the primary window" if handle == @primary_window_handle
208
214
  within_given_window(handle) do
209
215
  browser.close
210
216
  end
@@ -286,6 +292,11 @@ class Capybara::Selenium::Driver < Capybara::Driver::Base
286
292
  browser_name == "chrome"
287
293
  end
288
294
 
295
+ # @api private
296
+ def edge?
297
+ browser_name == "edge"
298
+ end
299
+
289
300
  private
290
301
 
291
302
  def browser_name
@@ -1,14 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Capybara::Selenium::Node < Capybara::Driver::Node
4
+ SET_FORMATS = Hash.new(date: '%Y-%m-%d', time: '%H:%M', datetime: "%m%d%Y\t%I%M%P").merge(
5
+ firefox: {
6
+ date: '%Y-%m-%d',
7
+ time: '%H:%M',
8
+ datetime: "%m%d%Y\t%I%M%P"
9
+ },
10
+ chrome: {
11
+ date: '%m%d%Y',
12
+ time: '%I%M%P',
13
+ datetime: "%m%d%Y\t%I%M%P"
14
+ }
15
+ )
16
+
4
17
  def visible_text
5
- # Selenium doesn't normalize Unicode whitespace.
6
- Capybara::Helpers.normalize_whitespace(native.text)
18
+ native.text
7
19
  end
8
20
 
9
21
  def all_text
10
22
  text = driver.execute_script("return arguments[0].textContent", self)
11
- Capybara::Helpers.normalize_whitespace(text)
23
+ text.gsub(/[\u200b\u200e\u200f]/, '')
24
+ .gsub(/[\ \n\f\t\v\u2028\u2029]+/, ' ')
25
+ .gsub(/\A[[:space:]&&[^\u00a0]]+/, "")
26
+ .gsub(/[[:space:]&&[^\u00a0]]+\z/, "")
27
+ .tr("\u00a0", ' ')
12
28
  end
13
29
 
14
30
  def [](name)
@@ -48,6 +64,12 @@ class Capybara::Selenium::Node < Capybara::Driver::Node
48
64
  click if value ^ checked?
49
65
  when 'file'
50
66
  set_file(value)
67
+ when 'date'
68
+ set_date(value)
69
+ when 'time'
70
+ set_time(value)
71
+ when 'datetime-local'
72
+ set_datetime_local(value)
51
73
  else
52
74
  set_text(value, options)
53
75
  end
@@ -197,7 +219,7 @@ private
197
219
  find_xpath(XPath.ancestor(:select)[1]).first
198
220
  end
199
221
 
200
- def set_text(value, clear: nil, **)
222
+ def set_text(value, clear: nil, **_unused)
201
223
  if value.to_s.empty? && clear.nil?
202
224
  native.clear
203
225
  elsif clear == :backspace
@@ -231,6 +253,30 @@ private
231
253
  yield
232
254
  end
233
255
 
256
+ def set_date(value) # rubocop:disable Naming/AccessorMethodName
257
+ if value.respond_to?(:to_date)
258
+ set_text(value.to_date.strftime(SET_FORMATS[driver.options[:browser].to_sym][:date]))
259
+ else
260
+ set_text(value)
261
+ end
262
+ end
263
+
264
+ def set_time(value) # rubocop:disable Naming/AccessorMethodName
265
+ if value.respond_to?(:to_time)
266
+ set_text(value.to_time.strftime(SET_FORMATS[driver.options[:browser].to_sym][:time]))
267
+ else
268
+ set_text(value)
269
+ end
270
+ end
271
+
272
+ def set_datetime_local(value) # rubocop:disable Naming/AccessorMethodName
273
+ if value.respond_to?(:to_time)
274
+ set_text(value.to_time.strftime(SET_FORMATS[driver.options[:browser].to_sym][:datetime]))
275
+ else
276
+ set_text(value)
277
+ end
278
+ end
279
+
234
280
  def set_file(value) # rubocop:disable Naming/AccessorMethodName
235
281
  path_names = value.to_s.empty? ? [] : value
236
282
  if driver.chrome?
@@ -413,7 +413,7 @@ module Capybara
413
413
  # @overload within_frame(element)
414
414
  # @param [Capybara::Node::Element] frame element
415
415
  # @overload within_frame([kind = :frame], locator, options = {})
416
- # @param [Symobl] kind Optional selector type (:css, :xpath, :field, etc.) - Defaults to :frame
416
+ # @param [Symbol] kind Optional selector type (:css, :xpath, :field, etc.) - Defaults to :frame
417
417
  # @param [String] locator The locator for the given selector kind. For :frame this is the name/id of a frame/iframe element
418
418
  # @overload within_frame(index)
419
419
  # @param [Integer] index index of a frame (0 based)
@@ -9,7 +9,6 @@ $(function() {
9
9
  }
10
10
  });
11
11
  $('#clickable').click(function(e) {
12
- debugger;
13
12
  var link = $(this);
14
13
  setTimeout(function() {
15
14
  $(link).after('<a id="has-been-clicked" href="#">Has been clicked</a>');
@@ -17,7 +17,7 @@ Capybara::SpecHelper.spec '#ancestor' do
17
17
 
18
18
  it "should find the ancestor element using the given locator and options" do
19
19
  el = @session.find(:css, '#child')
20
- expect(el.ancestor('//div', text: 'Ancestor Ancestor Ancestor')[:id]).to eq('ancestor3')
20
+ expect(el.ancestor('//div', text: "Ancestor\nAncestor\nAncestor")[:id]).to eq('ancestor3')
21
21
  end
22
22
 
23
23
  it "should raise an error if there are multiple matches" do
@@ -53,8 +53,8 @@ Capybara::SpecHelper.spec '#ancestor' do
53
53
  xpath { |num| ".//*[@id='ancestor#{num}']" }
54
54
  end
55
55
  el = @session.find(:css, '#child')
56
- expect(el.ancestor(:level, 1).text).to eq('Ancestor Child')
57
- expect(el.ancestor(:level, 3).text).to eq('Ancestor Ancestor Ancestor Child')
56
+ expect(el.ancestor(:level, 1)[:id]).to eq "ancestor1"
57
+ expect(el.ancestor(:level, 3)[:id]).to eq "ancestor3"
58
58
  end
59
59
  end
60
60
 
@@ -62,7 +62,7 @@ Capybara::SpecHelper.spec '#ancestor' do
62
62
  el = @session.find(:css, '#child')
63
63
  expect do
64
64
  el.ancestor(:xpath, '//div[@id="nosuchthing"]')
65
- end.to raise_error(Capybara::ElementNotFound, "Unable to find xpath \"//div[@id=\\\"nosuchthing\\\"]\" that is an ancestor of visible css \"#child\"")
65
+ end.to raise_error(Capybara::ElementNotFound, "Unable to find visible xpath \"//div[@id=\\\"nosuchthing\\\"]\" that is an ancestor of visible css \"#child\"")
66
66
  end
67
67
 
68
68
  context "within a scope" do
@@ -7,8 +7,7 @@ Capybara::SpecHelper.spec '#assert_text' do
7
7
  expect(@session.assert_text('Lorem')).to eq(true)
8
8
  expect(@session.assert_text('Redirect')).to eq(true)
9
9
  expect(@session.assert_text(:Redirect)).to eq(true)
10
- expect(@session.assert_text('text with whitespace')).to eq(true)
11
- expect(@session.assert_text("text with \n\n whitespace")).to eq(true)
10
+ expect(@session.assert_text('text with whitespace')).to eq(true)
12
11
  end
13
12
 
14
13
  it "should take scopes into account" do
@@ -49,7 +48,7 @@ Capybara::SpecHelper.spec '#assert_text' do
49
48
  it "should raise error with a helpful message if the requested text is present but with incorrect case" do
50
49
  @session.visit('/with_html')
51
50
  expect do
52
- @session.assert_text('Text With Whitespace')
51
+ @session.assert_text('Text With Whitespace')
53
52
  end.to raise_error(Capybara::ExpectationNotMet, /it was found 1 time using a case insensitive search/)
54
53
  end
55
54
 
@@ -77,7 +76,7 @@ Capybara::SpecHelper.spec '#assert_text' do
77
76
  @session.visit('/with_html')
78
77
  expect do
79
78
  @session.assert_text(/xxxxyzzz/)
80
- end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected to find text matching \/xxxxyzzz\/ in "This is a test Header Class(.+)"\Z/)
79
+ end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected to find text matching \/xxxxyzzz\/ in "This is a test\\nHeader Class(.+)"\Z/)
81
80
  end
82
81
 
83
82
  it "should escape any characters that would have special meaning in a regexp" do
@@ -112,7 +111,7 @@ Capybara::SpecHelper.spec '#assert_text' do
112
111
  Capybara.using_wait_time(0) do
113
112
  @session.visit('/with_js')
114
113
  @session.find(:css, '#reload-list').click
115
- @session.find(:css, '#the-list').assert_text('Foo Bar', wait: 0.9)
114
+ @session.find(:css, '#the-list').assert_text("Foo\nBar", wait: 0.9)
116
115
  end
117
116
  end
118
117
 
@@ -174,7 +173,7 @@ Capybara::SpecHelper.spec '#assert_no_text' do
174
173
  @session.visit('/with_html')
175
174
  expect do
176
175
  @session.assert_no_text('Lorem')
177
- end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected not to find text "Lorem" in "This is a test Header Class.+"\Z/)
176
+ end.to raise_error(Capybara::ExpectationNotMet, /\Aexpected not to find text "Lorem" in "This is a test.*"\z/)
178
177
  end
179
178
 
180
179
  it "should be true if scoped to an element which does not have the text" do
@@ -40,11 +40,20 @@ Capybara::SpecHelper.spec '#assert_title' do
40
40
  end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "monkey"')
41
41
  end
42
42
 
43
- it "should normalize given title" do
44
- @session.assert_title(' with_js ')
43
+ it "should not normalize given title" do
44
+ @session.visit('/with_js')
45
+ expect { @session.assert_title(' with_js ') }.to raise_error(Capybara::ExpectationNotMet)
46
+ end
47
+
48
+ it "should match correctly normalized title" do
49
+ uri = Addressable::URI.parse('/with_title')
50
+ uri.query_values = { title: ' &nbsp; with space &nbsp;title ' }
51
+ @session.visit(uri.to_s)
52
+ @session.assert_title(' with space title')
53
+ expect { @session.assert_title('with space title') }.to raise_error(Capybara::ExpectationNotMet)
45
54
  end
46
55
 
47
- it "should normalize given title in error message" do
56
+ it "should not normalize given title in error message" do
48
57
  expect do
49
58
  @session.assert_title(2)
50
59
  end.to raise_error(Capybara::ExpectationNotMet, 'expected "with_js" to include "2"')
@@ -11,19 +11,19 @@ Capybara::SpecHelper.spec "#attach_file" do
11
11
 
12
12
  context "with normal form" do
13
13
  it "should set a file path by id" do
14
- @session.attach_file "form_image", __FILE__
14
+ @session.attach_file "form_image", with_os_path_separators(__FILE__)
15
15
  @session.click_button('awesome')
16
16
  expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
17
17
  end
18
18
 
19
19
  it "should set a file path by label" do
20
- @session.attach_file "Image", __FILE__
20
+ @session.attach_file "Image", with_os_path_separators(__FILE__)
21
21
  @session.click_button('awesome')
22
22
  expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
23
23
  end
24
24
 
25
25
  it "casts to string" do
26
- @session.attach_file :form_image, __FILE__
26
+ @session.attach_file :form_image, with_os_path_separators(__FILE__)
27
27
  @session.click_button('awesome')
28
28
  expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
29
29
  end
@@ -31,13 +31,13 @@ Capybara::SpecHelper.spec "#attach_file" do
31
31
 
32
32
  context "with multipart form" do
33
33
  it "should set a file path by id" do
34
- @session.attach_file "form_document", @test_file_path
34
+ @session.attach_file "form_document", with_os_path_separators(@test_file_path)
35
35
  @session.click_button('Upload Single')
36
36
  expect(@session).to have_content(File.read(@test_file_path))
37
37
  end
38
38
 
39
39
  it "should set a file path by label" do
40
- @session.attach_file "Single Document", @test_file_path
40
+ @session.attach_file "Single Document", with_os_path_separators(@test_file_path)
41
41
  @session.click_button('Upload Single')
42
42
  expect(@session).to have_content(File.read(@test_file_path))
43
43
  end
@@ -48,25 +48,25 @@ Capybara::SpecHelper.spec "#attach_file" do
48
48
  end
49
49
 
50
50
  it "should send content type text/plain when uploading a text file" do
51
- @session.attach_file "Single Document", @test_file_path
51
+ @session.attach_file "Single Document", with_os_path_separators(@test_file_path)
52
52
  @session.click_button 'Upload Single'
53
53
  expect(@session).to have_content('text/plain')
54
54
  end
55
55
 
56
56
  it "should send content type image/jpeg when uploading an image" do
57
- @session.attach_file "Single Document", @test_jpg_file_path
57
+ @session.attach_file "Single Document", with_os_path_separators(@test_jpg_file_path)
58
58
  @session.click_button 'Upload Single'
59
59
  expect(@session).to have_content('image/jpeg')
60
60
  end
61
61
 
62
62
  it "should not break when uploading a file without extension" do
63
- @session.attach_file "Single Document", @no_extension_file_path
63
+ @session.attach_file "Single Document", with_os_path_separators(@no_extension_file_path)
64
64
  @session.click_button 'Upload Single'
65
65
  expect(@session).to have_content(File.read(@no_extension_file_path))
66
66
  end
67
67
 
68
68
  it "should not break when using HTML5 multiple file input" do
69
- @session.attach_file "Multiple Documents", @test_file_path
69
+ @session.attach_file "Multiple Documents", with_os_path_separators(@test_file_path)
70
70
  @session.click_button('Upload Multiple')
71
71
  expect(@session).to have_content(File.read(@test_file_path))
72
72
  expect(@session.body).to include("1 | ") # number of files
@@ -74,7 +74,8 @@ Capybara::SpecHelper.spec "#attach_file" do
74
74
 
75
75
  it "should not break when using HTML5 multiple file input uploading multiple files" do
76
76
  pending "Selenium is buggy on this, see http://code.google.com/p/selenium/issues/detail?id=2239" if @session.respond_to?(:mode) && @session.mode.to_s =~ /^selenium_(firefox|marionette)/
77
- @session.attach_file "Multiple Documents", [@test_file_path, @another_test_file_path]
77
+ @session.attach_file("Multiple Documents",
78
+ [@test_file_path, @another_test_file_path].map { |f| with_os_path_separators(f) })
78
79
  @session.click_button('Upload Multiple')
79
80
  expect(@session.body).to include("2 | ") # number of files
80
81
  expect(@session.body).to include(File.read(@test_file_path))
@@ -91,7 +92,7 @@ Capybara::SpecHelper.spec "#attach_file" do
91
92
  it "should raise an error" do
92
93
  msg = "Unable to find visible file field \"does not exist\" that is not disabled"
93
94
  expect do
94
- @session.attach_file('does not exist', @test_file_path)
95
+ @session.attach_file('does not exist', with_os_path_separators(@test_file_path))
95
96
  end.to raise_error(Capybara::ElementNotFound, msg)
96
97
  end
97
98
  end
@@ -104,14 +105,14 @@ Capybara::SpecHelper.spec "#attach_file" do
104
105
 
105
106
  context "with :exact option" do
106
107
  it "should set a file path by partial label when false" do
107
- @session.attach_file "Imag", __FILE__, exact: false
108
+ @session.attach_file "Imag", with_os_path_separators(__FILE__), exact: false
108
109
  @session.click_button('awesome')
109
110
  expect(extract_results(@session)['image']).to eq(File.basename(__FILE__))
110
111
  end
111
112
 
112
113
  it "should not allow partial matches when true" do
113
114
  expect do
114
- @session.attach_file "Imag", __FILE__, exact: true
115
+ @session.attach_file "Imag", with_os_path_separators(__FILE__), exact: true
115
116
  end.to raise_error(Capybara::ElementNotFound)
116
117
  end
117
118
  end
@@ -119,30 +120,40 @@ Capybara::SpecHelper.spec "#attach_file" do
119
120
  context "with :make_visible option", requires: %i[js es_args] do
120
121
  it "applies a default style change when true" do
121
122
  @session.visit('/with_js')
122
- expect { @session.attach_file("hidden_file", __FILE__) }.to raise_error Capybara::ElementNotFound
123
123
  expect do
124
- @session.attach_file("hidden_file", __FILE__, make_visible: true)
124
+ @session.attach_file("hidden_file", with_os_path_separators(__FILE__))
125
+ end.to raise_error Capybara::ElementNotFound
126
+ expect do
127
+ @session.attach_file("hidden_file", with_os_path_separators(__FILE__), make_visible: true)
125
128
  end.not_to raise_error
126
129
  end
127
130
 
128
131
  it "accepts a hash of styles to be applied" do
129
132
  @session.visit('/with_js')
130
133
  expect do
131
- @session.attach_file("hidden_file", __FILE__, make_visible: { opacity: 1, display: 'block' })
134
+ @session.attach_file("hidden_file",
135
+ with_os_path_separators(__FILE__),
136
+ make_visible: { opacity: 1, display: 'block' })
132
137
  end.not_to raise_error
133
138
  end
134
139
 
135
140
  it "raises an error when the file input is not made visible" do
136
141
  @session.visit('/with_js')
137
142
  expect do
138
- @session.attach_file("hidden_file", __FILE__, make_visible: { color: 'red' })
143
+ @session.attach_file("hidden_file", with_os_path_separators(__FILE__), make_visible: { color: 'red' })
139
144
  end.to raise_error(Capybara::ExpectationNotMet)
140
145
  end
141
146
 
142
147
  it "resets the style when done" do
143
148
  @session.visit('/with_js')
144
- @session.attach_file("hidden_file", __FILE__, make_visible: true)
149
+ @session.attach_file("hidden_file", with_os_path_separators(__FILE__), make_visible: true)
145
150
  expect(@session.evaluate_script("arguments[0].style.display", @session.find(:css, '#hidden_file', visible: :all))).to eq 'none'
146
151
  end
147
152
  end
153
+
154
+ private
155
+
156
+ def with_os_path_separators(path)
157
+ Gem.win_platform? ? path.to_s.tr('/', '\\') : path.to_s
158
+ end
148
159
  end
@@ -105,4 +105,14 @@ Capybara::SpecHelper.spec '#current_url, #current_path, #current_host' do
105
105
  expect { @session.current_url }.not_to raise_exception
106
106
  expect { @session.current_path }.not_to raise_exception
107
107
  end
108
+
109
+ context "within iframe", requires: [:frames] do
110
+ it "should get the url of the top level browsing context" do
111
+ @session.visit('/within_frames')
112
+ expect(@session.current_url).to match(/within_frames\z/)
113
+ @session.within_frame('frameOne') do
114
+ expect(@session.current_url).to match(/within_frames\z/)
115
+ end
116
+ end
117
+ end
108
118
  end
@@ -53,6 +53,30 @@ Capybara::SpecHelper.spec "#fill_in" do
53
53
  expect(extract_results(@session)['password']).to eq('supasikrit')
54
54
  end
55
55
 
56
+ context "Date/Time" do
57
+ it "should fill in a date input" do
58
+ date = Date.today
59
+ @session.fill_in('form_date', with: date)
60
+ @session.click_button('awesome')
61
+ expect(Date.parse(extract_results(@session)['date'])).to eq date
62
+ end
63
+
64
+ it "should fill in a time input" do
65
+ time = Time.new(2018, 3, 9, 15, 26)
66
+ @session.fill_in('form_time', with: time)
67
+ @session.click_button('awesome')
68
+ results = extract_results(@session)['time']
69
+ expect(Time.parse(results).strftime('%r')).to eq time.strftime('%r')
70
+ end
71
+
72
+ it "should fill in a datetime input" do
73
+ dt = Time.new(2018, 3, 13, 9, 53)
74
+ @session.fill_in('form_datetime', with: dt)
75
+ @session.click_button('awesome')
76
+ expect(Time.parse(extract_results(@session)['datetime'])).to eq dt
77
+ end
78
+ end
79
+
56
80
  it "should handle HTML in a textarea" do
57
81
  @session.fill_in('form_description', with: 'is <strong>very</strong> secret!')
58
82
  @session.click_button('awesome')
@@ -7,7 +7,7 @@ Capybara::SpecHelper.spec '#find_field' do
7
7
 
8
8
  it "should find any field" do
9
9
  expect(@session.find_field('Dog').value).to eq('dog')
10
- expect(@session.find_field('form_description').text).to eq('Descriptive text goes here')
10
+ expect(@session.find_field('form_description').value).to eq('Descriptive text goes here')
11
11
  expect(@session.find_field('Region')[:name]).to eq('form[region]')
12
12
  expect(@session.find_field('With Asterisk*')).to be
13
13
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#frame_title', requires: [:frames] do
4
+ before(:each) do
5
+ @session.visit('/within_frames')
6
+ end
7
+
8
+ it "should return the title in a frame" do
9
+ @session.within_frame("frameOne") do
10
+ expect(@session.driver.frame_title).to eq 'This is the title of frame one'
11
+ end
12
+ end
13
+
14
+ it "should return the title in FrameTwo" do
15
+ @session.within_frame("frameTwo") do
16
+ expect(@session.driver.frame_title).to eq 'This is the title of frame two'
17
+ end
18
+ end
19
+
20
+ it "should return the title in the main frame" do
21
+ expect(@session.driver.frame_title).to eq 'With Frames'
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ Capybara::SpecHelper.spec '#frame_url', requires: [:frames] do
4
+ before(:each) do
5
+ @session.visit('/within_frames')
6
+ end
7
+
8
+ it "should return the url in a frame" do
9
+ @session.within_frame("frameOne") do
10
+ expect(@session.driver.frame_url).to end_with '/frame_one'
11
+ end
12
+ end
13
+
14
+ it "should return the url in FrameTwo" do
15
+ @session.within_frame("frameTwo") do
16
+ expect(@session.driver.frame_url).to end_with '/frame_two'
17
+ end
18
+ end
19
+
20
+ it "should return the url in the main frame" do
21
+ expect(@session.driver.frame_url).to end_with('/within_frames')
22
+ end
23
+ end
@@ -29,14 +29,9 @@ Capybara::SpecHelper.spec '#has_text?' do
29
29
  expect(@session).to have_text('exercitation ullamco laboris')
30
30
  end
31
31
 
32
- it "should ignore extra whitespace and newlines" do
32
+ it "should search correctly normalized text" do
33
33
  @session.visit('/with_html')
34
- expect(@session).to have_text('text with whitespace')
35
- end
36
-
37
- it "should ignore whitespace and newlines in the search string" do
38
- @session.visit('/with_html')
39
- expect(@session).to have_text("text with \n\n whitespace")
34
+ expect(@session).to have_text('text with whitespace')
40
35
  end
41
36
 
42
37
  it "should be false if the given text is not on the page" do
@@ -326,7 +321,7 @@ Capybara::SpecHelper.spec '#has_no_text?' do
326
321
  it "should not find element if it appears after given wait duration" do
327
322
  @session.visit('/with_js')
328
323
  @session.click_link('Click me')
329
- expect(@session).to have_no_text('Has been clicked', wait: 0.1)
324
+ expect(@session).to have_no_text('Has been clicked', wait: 0.05)
330
325
  end
331
326
  end
332
327
  end
@@ -119,7 +119,7 @@ Capybara::SpecHelper.spec "node" do
119
119
  @session.visit('/with_js')
120
120
  @session.find(:css, '#existing_content_editable_child').set('WYSIWYG')
121
121
  expect(@session.find(:css, '#existing_content_editable_child').text).to eq('WYSIWYG')
122
- expect(@session.find(:css, '#existing_content_editable_child_parent').text).to eq('Some content WYSIWYG')
122
+ expect(@session.find(:css, '#existing_content_editable_child_parent').text).to eq("Some content\nWYSIWYG")
123
123
  end
124
124
  end
125
125
  end
@@ -18,7 +18,9 @@ Capybara::SpecHelper.spec '#refresh' do
18
18
  end
19
19
 
20
20
  it "it reposts" do
21
- skip "Firefox insists on prompting without providing a way to suppress" if marionette?(@session)
21
+ if marionette?(@session) || edge?(@session)
22
+ skip "Firefox and Edge insist on prompting without providing a way to suppress"
23
+ end
22
24
  @session.visit('/form')
23
25
  @session.select('Sweden', from: 'form_region')
24
26
  @session.click_button('awesome')
@@ -63,6 +63,24 @@ Capybara::SpecHelper.spec '#reset_session!' do
63
63
  expect(@session.current_path).to eq("/")
64
64
  end
65
65
 
66
+ it "closes extra windows", requires: [:windows] do
67
+ @session.visit('/with_html')
68
+ @session.open_new_window
69
+ @session.open_new_window
70
+ expect(@session.windows.size).to eq 3
71
+ @session.reset_session!
72
+ expect(@session.windows.size).to eq 1
73
+ end
74
+
75
+ it "closes extra windows when not on the first window", requires: [:windows] do
76
+ @session.visit('/with_html')
77
+ @session.switch_to_window(@session.open_new_window)
78
+ @session.open_new_window
79
+ expect(@session.windows.size).to eq 3
80
+ @session.reset_session!
81
+ expect(@session.windows.size).to eq 1
82
+ end
83
+
66
84
  context "When reuse_server == false" do
67
85
  before do
68
86
  @reuse_server = Capybara.reuse_server
@@ -16,7 +16,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
16
16
 
17
17
  @session.save_screenshot
18
18
 
19
- regexp = Regexp.new(File.expand_path('capybara-\d+\.png'))
19
+ regexp = Regexp.new(File.join(Dir.pwd, 'capybara-\d+\.png'))
20
20
  expect(@session.driver).to have_received(:save_screenshot).with(regexp, {})
21
21
  end
22
22
 
@@ -36,7 +36,7 @@ Capybara::SpecHelper.spec '#save_screenshot', requires: [:screenshot] do
36
36
 
37
37
  @session.save_screenshot
38
38
 
39
- regexp = Regexp.new(File.expand_path('capybara-\d+\.png', alternative_path))
39
+ regexp = Regexp.new(File.join(alternative_path, 'capybara-\d+\.png'))
40
40
  expect(@session.driver).to have_received(:save_screenshot).with(regexp, {})
41
41
  end
42
42
 
@@ -51,9 +51,22 @@ Capybara::SpecHelper.spec '#text' do
51
51
  after { Capybara.default_selector = :xpath }
52
52
  end
53
53
 
54
- it "should strip whitespace" do
54
+ it "should be correctly normalized when visible" do
55
55
  @session.visit('/with_html')
56
- @session.find(:css, '#second')
57
- expect(@session.find(:css, '#second').text).to match(/\ADuis aute .* text with whitespace .* est laborum\.\z/)
56
+ el = @session.find(:css, '#normalized')
57
+ expect(el.text).to eq "Some text\nMore text\nAnd more text\nEven more text on multiple lines"
58
+ end
59
+
60
+ it "should be a textContent with irrelevant whitespace collapsed when non-visible" do
61
+ @session.visit('/with_html')
62
+ el = @session.find(:css, '#non_visible_normalized', visible: false)
63
+ expect(el.text(:all)).to eq "Some textMore text And more text Even more text on multiple lines"
64
+ end
65
+
66
+ it "should strip correctly" do
67
+ @session.visit('/with_html')
68
+ el = @session.find(:css, '#ws')
69
+ expect(el.text).to eq " "
70
+ expect(el.text(:all)).to eq " "
58
71
  end
59
72
  end
@@ -14,4 +14,14 @@ Capybara::SpecHelper.spec '#title' do
14
14
  end
15
15
  after { Capybara.default_selector = :xpath }
16
16
  end
17
+
18
+ context "within iframe", requires: [:frames] do
19
+ it "should get the title of the top level browsing context" do
20
+ @session.visit('/within_frames')
21
+ expect(@session.title).to eq('With Frames')
22
+ @session.within_frame('frameOne') do
23
+ expect(@session.title).to eq('With Frames')
24
+ end
25
+ end
26
+ end
17
27
  end
@@ -20,16 +20,15 @@ Capybara::SpecHelper.spec '#within_window', requires: [:windows] do
20
20
 
21
21
  context "with an instance of Capybara::Window" do
22
22
  it "should not invoke driver#switch_to_window when given current window" do
23
- # switch_to_window is invoked in after hook
24
- expect(@session.driver).to receive(:switch_to_window).exactly(3).times.and_call_original
23
+ allow(@session.driver).to receive(:switch_to_window).and_call_original
25
24
  @session.within_window @window do
26
25
  expect(@session.title).to eq('With Windows')
27
26
  end
27
+ expect(@session.driver).not_to have_received(:switch_to_window)
28
28
  end
29
29
 
30
30
  it "should be able to switch to another window" do
31
31
  window = (@session.windows - [@window]).first
32
- expect(@session.driver).to receive(:switch_to_window).exactly(5).times.and_call_original
33
32
  @session.within_window window do
34
33
  expect(@session).to have_title(/Title of the first popup|Title of popup two/)
35
34
  end
@@ -133,6 +133,10 @@ module Capybara
133
133
  def chrome_gte?(version, session)
134
134
  chrome?(session) && (session.driver.browser.capabilities[:version].to_f >= version)
135
135
  end
136
+
137
+ def edge?(session)
138
+ session.respond_to?(:driver) && session.driver.respond_to?(:edge?, true) && session.driver.send(:edge?)
139
+ end
136
140
  end
137
141
  end
138
142
 
@@ -144,6 +144,15 @@ class TestApp < Sinatra::Base
144
144
  erb :with_html, locals: { referrer: request.referrer }
145
145
  end
146
146
 
147
+ get '/with_title' do
148
+ <<-HTML
149
+ <title>#{params[:title] || 'Test Title'}</title>
150
+ <body>
151
+ <svg><title>abcdefg</title></svg>
152
+ </body>
153
+ HTML
154
+ end
155
+
147
156
  get '/:view' do |view|
148
157
  erb view.to_sym, locals: { referrer: request.referrer }
149
158
  end
@@ -426,6 +426,12 @@ New line after and before textarea tag
426
426
  <input type="button" disabled="disabled" value="Disabled button"/>
427
427
  </p>
428
428
 
429
+ <p>
430
+ <input type="date" name="form[date]" id="form_date"/>
431
+ <input type="time" name="form[time]" id="form_time"/>
432
+ <input type="datetime-local" name="form[datetime]" id="form_datetime">
433
+ </p>
434
+
429
435
  <p>
430
436
  <input id="readonly" name="form[readonly_test]" readonly/>
431
437
  <input id="not_readonly" name="form[readonly_test]" />
@@ -153,3 +153,23 @@ banana</textarea>
153
153
  </div>
154
154
 
155
155
  <div id='1escape.me' class="2escape">needs escaping</div>
156
+
157
+ <div id="normalized">
158
+ Some text<div>More text</div>
159
+ <div> And more text</div>
160
+ Even more &nbsp;&nbsp; text
161
+
162
+ on multiple lines
163
+ </div>
164
+
165
+ <div id="non_visible_normalized" style="display: none">
166
+ Some text<div>More text</div>
167
+ <div> And more text</div>
168
+ Even more &nbsp;&nbsp; text
169
+
170
+ on multiple lines
171
+ </div>
172
+
173
+ <div id="ws">
174
+ &#x20;&#x1680;&#x2000;&#x2001;&#x2002; &#x2003;&#x2004;&nbsp;&#x2005; &#x2006;&#x2007;&#x2008;&#x2009;&#x200A;&#x202F;&#x205F;&#x3000;
175
+ </div>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Capybara
4
- VERSION = '3.0.0.rc1'.freeze
4
+ VERSION = '3.0.0.rc2'.freeze
5
5
  end
@@ -28,6 +28,8 @@ skipped_tests = %i[response_headers status_code trigger]
28
28
  # skip window tests when headless for now - closing a window not supported by chromedriver/chrome
29
29
  skipped_tests << :windows if ENV['TRAVIS'] && (ENV['SKIP_WINDOW'] || ENV['HEADLESS'])
30
30
 
31
+ $stdout.puts `#{Selenium::WebDriver::Chrome.driver_path} --version` if ENV['CI']
32
+
31
33
  Capybara::SpecHelper.run_specs TestSessions::Chrome, CHROME_DRIVER.to_s, capybara_skip: skipped_tests
32
34
 
33
35
  RSpec.describe "Capybara::Session with chrome" do
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require "selenium-webdriver"
5
+ require 'shared_selenium_session'
6
+ require 'rspec/shared_spec_matchers'
7
+
8
+ Capybara.register_driver :selenium_edge do |app|
9
+ # ::Selenium::WebDriver.logger.level = "debug"
10
+ Capybara::Selenium::Driver.new(app, browser: :edge)
11
+ end
12
+
13
+ module TestSessions
14
+ SeleniumEdge = Capybara::Session.new(:selenium_edge, TestApp)
15
+ end
16
+
17
+ skipped_tests = %i[response_headers status_code trigger modals]
18
+
19
+ $stdout.puts `#{Selenium::WebDriver::Edge.driver_path} --version` if ENV['CI']
20
+
21
+ Capybara::SpecHelper.run_specs TestSessions::SeleniumEdge, "selenium", capybara_skip: skipped_tests
22
+
23
+ RSpec.describe "Capybara::Session with Edge" do
24
+ include Capybara::SpecHelper
25
+ include_examples "Capybara::Session", TestSessions::SeleniumEdge, :selenium_edge
26
+ include_examples Capybara::RSpecMatchers, TestSessions::SeleniumEdge, :selenium_edge
27
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require "selenium-webdriver"
5
+ require 'shared_selenium_session'
6
+ require 'rspec/shared_spec_matchers'
7
+
8
+ Capybara.register_driver :selenium_ie do |app|
9
+ # ::Selenium::WebDriver.logger.level = "debug"
10
+ Capybara::Selenium::Driver.new(app, browser: :ie)
11
+ end
12
+
13
+ module TestSessions
14
+ SeleniumIE = Capybara::Session.new(:selenium_ie, TestApp)
15
+ end
16
+
17
+ skipped_tests = %i[response_headers status_code trigger]
18
+
19
+ $stdout.puts `#{Selenium::WebDriver::IE.driver_path} --version` if ENV['CI']
20
+
21
+ Capybara::SpecHelper.run_specs TestSessions::SeleniumIE, "selenium", capybara_skip: skipped_tests
22
+
23
+ RSpec.describe "Capybara::Session with Internet Explorer" do
24
+ include Capybara::SpecHelper
25
+ include_examples "Capybara::Session", TestSessions::SeleniumIE, :selenium_ie
26
+ include_examples Capybara::RSpecMatchers, TestSessions::SeleniumIE, :selenium_ie
27
+ end
@@ -40,6 +40,8 @@ end
40
40
  skipped_tests = %i[response_headers status_code trigger]
41
41
  skipped_tests << :windows if ENV['TRAVIS'] && ENV['SKIP_WINDOW']
42
42
 
43
+ $stdout.puts `#{Selenium::WebDriver::Firefox.driver_path} --version` if ENV['CI']
44
+
43
45
  Capybara::SpecHelper.run_specs TestSessions::SeleniumMarionette, "selenium", capybara_skip: skipped_tests
44
46
 
45
47
  RSpec.describe "Capybara::Session with firefox" do
@@ -35,7 +35,7 @@ RSpec.describe Capybara::Server do
35
35
  ensure
36
36
  Capybara.server_host = nil
37
37
  end
38
- end unless ENV['TRAVIS'] and (RUBY_ENGINE == 'jruby')
38
+ end unless ENV['TRAVIS'] && (RUBY_ENGINE == 'jruby') or Gem.win_platform?
39
39
 
40
40
  it "should use specified port" do
41
41
  Capybara.server_port = 22789
@@ -64,6 +64,7 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
64
64
  end
65
65
 
66
66
  it "can be called before visiting" do
67
+ skip "Edge driver doesn't get any interactions when alert is set" if edge?(@session)
67
68
  @session.accept_alert "Initial alert" do
68
69
  @session.visit('/initial_alert')
69
70
  end
@@ -217,5 +218,13 @@ RSpec.shared_examples "Capybara::Session" do |session, mode|
217
218
  expect(@session).to have_current_path('/')
218
219
  end
219
220
  end
221
+
222
+ context "Windows" do
223
+ it "can't close the primary window" do
224
+ expect do
225
+ @session.current_window.close
226
+ end.to raise_error(ArgumentError, 'Not allowed to close the primary window')
227
+ end
228
+ end
220
229
  end
221
230
  end
@@ -2,10 +2,10 @@
2
2
 
3
3
  require 'rspec/expectations'
4
4
  require "capybara/spec/spec_helper"
5
- require 'webdrivers' if ENV['TRAVIS']
5
+ require 'webdrivers' if ENV['CI']
6
6
 
7
7
  RSpec.configure do |config|
8
8
  Capybara::SpecHelper.configure(config)
9
- config.filter_run_including focus_: true unless ENV['TRAVIS']
9
+ config.filter_run_including focus_: true unless ENV['CI']
10
10
  config.run_all_when_everything_filtered = true
11
11
  end
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: 3.0.0.rc1
4
+ version: 3.0.0.rc2
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: 2018-03-02 00:00:00.000000000 Z
13
+ date: 2018-03-23 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: addressable
@@ -371,6 +371,8 @@ files:
371
371
  - lib/capybara/spec/session/find_link_spec.rb
372
372
  - lib/capybara/spec/session/find_spec.rb
373
373
  - lib/capybara/spec/session/first_spec.rb
374
+ - lib/capybara/spec/session/frame/frame_title_spec.rb
375
+ - lib/capybara/spec/session/frame/frame_url_spec.rb
374
376
  - lib/capybara/spec/session/frame/switch_to_frame_spec.rb
375
377
  - lib/capybara/spec/session/frame/within_frame_spec.rb
376
378
  - lib/capybara/spec/session/go_back_spec.rb
@@ -471,6 +473,8 @@ files:
471
473
  - spec/rspec_spec.rb
472
474
  - spec/selector_spec.rb
473
475
  - spec/selenium_spec_chrome.rb
476
+ - spec/selenium_spec_edge.rb
477
+ - spec/selenium_spec_ie.rb
474
478
  - spec/selenium_spec_marionette.rb
475
479
  - spec/server_spec.rb
476
480
  - spec/session_spec.rb