watir 6.5.0 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +58 -21
  3. data/CHANGES.md +11 -0
  4. data/Rakefile +3 -5
  5. data/lib/watir.rb +14 -2
  6. data/lib/watir/adjacent.rb +20 -27
  7. data/lib/watir/alert.rb +1 -1
  8. data/lib/watir/attribute_helper.rb +1 -1
  9. data/lib/watir/browser.rb +6 -3
  10. data/lib/watir/capabilities.rb +95 -0
  11. data/lib/watir/cookies.rb +5 -6
  12. data/lib/watir/element_collection.rb +17 -0
  13. data/lib/watir/elements/element.rb +12 -15
  14. data/lib/watir/elements/iframe.rb +1 -1
  15. data/lib/watir/elements/option.rb +5 -6
  16. data/lib/watir/elements/select.rb +52 -36
  17. data/lib/watir/legacy_wait.rb +2 -2
  18. data/lib/watir/locators/button/selector_builder.rb +10 -7
  19. data/lib/watir/locators/element/locator.rb +2 -2
  20. data/lib/watir/locators/element/selector_builder.rb +10 -4
  21. data/lib/watir/locators/element/selector_builder/xpath.rb +22 -3
  22. data/lib/watir/logger.rb +109 -0
  23. data/lib/watir/wait.rb +6 -6
  24. data/lib/watirspec.rb +1 -1
  25. data/lib/watirspec/guards.rb +4 -4
  26. data/lib/watirspec/implementation.rb +13 -5
  27. data/lib/watirspec/remote_server.rb +38 -0
  28. data/lib/watirspec/runner.rb +2 -2
  29. data/lib/watirspec/server.rb +1 -1
  30. data/spec/browser_spec.rb +101 -17
  31. data/spec/element_locator_spec.rb +1 -1
  32. data/spec/element_spec.rb +1 -1
  33. data/spec/logger_spec.rb +46 -0
  34. data/spec/watirspec/adjacent_spec.rb +45 -0
  35. data/spec/watirspec/after_hooks_spec.rb +45 -40
  36. data/spec/watirspec/alert_spec.rb +20 -14
  37. data/spec/watirspec/browser_spec.rb +71 -77
  38. data/spec/watirspec/cookies_spec.rb +13 -16
  39. data/spec/watirspec/drag_and_drop_spec.rb +6 -6
  40. data/spec/watirspec/elements/button_spec.rb +14 -7
  41. data/spec/watirspec/elements/collections_spec.rb +18 -1
  42. data/spec/watirspec/elements/dd_spec.rb +4 -2
  43. data/spec/watirspec/elements/del_spec.rb +12 -10
  44. data/spec/watirspec/elements/div_spec.rb +17 -13
  45. data/spec/watirspec/elements/dl_spec.rb +4 -2
  46. data/spec/watirspec/elements/form_spec.rb +8 -6
  47. data/spec/watirspec/elements/frame_spec.rb +27 -19
  48. data/spec/watirspec/elements/iframe_spec.rb +28 -17
  49. data/spec/watirspec/elements/ins_spec.rb +12 -10
  50. data/spec/watirspec/elements/option_spec.rb +17 -33
  51. data/spec/watirspec/elements/select_list_spec.rb +111 -97
  52. data/spec/watirspec/elements/span_spec.rb +12 -10
  53. data/spec/watirspec/elements/table_spec.rb +13 -11
  54. data/spec/watirspec/elements/tbody_spec.rb +13 -11
  55. data/spec/watirspec/elements/td_spec.rb +6 -4
  56. data/spec/watirspec/elements/text_field_spec.rb +19 -17
  57. data/spec/watirspec/elements/tr_spec.rb +12 -8
  58. data/spec/watirspec/html/javascript/helpers.js +2 -2
  59. data/spec/watirspec/html/nested_elements.html +5 -5
  60. data/spec/watirspec/relaxed_locate_spec.rb +13 -19
  61. data/spec/watirspec/wait_spec.rb +279 -301
  62. data/spec/watirspec/window_switching_spec.rb +190 -174
  63. data/spec/watirspec_helper.rb +64 -122
  64. data/support/doctest_helper.rb +4 -0
  65. data/watir.gemspec +2 -2
  66. metadata +15 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e19bc6a7d28d78bba208d88dd97a58bce85fc9d
4
- data.tar.gz: 0031cc40646d67219270b7914369df5a7e084144
3
+ metadata.gz: da90c92ae28c4fd2e22b1bb60bdcbe18b060dee0
4
+ data.tar.gz: 9ff7214a544eda7ac4a60cd923c504f35ba92fec
5
5
  SHA512:
6
- metadata.gz: f71791589c4bc26c594d25ffb755fec75a8cbf41c2d93e0bf8c9671573a66e2fac01a21618159c169fa79a25387963a5a79c6940a329b177939b305ede9c3dbd
7
- data.tar.gz: 7ca2f02eb0a3c950f2e8b8e16ce8e1acb9c3dd8766637d8bc5c3594b49634c0dce2af3d7ec216add6d36f81968df69eb3b35215bd5a43c216b2c04883d350c98
6
+ metadata.gz: b6fbd488d5d064acaeb9b4dca1f9a3d8d6246c51b3b29d36089916e4cd3c048ccf5c343c88c8e962d1b533c8402c2a21ce3bd36db3b9dd96c2ddda89b51da2af
7
+ data.tar.gz: a42a2727efabda8ac3210efce1707636d61eab62f311ec8f3efe3542c065c02e8944e00ce41b785f260b94ad42b9abca5585868f49e89b0a2d824e5719c435f9
@@ -3,31 +3,68 @@
3
3
  # use host's /dev/shm.
4
4
  sudo: required
5
5
  dist: trusty
6
- rvm:
7
- - 2.2.7
8
- - 2.3.4
9
- - 2.4.1
10
- addons:
11
- firefox: latest
12
- apt:
13
- packages:
14
- - unzip
15
- - libxss1
16
- - google-chrome-stable
17
6
  cache: bundler
18
7
  notifications:
19
- recipients:
20
- - p0deje@gmail.com
21
- - jarmo.p@gmail.com
22
- - titusfortner@gmail.com
23
8
  slack:
24
9
  secure: BLsBCm33R32VNRccrLx9F0P24X6BVpVHj1OWaN4Kyn6g9qXteIwC2VKVMnKNbifpojfMkrn0OeFQFK1O1DSOsC3mgzn/udoB+DnUGcSemFUn04xhbYF5SI+3zGPKPo0JLvjjdEKSSma84YwKdrj88pGUK34p01gL8hiaqjFzWdk=
25
10
  before_script:
26
11
  - support/travis.sh
27
12
  script: bundle exec rake $RAKE_TASK
28
- env:
29
- - RAKE_TASK=spec:firefox
30
- - RAKE_TASK=spec:firefox RELAXED_LOCATE=false
31
- - RAKE_TASK=spec:chrome
32
- - RAKE_TASK=spec:chrome RELAXED_LOCATE=false
33
- - RAKE_TASK=yard:doctest
13
+
14
+ _version:
15
+ two: &two
16
+ language: ruby
17
+ rvm: 2.2.7
18
+ three: &three
19
+ language: ruby
20
+ rvm: 2.3.4
21
+ four: &four
22
+ language: ruby
23
+ rvm: 2.4.1
24
+
25
+ _browsers:
26
+ firefox: &firefox-latest
27
+ addons:
28
+ firefox: latest
29
+ chrome: &chrome
30
+ addons:
31
+ chrome: stable
32
+
33
+ matrix:
34
+ include:
35
+ - env: RAKE_TASK=spec:remote_firefox
36
+ <<: *four
37
+ <<: *firefox-latest
38
+ - env: RAKE_TASK=spec:remote_chrome
39
+ <<: *four
40
+ <<: *chrome
41
+ - env: RAKE_TASK=spec:firefox RELAXED_LOCATE=false
42
+ <<: *four
43
+ <<: *firefox-latest
44
+ - env: RAKE_TASK=spec:firefox
45
+ <<: *four
46
+ <<: *firefox-latest
47
+ - env: RAKE_TASK=spec:firefox
48
+ <<: *three
49
+ <<: *firefox-latest
50
+ - env: RAKE_TASK=spec:firefox
51
+ <<: *two
52
+ <<: *firefox-latest
53
+ - env: RAKE_TASK=spec:chrome
54
+ <<: *four
55
+ <<: *chrome
56
+ - env: RAKE_TASK=spec:chrome
57
+ <<: *three
58
+ <<: *chrome
59
+ - env: RAKE_TASK=spec:chrome
60
+ <<: *two
61
+ <<: *chrome
62
+ - env: RAKE_TASK=spec:chrome RELAXED_LOCATE=false
63
+ <<: *four
64
+ <<: *chrome
65
+ - env: RAKE_TASK=spec:chrome HEADLESS=true
66
+ <<: *four
67
+ <<: *chrome
68
+ - env: RAKE_TASK=yard:doctest
69
+ <<: *four
70
+ <<: *chrome
data/CHANGES.md CHANGED
@@ -1,3 +1,14 @@
1
+ ### 6.6.0 (2017-08-02)
2
+
3
+ * Implement `Select#select_all` for selecting multiple options in select list
4
+ * Deprecate `Select#select` for selecting multiple options in a list
5
+ * Implement `ElementCollection#empty?` and `ElementCollection#locate?`
6
+ * Implement `Watir::Logger` class
7
+ * Implement `Watir::Capabilities` class
8
+ * Add support for relocating elements created with `Element#to_subtype`
9
+ * Add support for locating adjacent elements with any Watir locator
10
+ * Allow locating buttons by type attribute (thanks Justin Ko )
11
+
1
12
  ### 6.5.0 (2017-07-25)
2
13
 
3
14
  * Add support for locating multiple classes using :class parameter
data/Rakefile CHANGED
@@ -125,7 +125,6 @@ namespace :spec do
125
125
  desc 'Run specs locally for all browsers'
126
126
  task browsers: [:chrome,
127
127
  :firefox,
128
- :ff_legacy,
129
128
  (:safari if Selenium::WebDriver::Platform.mac?),
130
129
  (:ie if Selenium::WebDriver::Platform.windows?),
131
130
  (:edge if Selenium::WebDriver::Platform.windows?)].compact
@@ -133,12 +132,11 @@ namespace :spec do
133
132
  desc 'Run specs remotely for all browsers'
134
133
  task remote_browsers: [:remote_chrome,
135
134
  :remote_firefox,
136
- :remote_ff_legacy,
137
135
  (:remote_safari if Selenium::WebDriver::Platform.mac?),
138
136
  (:remote_ie if Selenium::WebDriver::Platform.windows?),
139
137
  (:remote_edge if Selenium::WebDriver::Platform.windows?)].compact
140
138
 
141
- %w(firefox ff_legacy chrome safari ie edge).each do |browser|
139
+ %w(firefox chrome safari ie edge).each do |browser|
142
140
  desc "Run specs in #{browser}"
143
141
  task browser do
144
142
  ENV['WATIR_BROWSER'] = browser
@@ -147,8 +145,8 @@ namespace :spec do
147
145
 
148
146
  desc "Run specs in Remote #{browser}"
149
147
  task "remote_#{browser}" do
150
- ENV['WATIR_BROWSER'] = 'remote'
151
- ENV['REMOTE_BROWSER'] = browser
148
+ ENV['WATIR_BROWSER'] = browser
149
+ ENV["USE_REMOTE"] = 'true'
152
150
  Rake::Task[:spec].execute
153
151
  end
154
152
  end
@@ -11,9 +11,11 @@ require 'watir/alert'
11
11
  require 'watir/atoms'
12
12
  require 'watir/container'
13
13
  require 'watir/cookies'
14
+ require 'watir/capabilities'
14
15
  require 'watir/browser'
15
16
  require 'watir/screenshot'
16
17
  require 'watir/after_hooks'
18
+ require 'watir/logger'
17
19
 
18
20
  module Watir
19
21
 
@@ -43,7 +45,7 @@ module Watir
43
45
  end
44
46
 
45
47
  def always_locate_message
46
- warn <<-EOS
48
+ Watir.logger.warn <<-EOS
47
49
  Watir#always_locate is deprecated; elements are always cached and will always
48
50
  be re-located if they go stale before use.
49
51
  Use Element#stale? or Element#wait_until(&:stale?) if needed for flow control.
@@ -60,7 +62,7 @@ Use Element#stale? or Element#wait_until(&:stale?) if needed for flow control.
60
62
  end
61
63
 
62
64
  def prefer_css_message
63
- warn <<-EOS
65
+ Watir.logger.warn <<-EOS
64
66
  Watir#prefer_css is deprecated; all elements that can not be passed directly
65
67
  as Selenium locators will be translated to XPath. To continue using CSS Selectors
66
68
  require the watir_css gem - https://github.com/watir/watir_css
@@ -101,6 +103,16 @@ require the watir_css gem - https://github.com/watir/watir_css
101
103
  end
102
104
  end
103
105
 
106
+ #
107
+ # Returns logger instance that can be used across the whole Selenium.
108
+ #
109
+ # @return [Logger]
110
+ #
111
+
112
+ def self.logger
113
+ @logger ||= Watir::Logger.new
114
+ end
115
+
104
116
  end
105
117
 
106
118
  require 'watir/attribute_helper'
@@ -10,8 +10,7 @@ module Watir
10
10
  #
11
11
 
12
12
  def parent(opt = {})
13
- opt[:index] ||= 0
14
- xpath_adjacent("ancestor::", opt)
13
+ xpath_adjacent(opt.merge(adjacent: :ancestor, plural: false))
15
14
  end
16
15
 
17
16
  #
@@ -23,8 +22,7 @@ module Watir
23
22
  #
24
23
 
25
24
  def preceding_sibling(opt = {})
26
- opt[:index] ||= 0
27
- xpath_adjacent("preceding-sibling::", opt)
25
+ xpath_adjacent(opt.merge(adjacent: :preceding, plural: false))
28
26
  end
29
27
  alias_method :previous_sibling, :preceding_sibling
30
28
 
@@ -38,7 +36,7 @@ module Watir
38
36
 
39
37
  def preceding_siblings(opt = {})
40
38
  raise ArgumentError, "#previous_siblings can not take an index value" if opt[:index]
41
- xpath_adjacent("preceding-sibling::", opt)
39
+ xpath_adjacent(opt.merge(adjacent: :preceding, plural: true))
42
40
  end
43
41
  alias_method :previous_siblings, :preceding_siblings
44
42
 
@@ -51,8 +49,7 @@ module Watir
51
49
  #
52
50
 
53
51
  def following_sibling(opt = {})
54
- opt[:index] ||= 0
55
- xpath_adjacent("following-sibling::", opt)
52
+ xpath_adjacent(opt.merge(adjacent: :following, plural: false))
56
53
  end
57
54
  alias_method :next_sibling, :following_sibling
58
55
 
@@ -66,7 +63,7 @@ module Watir
66
63
 
67
64
  def following_siblings(opt = {})
68
65
  raise ArgumentError, "#next_siblings can not take an index value" if opt[:index]
69
- xpath_adjacent("following-sibling::", opt)
66
+ xpath_adjacent(opt.merge(adjacent: :following, plural: true))
70
67
  end
71
68
  alias_method :next_siblings, :following_siblings
72
69
 
@@ -79,8 +76,7 @@ module Watir
79
76
  #
80
77
 
81
78
  def child(opt = {})
82
- opt[:index] ||= 0
83
- xpath_adjacent('', opt)
79
+ xpath_adjacent(opt.merge(adjacent: :child, plural: false))
84
80
  end
85
81
 
86
82
  #
@@ -93,27 +89,24 @@ module Watir
93
89
 
94
90
  def children(opt = {})
95
91
  raise ArgumentError, "#children can not take an index value" if opt[:index]
96
- xpath_adjacent('', opt)
92
+ xpath_adjacent(opt.merge(adjacent: :child, plural: true))
97
93
  end
98
94
 
99
95
  private
100
96
 
101
- def xpath_adjacent(direction = '', opt = {})
102
- opt = opt.dup
103
- index = opt.delete :index
104
- tag_name = opt.delete :tag_name
105
- unless opt.empty?
106
- caller = caller_locations(1, 1)[0].label
107
- raise ArgumentError, "unsupported locators: #{opt.inspect} for ##{caller} method"
108
- end
109
-
110
- if index
111
- klass = tag_name ? self.send(tag_name).class : HTMLElement
112
- klass.new(self, xpath: "./#{direction}#{tag_name || '*'}[#{index + 1}]")
113
- else
114
- klass = tag_name ? Object.const_get("#{self.send(tag_name).class}Collection") : HTMLElementCollection
115
- klass.new(self, xpath: "./#{direction}#{tag_name || '*'}")
116
- end
97
+ def xpath_adjacent(opt = {})
98
+ plural = opt.delete(:plural)
99
+ opt[:index] ||= 0 unless plural || opt.values.any? { |e| e.is_a? Regexp }
100
+ klass = if !plural && opt[:tag_name]
101
+ self.send(opt[:tag_name]).class
102
+ elsif !plural
103
+ HTMLElement
104
+ elsif opt[:tag_name]
105
+ Object.const_get("#{self.send(opt[:tag_name]).class}Collection")
106
+ else
107
+ HTMLElementCollection
108
+ end
109
+ klass.new(self, opt)
117
110
  end
118
111
 
119
112
  end # Adjacent
@@ -110,7 +110,7 @@ module Watir
110
110
  message = "This code has slept for the duration of the default timeout "
111
111
  message << "waiting for an Alert to exist. If the test is still passing, "
112
112
  message << "consider using Alert#exists? instead of rescuing UnknownObjectException"
113
- warn message
113
+ Watir.logger.warn message
114
114
  end
115
115
  raise Exception::UnknownObjectException, 'unable to locate alert'
116
116
  end
@@ -62,7 +62,7 @@ module Watir
62
62
  when 'Float'
63
63
  define_float_attribute(name, attr)
64
64
  else
65
- # $stderr.puts "treating #{type.inspect} as string for now"
65
+ Watir.logger.debug "treating #{type.inspect} as string for now"
66
66
  end
67
67
  end
68
68
 
@@ -44,7 +44,8 @@ module Watir
44
44
  def initialize(browser = :chrome, *args)
45
45
  case browser
46
46
  when ::Symbol, String
47
- @driver = Selenium::WebDriver.for browser.to_sym, *args
47
+ selenium_args = Watir::Capabilities.new(browser, *args).to_args
48
+ @driver = Selenium::WebDriver.for *selenium_args
48
49
  when Selenium::WebDriver::Driver
49
50
  @driver = browser
50
51
  else
@@ -58,8 +59,10 @@ module Watir
58
59
 
59
60
  def inspect
60
61
  '#<%s:0x%x url=%s title=%s>' % [self.class, hash*2, url.inspect, title.inspect]
61
- rescue
62
- '#<%s:0x%x closed=%s>' % [self.class, hash*2, @closed.to_s]
62
+ rescue Errno::ECONNREFUSED
63
+ '#<%s:0x%x closed=true>' % [self.class, hash*2]
64
+ rescue Selenium::WebDriver::Error::UnhandledAlertError
65
+ '#<%s:0x%x alert=true>' % [self.class, hash*2]
63
66
  end
64
67
  alias selector_string inspect
65
68
 
@@ -0,0 +1,95 @@
1
+ module Watir
2
+ class Capabilities
3
+
4
+ attr_reader :options
5
+
6
+ def initialize(browser, options = {})
7
+ @browser = browser == :remote ? @options.delete(:browser).to_sym : browser.to_sym
8
+ @selenium_browser = browser == :remote || options[:url] ? :remote : browser
9
+
10
+ @options = options
11
+ @selenium_opts = {}
12
+ end
13
+
14
+ def to_args
15
+ [@selenium_browser, process_capabilities]
16
+ end
17
+
18
+ private
19
+
20
+ def process_capabilities
21
+ url = @options.delete(:url)
22
+ @selenium_opts[:url] = url if url
23
+
24
+ create_http_client
25
+
26
+ @selenium_opts[:port] = @options.delete(:port) if @options.key?(:port)
27
+
28
+ process_browser_options
29
+ process_caps
30
+
31
+ @selenium_opts
32
+ end
33
+
34
+ def create_http_client
35
+ client_timeout = @options.delete(:client_timeout)
36
+ open_timeout = @options.delete(:open_timeout)
37
+ read_timeout = @options.delete(:read_timeout)
38
+
39
+ http_client = @options.delete(:http_client)
40
+
41
+ %i(open_timeout read_timeout client_timeout).each do |t|
42
+ next if http_client.nil? || !respond_to?(t)
43
+ warn "You can now pass #{t} value directly into Watir::Browser opt without needing to use :http_client"
44
+ end
45
+
46
+ http_client ||= Selenium::WebDriver::Remote::Http::Default.new
47
+
48
+ http_client.timeout = client_timeout if client_timeout
49
+ http_client.open_timeout = open_timeout if open_timeout
50
+ http_client.read_timeout = read_timeout if read_timeout
51
+ @selenium_opts[:http_client] = http_client
52
+ end
53
+
54
+ def process_browser_options
55
+ browser_options = @options.delete(:options)
56
+
57
+ case @selenium_browser
58
+ when :chrome
59
+ if @options.key?(:args)
60
+ browser_options ||= {}
61
+ browser_options[:args] = @options.delete(:args)
62
+ end
63
+ if @options.delete(:headless)
64
+ browser_options ||= {}
65
+ browser_options[:args] << '--headless'
66
+ browser_options[:args] << '--disable-gpu'
67
+ end
68
+ @selenium_opts[:options] = Selenium::WebDriver::Chrome::Options.new(browser_options) if browser_options
69
+ when :firefox
70
+ @selenium_opts[:options] = Selenium::WebDriver::Firefox::Options.new(options) if browser_options
71
+ when :safari
72
+ @selenium_opts["safari.options"] = {'technologyPreview' => true} if @options[:technology_preview]
73
+ when :remote
74
+ if @browser == :chrome && @options.delete(:headless)
75
+ @options.delete(:args)
76
+ @options['chromeOptions'] = {'args' => ['--headless', '--disable-gpu']}
77
+ end
78
+ end
79
+ end
80
+
81
+ def process_caps
82
+ caps = @options.delete(:desired_capabilities)
83
+
84
+ if caps
85
+ warn 'You can now pass values directly into Watir::Browser opt without needing to use :desired_capabilities'
86
+ @selenium_opts.merge!(@options)
87
+ else
88
+ caps = Selenium::WebDriver::Remote::Capabilities.send @browser, @options
89
+ end
90
+
91
+ @selenium_opts[:desired_capabilities] = caps
92
+ end
93
+
94
+ end
95
+ end
@@ -56,12 +56,11 @@ module Watir
56
56
  def add(name, value, opts = {})
57
57
  cookie = {
58
58
  name: name,
59
- value: value,
60
- secure: opts[:secure],
61
- path: opts[:path],
62
- expires: opts[:expires],
63
- domain: opts[:domain]
64
- }
59
+ value: value}
60
+ cookie[:secure] = opts[:secure] if opts.key?(:secure)
61
+ cookie[:path] = opts[:path] if opts.key?(:path)
62
+ cookie[:expires] = opts[:expires] if opts.key?(:expires)
63
+ cookie[:domain] = opts[:domain] if opts.key?(:domain)
65
64
 
66
65
  @control.add_cookie cookie
67
66
  end