selenium-webdriver 3.0.0.beta4.0 → 4.0.0.alpha5

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 (139) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +679 -0
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/README.md +1 -1
  6. data/lib/selenium-webdriver.rb +2 -2
  7. data/lib/selenium/server.rb +23 -16
  8. data/lib/selenium/webdriver.rb +43 -25
  9. data/lib/selenium/webdriver/atoms.rb +20 -1
  10. data/lib/selenium/webdriver/atoms/findElements.js +122 -0
  11. data/lib/selenium/webdriver/atoms/getAttribute.js +84 -11
  12. data/lib/selenium/webdriver/atoms/isDisplayed.js +100 -0
  13. data/lib/selenium/webdriver/chrome.rb +15 -20
  14. data/lib/selenium/webdriver/chrome/bridge.rb +29 -66
  15. data/lib/selenium/webdriver/{edge/service.rb → chrome/driver.rb} +19 -22
  16. data/lib/selenium/webdriver/chrome/options.rb +221 -0
  17. data/lib/selenium/webdriver/chrome/profile.rb +6 -7
  18. data/lib/selenium/webdriver/chrome/service.rb +20 -20
  19. data/lib/selenium/webdriver/common.rb +19 -11
  20. data/lib/selenium/webdriver/common/action_builder.rb +98 -246
  21. data/lib/selenium/webdriver/common/alert.rb +2 -7
  22. data/lib/selenium/webdriver/common/driver.rb +89 -51
  23. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
  24. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_debugger.rb} +12 -25
  26. data/lib/selenium/webdriver/common/driver_extensions/has_devtools.rb +38 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +3 -5
  28. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
  29. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +3 -3
  30. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
  31. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +2 -2
  32. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +2 -2
  33. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +2 -2
  34. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +4 -4
  35. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +9 -3
  36. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +3 -5
  37. data/lib/selenium/webdriver/common/element.rb +32 -10
  38. data/lib/selenium/webdriver/common/error.rb +103 -121
  39. data/lib/selenium/webdriver/common/file_reaper.rb +3 -5
  40. data/lib/selenium/webdriver/common/html5/local_storage.rb +2 -2
  41. data/lib/selenium/webdriver/common/html5/session_storage.rb +2 -2
  42. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +3 -2
  43. data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
  44. data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
  45. data/lib/selenium/webdriver/{phantomjs.rb → common/interactions/interactions.rb} +17 -20
  46. data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
  47. data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
  48. data/lib/selenium/webdriver/common/interactions/none_input.rb +36 -0
  49. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
  50. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
  51. data/lib/selenium/webdriver/common/keys.rb +37 -15
  52. data/lib/selenium/webdriver/common/log_entry.rb +4 -4
  53. data/lib/selenium/webdriver/common/logger.rb +147 -0
  54. data/lib/selenium/webdriver/common/logs.rb +2 -2
  55. data/lib/selenium/webdriver/common/manager.rb +177 -0
  56. data/lib/selenium/webdriver/common/navigation.rb +2 -2
  57. data/lib/selenium/webdriver/common/options.rb +47 -105
  58. data/lib/selenium/webdriver/common/platform.rb +44 -38
  59. data/lib/selenium/webdriver/common/port_prober.rb +8 -19
  60. data/lib/selenium/webdriver/common/profile_helper.rb +13 -5
  61. data/lib/selenium/webdriver/common/proxy.rb +14 -8
  62. data/lib/selenium/webdriver/common/search_context.rb +16 -20
  63. data/lib/selenium/webdriver/common/service.rb +115 -30
  64. data/lib/selenium/webdriver/common/socket_lock.rb +12 -7
  65. data/lib/selenium/webdriver/common/socket_poller.rb +29 -22
  66. data/lib/selenium/webdriver/common/target_locator.rb +6 -6
  67. data/lib/selenium/webdriver/common/timeouts.rb +2 -2
  68. data/lib/selenium/webdriver/common/wait.rb +14 -8
  69. data/lib/selenium/webdriver/common/window.rb +38 -2
  70. data/lib/selenium/webdriver/common/zipper.rb +3 -5
  71. data/lib/selenium/webdriver/edge.rb +33 -20
  72. data/lib/selenium/webdriver/edge_chrome/bridge.rb +30 -0
  73. data/lib/selenium/webdriver/edge_chrome/driver.rb +38 -0
  74. data/lib/selenium/webdriver/{common/driver_extensions/has_touch_screen.rb → edge_chrome/options.rb} +10 -12
  75. data/lib/selenium/webdriver/edge_chrome/profile.rb +33 -0
  76. data/lib/selenium/webdriver/edge_chrome/service.rb +36 -0
  77. data/lib/selenium/webdriver/edge_html/driver.rb +39 -0
  78. data/lib/selenium/webdriver/edge_html/options.rb +91 -0
  79. data/lib/selenium/webdriver/edge_html/service.rb +47 -0
  80. data/lib/selenium/webdriver/firefox.rb +24 -29
  81. data/lib/selenium/webdriver/firefox/bridge.rb +15 -39
  82. data/lib/selenium/webdriver/firefox/{util.rb → driver.rb} +13 -19
  83. data/lib/selenium/webdriver/firefox/extension.rb +28 -8
  84. data/lib/selenium/webdriver/firefox/options.rb +162 -0
  85. data/lib/selenium/webdriver/firefox/profile.rb +23 -82
  86. data/lib/selenium/webdriver/firefox/profiles_ini.rb +5 -5
  87. data/lib/selenium/webdriver/firefox/service.rb +18 -37
  88. data/lib/selenium/webdriver/ie.rb +13 -19
  89. data/lib/selenium/webdriver/ie/driver.rb +40 -0
  90. data/lib/selenium/webdriver/ie/options.rb +118 -0
  91. data/lib/selenium/webdriver/ie/service.rb +20 -20
  92. data/lib/selenium/webdriver/remote.rb +15 -17
  93. data/lib/selenium/webdriver/remote/bridge.rb +281 -300
  94. data/lib/selenium/webdriver/remote/capabilities.rb +102 -83
  95. data/lib/selenium/webdriver/remote/commands.rb +132 -192
  96. data/lib/selenium/webdriver/remote/driver.rb +52 -0
  97. data/lib/selenium/webdriver/remote/http/common.rb +23 -13
  98. data/lib/selenium/webdriver/remote/http/curb.rb +10 -7
  99. data/lib/selenium/webdriver/remote/http/default.rb +52 -32
  100. data/lib/selenium/webdriver/remote/http/persistent.rb +8 -4
  101. data/lib/selenium/webdriver/remote/response.rb +32 -35
  102. data/lib/selenium/webdriver/remote/server_error.rb +2 -2
  103. data/lib/selenium/webdriver/safari.rb +24 -22
  104. data/lib/selenium/webdriver/safari/bridge.rb +21 -21
  105. data/lib/selenium/webdriver/safari/driver.rb +41 -0
  106. data/lib/selenium/webdriver/safari/options.rb +66 -0
  107. data/lib/selenium/webdriver/safari/service.rb +8 -24
  108. data/lib/selenium/webdriver/support.rb +3 -2
  109. data/lib/selenium/webdriver/support/abstract_event_listener.rb +2 -2
  110. data/lib/selenium/webdriver/support/block_event_listener.rb +3 -3
  111. data/lib/selenium/webdriver/support/color.rb +13 -13
  112. data/lib/selenium/webdriver/support/escaper.rb +2 -2
  113. data/lib/selenium/webdriver/support/event_firing_bridge.rb +4 -4
  114. data/lib/selenium/webdriver/support/relative_locator.rb +51 -0
  115. data/lib/selenium/webdriver/support/select.rb +20 -21
  116. data/lib/selenium/webdriver/version.rb +24 -0
  117. data/selenium-webdriver.gemspec +31 -17
  118. metadata +331 -248
  119. data/lib/selenium/webdriver/common/bridge_helper.rb +0 -82
  120. data/lib/selenium/webdriver/common/keyboard.rb +0 -69
  121. data/lib/selenium/webdriver/common/mouse.rb +0 -88
  122. data/lib/selenium/webdriver/common/touch_action_builder.rb +0 -81
  123. data/lib/selenium/webdriver/common/touch_screen.rb +0 -121
  124. data/lib/selenium/webdriver/common/w3c_error.rb +0 -191
  125. data/lib/selenium/webdriver/edge/bridge.rb +0 -76
  126. data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
  127. data/lib/selenium/webdriver/firefox/binary.rb +0 -186
  128. data/lib/selenium/webdriver/firefox/extension/prefs.json +0 -69
  129. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  130. data/lib/selenium/webdriver/firefox/launcher.rb +0 -114
  131. data/lib/selenium/webdriver/firefox/native/linux/amd64/x_ignore_nofocus.so +0 -0
  132. data/lib/selenium/webdriver/firefox/native/linux/x86/x_ignore_nofocus.so +0 -0
  133. data/lib/selenium/webdriver/firefox/w3c_bridge.rb +0 -79
  134. data/lib/selenium/webdriver/ie/bridge.rb +0 -76
  135. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -65
  136. data/lib/selenium/webdriver/phantomjs/service.rb +0 -66
  137. data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -682
  138. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -228
  139. data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -135
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -22,7 +22,7 @@ module Selenium
22
22
  module Keys
23
23
  #
24
24
  # @see Element#send_keys
25
- # @see http://www.google.com.au/search?&q=unicode+pua&btnG=Search
25
+ # @see http://www.google.com.au/search?&q=unicode+pua&btnK=Search
26
26
  #
27
27
 
28
28
  KEYS = {
@@ -88,7 +88,22 @@ module Selenium
88
88
  f11: "\ue03B",
89
89
  f12: "\ue03C",
90
90
  meta: "\ue03D",
91
- command: "\ue03D" # alias
91
+ command: "\ue03D", # alias
92
+ left_meta: "\ue03D", # alias
93
+ right_shift: "\ue050",
94
+ right_control: "\ue051",
95
+ right_alt: "\ue052",
96
+ right_meta: "\ue053",
97
+ numpad_page_up: "\ue054",
98
+ numpad_page_down: "\ue055",
99
+ numpad_end: "\ue056",
100
+ numpad_home: "\ue057",
101
+ numpad_left: "\ue058",
102
+ numpad_up: "\ue059",
103
+ numpad_right: "\ue05A",
104
+ numpad_down: "\ue05B",
105
+ numpad_insert: "\ue05C",
106
+ numpad_delete: "\ue05D"
92
107
  }.freeze
93
108
 
94
109
  #
@@ -97,6 +112,7 @@ module Selenium
97
112
 
98
113
  def self.[](key)
99
114
  return KEYS[key] if KEYS[key]
115
+
100
116
  raise Error::UnsupportedOperationError, "no such key #{key.inspect}"
101
117
  end
102
118
 
@@ -105,18 +121,24 @@ module Selenium
105
121
  #
106
122
 
107
123
  def self.encode(keys)
108
- keys.map do |arg|
109
- case arg
110
- when Symbol
111
- Keys[arg]
112
- when Array
113
- arg = arg.map { |e| e.is_a?(Symbol) ? Keys[e] : e }.join
114
- arg << Keys[:null]
124
+ keys.map { |key| encode_key(key) }
125
+ end
126
+
127
+ #
128
+ # @api private
129
+ #
130
+
131
+ def self.encode_key(key)
132
+ case key
133
+ when Symbol
134
+ Keys[key]
135
+ when Array
136
+ key = key.map { |e| e.is_a?(Symbol) ? Keys[e] : e }.join
137
+ key << Keys[:null]
115
138
 
116
- arg
117
- else
118
- arg.to_s
119
- end
139
+ key
140
+ else
141
+ key.to_s
120
142
  end
121
143
  end
122
144
  end # Keys
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -30,9 +30,9 @@ module Selenium
30
30
 
31
31
  def as_json(*)
32
32
  {
33
- 'level' => level,
33
+ 'level' => level,
34
34
  'timestamp' => timestamp,
35
- 'message' => message
35
+ 'message' => message
36
36
  }
37
37
  end
38
38
 
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ require 'forwardable'
21
+ require 'logger'
22
+
23
+ module Selenium
24
+ module WebDriver
25
+ #
26
+ # @example Enable full logging
27
+ # Selenium::WebDriver.logger.level = :debug
28
+ #
29
+ # @example Log to file
30
+ # Selenium::WebDriver.logger.output = 'selenium.log'
31
+ #
32
+ # @example Use logger manually
33
+ # Selenium::WebDriver.logger.info('This is info message')
34
+ # Selenium::WebDriver.logger.warn('This is warning message')
35
+ #
36
+ class Logger
37
+ extend Forwardable
38
+
39
+ def_delegators :@logger,
40
+ :close,
41
+ :debug, :debug?,
42
+ :info, :info?,
43
+ :warn, :warn?,
44
+ :error, :error?,
45
+ :fatal, :fatal?,
46
+ :level, :level=
47
+
48
+ #
49
+ # @param [String] progname Allow child projects to use Selenium's Logger pattern
50
+ #
51
+ def initialize(progname = 'Selenium')
52
+ @logger = create_logger(progname)
53
+ @ignored = []
54
+ end
55
+
56
+ #
57
+ # Changes logger output to a new IO.
58
+ #
59
+ # @param [String] io
60
+ #
61
+ def output=(io)
62
+ @logger.reopen(io)
63
+ end
64
+
65
+ #
66
+ # Returns IO object used by logger internally.
67
+ #
68
+ # Normally, we would have never needed it, but we want to
69
+ # use it as IO object for all child processes to ensure their
70
+ # output is redirected there.
71
+ #
72
+ # It is only used in debug level, in other cases output is suppressed.
73
+ #
74
+ # @api private
75
+ #
76
+ def io
77
+ @logger.instance_variable_get(:@logdev).dev
78
+ end
79
+
80
+ #
81
+ # Will not log the provided ID.
82
+ #
83
+ # @param [Array, Symbol] id
84
+ #
85
+ def ignore(id)
86
+ Array(id).each { |ignore| @ignored << ignore }
87
+ end
88
+
89
+ #
90
+ # Overrides default #warn to skip ignored messages by provided id
91
+ #
92
+ # @param [String] message
93
+ # @param [Symbol, Array<Sybmol>] id
94
+ # @yield see #deprecate
95
+ #
96
+ def warn(message, id: [])
97
+ id = Array(id)
98
+ return if (@ignored & id).any?
99
+
100
+ msg = id.empty? ? message : "[#{id.map(&:inspect).join(', ')}] #{message} "
101
+ msg += " #{yield}" if block_given?
102
+
103
+ @logger.warn { msg }
104
+ end
105
+
106
+ #
107
+ # Marks code as deprecated with/without replacement.
108
+ #
109
+ # @param [String] old
110
+ # @param [String, nil] new
111
+ # @param [Symbol, Array<Sybmol>] id
112
+ # @yield appends additional message to end of provided template
113
+ #
114
+ def deprecate(old, new = nil, id: [], &block)
115
+ id = Array(id)
116
+ return if @ignored.include?(:deprecations) || (@ignored & id).any?
117
+
118
+ ids = id.empty? ? '' : "[#{id.map(&:inspect).join(', ')}] "
119
+
120
+ message = +"[DEPRECATION] #{ids}#{old} is deprecated"
121
+ message << if new
122
+ ". Use #{new} instead."
123
+ else
124
+ ' and will be removed in a future release.'
125
+ end
126
+ warn message, &block
127
+ end
128
+
129
+ private
130
+
131
+ def create_logger(name)
132
+ logger = ::Logger.new($stdout)
133
+ logger.progname = name
134
+ logger.level = default_level
135
+ logger.formatter = proc do |severity, time, progname, msg|
136
+ "#{time.strftime('%F %T')} #{severity} #{progname} #{msg}\n"
137
+ end
138
+
139
+ logger
140
+ end
141
+
142
+ def default_level
143
+ $DEBUG || ENV.key?('DEBUG') ? :debug : :warn
144
+ end
145
+ end # Logger
146
+ end # WebDriver
147
+ end # Selenium
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Licensed to the Software Freedom Conservancy (SFC) under one
4
+ # or more contributor license agreements. See the NOTICE file
5
+ # distributed with this work for additional information
6
+ # regarding copyright ownership. The SFC licenses this file
7
+ # to you under the Apache License, Version 2.0 (the
8
+ # "License"); you may not use this file except in compliance
9
+ # with the License. You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing,
14
+ # software distributed under the License is distributed on an
15
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ # KIND, either express or implied. See the License for the
17
+ # specific language governing permissions and limitations
18
+ # under the License.
19
+
20
+ module Selenium
21
+ module WebDriver
22
+ class Manager
23
+ #
24
+ # @api private
25
+ #
26
+
27
+ def initialize(bridge)
28
+ @bridge = bridge
29
+ end
30
+
31
+ #
32
+ # Add a cookie to the browser
33
+ #
34
+ # @param [Hash] opts the options to create a cookie with.
35
+ # @option opts [String] :name A name
36
+ # @option opts [String] :value A value
37
+ # @option opts [String] :path ('/') A path
38
+ # @option opts [String] :secure (false) A boolean
39
+ # @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
40
+ #
41
+ # @raise [ArgumentError] if :name or :value is not specified
42
+ #
43
+
44
+ def add_cookie(opts = {})
45
+ raise ArgumentError, 'name is required' unless opts[:name]
46
+ raise ArgumentError, 'value is required' unless opts[:value]
47
+
48
+ opts[:path] ||= '/'
49
+ opts[:secure] ||= false
50
+
51
+ obj = opts.delete(:expires)
52
+ opts[:expiry] = seconds_from(obj).to_i if obj
53
+
54
+ @bridge.add_cookie opts
55
+ end
56
+
57
+ #
58
+ # Get the cookie with the given name
59
+ #
60
+ # @param [String] name the name of the cookie
61
+ # @return [Hash, nil] the cookie, or nil if it wasn't found.
62
+ #
63
+
64
+ def cookie_named(name)
65
+ convert_cookie(@bridge.cookie(name))
66
+ end
67
+
68
+ #
69
+ # Delete the cookie with the given name
70
+ #
71
+ # @param [String] name the name of the cookie to delete
72
+ #
73
+
74
+ def delete_cookie(name)
75
+ @bridge.delete_cookie name
76
+ end
77
+
78
+ #
79
+ # Delete all cookies
80
+ #
81
+
82
+ def delete_all_cookies
83
+ @bridge.delete_all_cookies
84
+ end
85
+
86
+ #
87
+ # Get all cookies
88
+ #
89
+ # @return [Array<Hash>] list of cookies
90
+ #
91
+
92
+ def all_cookies
93
+ @bridge.cookies.map { |cookie| convert_cookie(cookie) }
94
+ end
95
+
96
+ def timeouts
97
+ @timeouts ||= Timeouts.new(@bridge)
98
+ end
99
+
100
+ #
101
+ # @api beta This API may be changed or removed in a future release.
102
+ #
103
+
104
+ def logs
105
+ @logs ||= Logs.new(@bridge)
106
+ end
107
+
108
+ #
109
+ # Create a new top-level browsing context
110
+ # https://w3c.github.io/webdriver/#new-window
111
+ # @param type [Symbol] Supports two values: :tab and :window.
112
+ # Use :tab if you'd like the new window to share an OS-level window
113
+ # with the current browsing context.
114
+ # Use :window otherwise
115
+ # @return [String] The value of the window handle
116
+ #
117
+ def new_window(type = :tab)
118
+ case type
119
+ when :tab, :window
120
+ result = @bridge.new_window(type)
121
+ unless result.key?('handle')
122
+ raise UnknownError, "the driver did not return a handle. " \
123
+ "The returned result: #{result.inspect}"
124
+ end
125
+ result['handle']
126
+ else
127
+ raise ArgumentError, "invalid argument for type. Got: '#{type.inspect}'. " \
128
+ "Try :tab or :window"
129
+ end
130
+ end
131
+
132
+ #
133
+ # @api beta This API may be changed or removed in a future release.
134
+ #
135
+
136
+ def window
137
+ @window ||= Window.new(@bridge)
138
+ end
139
+
140
+ private
141
+
142
+ SECONDS_PER_DAY = 86_400.0
143
+
144
+ def datetime_at(int)
145
+ DateTime.civil(1970) + (int / SECONDS_PER_DAY)
146
+ end
147
+
148
+ def seconds_from(obj)
149
+ case obj
150
+ when Time
151
+ obj.to_f
152
+ when DateTime
153
+ (obj - DateTime.civil(1970)) * SECONDS_PER_DAY
154
+ when Numeric
155
+ obj
156
+ else
157
+ raise ArgumentError, "invalid value for expiration date: #{obj.inspect}"
158
+ end
159
+ end
160
+
161
+ def strip_port(str)
162
+ str.split(':', 2).first
163
+ end
164
+
165
+ def convert_cookie(cookie)
166
+ {
167
+ name: cookie['name'],
168
+ value: cookie['value'],
169
+ path: cookie['path'],
170
+ domain: cookie['domain'] && strip_port(cookie['domain']),
171
+ expires: cookie['expiry'] && datetime_at(cookie['expiry']),
172
+ secure: cookie['secure']
173
+ }
174
+ end
175
+ end # Options
176
+ end # WebDriver
177
+ end # Selenium
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -1,5 +1,5 @@
1
- # encoding: utf-8
2
- #
1
+ # frozen_string_literal: true
2
+
3
3
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
4
  # or more contributor license agreements. See the NOTICE file
5
5
  # distributed with this work for additional information
@@ -20,131 +20,73 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  class Options
23
- #
24
- # @api private
25
- #
26
-
27
- def initialize(bridge)
28
- @bridge = bridge
23
+ attr_accessor :options
24
+
25
+ def initialize(options: nil, **opts)
26
+ @options = if options
27
+ WebDriver.logger.deprecate(":options as keyword for initializing #{self.class}",
28
+ "custom values directly in #new constructor",
29
+ id: :options_options)
30
+ opts.merge(options)
31
+ else
32
+ opts
33
+ end
29
34
  end
30
35
 
31
36
  #
32
- # Add a cookie to the browser
37
+ # Add a new option not yet handled by bindings.
33
38
  #
34
- # @param [Hash] opts the options to create a cookie with.
35
- # @option opts [String] :name A name
36
- # @option opts [String] :value A value
37
- # @option opts [String] :path ('/') A path
38
- # @option opts [String] :secure (false) A boolean
39
- # @option opts [Time,DateTime,Numeric,nil] :expires (nil) Expiry date, either as a Time, DateTime, or seconds since epoch.
39
+ # @example Leave Chrome open when chromedriver is killed
40
+ # options = Selenium::WebDriver::Chrome::Options.new
41
+ # options.add_option(:detach, true)
40
42
  #
41
- # @raise [ArgumentError] if :name or :value is not specified
43
+ # @param [String, Symbol] name Name of the option
44
+ # @param [Boolean, String, Integer] value Value of the option
42
45
  #
43
46
 
44
- def add_cookie(opts = {})
45
- raise ArgumentError, 'name is required' unless opts[:name]
46
- raise ArgumentError, 'value is required' unless opts[:value]
47
-
48
- opts[:path] ||= '/'
49
- opts[:secure] ||= false
50
-
51
- obj = opts.delete(:expires)
52
- opts[:expiry] = seconds_from(obj).to_i if obj
53
-
54
- @bridge.add_cookie opts
47
+ def add_option(name, value)
48
+ @options[name] = value
55
49
  end
56
50
 
57
51
  #
58
- # Get the cookie with the given name
59
- #
60
- # @param [String] name the name of the cookie
61
- # @return [Hash, nil] the cookie, or nil if it wasn't found.
62
- #
63
-
64
- def cookie_named(name)
65
- all_cookies.find { |c| c[:name] == name }
66
- end
67
-
68
- #
69
- # Delete the cookie with the given name
70
- #
71
- # @param [String] name the name of the cookie to delete
72
- #
73
-
74
- def delete_cookie(name)
75
- @bridge.delete_cookie name
76
- end
77
-
78
- #
79
- # Delete all cookies
52
+ # @api private
80
53
  #
81
54
 
82
- def delete_all_cookies
83
- @bridge.delete_all_cookies
84
- end
55
+ def as_json(*)
56
+ options = @options.dup
85
57
 
86
- #
87
- # Get all cookies
88
- #
89
- # @return [Array<Hash>] list of cookies
90
- #
91
-
92
- def all_cookies
93
- @bridge.cookies.map do |cookie|
94
- {
95
- name: cookie['name'],
96
- value: cookie['value'],
97
- path: cookie['path'],
98
- domain: cookie['domain'] && strip_port(cookie['domain']),
99
- expires: cookie['expiry'] && datetime_at(cookie['expiry']),
100
- secure: cookie['secure']
101
- }
58
+ opts = self.class::CAPABILITIES.each_with_object({}) do |(capability_alias, capability_name), hash|
59
+ capability_value = options.delete(capability_alias)
60
+ hash[capability_name] = capability_value unless capability_value.nil?
102
61
  end
103
- end
104
-
105
- def timeouts
106
- @timeouts ||= Timeouts.new(@bridge)
107
- end
108
-
109
- #
110
- # @api beta This API may be changed or removed in a future release.
111
- #
112
-
113
- def logs
114
- @logs ||= Logs.new(@bridge)
115
- end
116
-
117
- #
118
- # @api beta This API may be changed or removed in a future release.
119
- #
120
-
121
- def window
122
- @window ||= Window.new(@bridge)
62
+ opts.merge(options)
123
63
  end
124
64
 
125
65
  private
126
66
 
127
- SECONDS_PER_DAY = 86_400.0
128
-
129
- def datetime_at(int)
130
- DateTime.civil(1970) + (int / SECONDS_PER_DAY)
131
- end
132
-
133
- def seconds_from(obj)
134
- case obj
135
- when Time
136
- obj.to_f
137
- when DateTime
138
- (obj - DateTime.civil(1970)) * SECONDS_PER_DAY
139
- when Numeric
140
- obj
67
+ def generate_as_json(value)
68
+ if value.respond_to?(:as_json)
69
+ value.as_json
70
+ elsif value.is_a?(Hash)
71
+ value.each_with_object({}) { |(key, val), hash| hash[convert_json_key(key)] = generate_as_json(val) }
72
+ elsif value.is_a?(Array)
73
+ value.map(&method(:generate_as_json))
74
+ elsif value.is_a?(Symbol)
75
+ value.to_s
141
76
  else
142
- raise ArgumentError, "invalid value for expiration date: #{obj.inspect}"
77
+ value
143
78
  end
144
79
  end
145
80
 
146
- def strip_port(str)
147
- str.split(':', 2).first
81
+ def convert_json_key(key)
82
+ key = camel_case(key) if key.is_a?(Symbol)
83
+ return key if key.is_a?(String)
84
+
85
+ raise TypeError, "expected String or Symbol, got #{key.inspect}:#{key.class}"
86
+ end
87
+
88
+ def camel_case(str)
89
+ str.to_s.gsub(/_([a-z])/) { Regexp.last_match(1).upcase }
148
90
  end
149
91
  end # Options
150
92
  end # WebDriver