capybara 3.0.0.rc1 → 3.0.0.rc2

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