selenium-webdriver 2.53.3 → 3.142.7

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 (162) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +665 -8
  3. data/Gemfile +2 -0
  4. data/LICENSE +1 -1
  5. data/README.md +2 -3
  6. data/lib/selenium/server.rb +76 -73
  7. data/lib/selenium/webdriver/atoms/getAttribute.js +7 -0
  8. data/lib/selenium/webdriver/atoms/isDisplayed.js +102 -0
  9. data/lib/selenium/webdriver/{phantomjs.rb → atoms.rb} +10 -14
  10. data/lib/selenium/webdriver/chrome/bridge.rb +30 -101
  11. data/lib/selenium/webdriver/chrome/driver.rb +127 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +190 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +21 -20
  14. data/lib/selenium/webdriver/chrome/service.rb +26 -93
  15. data/lib/selenium/webdriver/chrome.rb +15 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +52 -58
  17. data/lib/selenium/webdriver/common/alert.rb +7 -15
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +18 -22
  19. data/lib/selenium/webdriver/common/driver.rb +72 -72
  20. data/lib/selenium/webdriver/common/driver_extensions/downloads_files.rb +45 -0
  21. data/lib/selenium/webdriver/common/driver_extensions/has_addons.rb +50 -0
  22. data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_debugger.rb} +11 -27
  23. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +6 -10
  24. data/lib/selenium/webdriver/common/driver_extensions/has_network_conditions.rb +51 -0
  25. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +7 -8
  26. data/lib/selenium/webdriver/common/driver_extensions/has_permissions.rb +51 -0
  27. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +2 -4
  28. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +2 -4
  29. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +3 -5
  30. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +2 -5
  31. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +6 -9
  32. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +9 -7
  33. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +3 -8
  34. data/lib/selenium/webdriver/common/element.rb +59 -39
  35. data/lib/selenium/webdriver/common/error.rb +259 -104
  36. data/lib/selenium/webdriver/common/file_reaper.rb +6 -14
  37. data/lib/selenium/webdriver/common/html5/local_storage.rb +8 -10
  38. data/lib/selenium/webdriver/common/html5/session_storage.rb +8 -10
  39. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +8 -16
  40. data/lib/selenium/webdriver/common/interactions/input_device.rb +54 -0
  41. data/lib/selenium/webdriver/common/interactions/interaction.rb +53 -0
  42. data/lib/selenium/webdriver/{safari/browser.rb → common/interactions/interactions.rb} +17 -14
  43. data/lib/selenium/webdriver/common/interactions/key_actions.rb +145 -0
  44. data/lib/selenium/webdriver/common/interactions/key_input.rb +66 -0
  45. data/lib/selenium/webdriver/{android.rb → common/interactions/none_input.rb} +14 -6
  46. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +363 -0
  47. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +139 -0
  48. data/lib/selenium/webdriver/common/keyboard.rb +10 -14
  49. data/lib/selenium/webdriver/common/keys.rb +102 -82
  50. data/lib/selenium/webdriver/common/log_entry.rb +7 -8
  51. data/lib/selenium/webdriver/common/logger.rb +115 -0
  52. data/lib/selenium/webdriver/common/logs.rb +4 -6
  53. data/lib/selenium/webdriver/common/manager.rb +177 -0
  54. data/lib/selenium/webdriver/common/mouse.rb +12 -14
  55. data/lib/selenium/webdriver/common/navigation.rb +4 -6
  56. data/lib/selenium/webdriver/common/options.rb +26 -127
  57. data/lib/selenium/webdriver/common/platform.rb +75 -101
  58. data/lib/selenium/webdriver/common/port_prober.rb +7 -19
  59. data/lib/selenium/webdriver/common/profile_helper.rb +8 -11
  60. data/lib/selenium/webdriver/common/proxy.rb +68 -74
  61. data/lib/selenium/webdriver/common/search_context.rb +28 -37
  62. data/lib/selenium/webdriver/common/service.rb +219 -0
  63. data/lib/selenium/webdriver/common/socket_lock.rb +15 -16
  64. data/lib/selenium/webdriver/common/socket_poller.rb +30 -28
  65. data/lib/selenium/webdriver/common/target_locator.rb +16 -18
  66. data/lib/selenium/webdriver/common/timeouts.rb +6 -8
  67. data/lib/selenium/webdriver/common/touch_action_builder.rb +5 -10
  68. data/lib/selenium/webdriver/common/touch_screen.rb +22 -23
  69. data/lib/selenium/webdriver/common/w3c_action_builder.rb +212 -0
  70. data/lib/selenium/webdriver/common/w3c_manager.rb +45 -0
  71. data/lib/selenium/webdriver/common/wait.rb +17 -16
  72. data/lib/selenium/webdriver/common/window.rb +50 -17
  73. data/lib/selenium/webdriver/common/zipper.rb +9 -13
  74. data/lib/selenium/webdriver/common.rb +21 -7
  75. data/lib/selenium/webdriver/edge/bridge.rb +34 -63
  76. data/lib/selenium/webdriver/edge/driver.rb +66 -0
  77. data/lib/selenium/webdriver/edge/options.rb +80 -0
  78. data/lib/selenium/webdriver/edge/service.rb +23 -95
  79. data/lib/selenium/webdriver/edge.rb +13 -13
  80. data/lib/selenium/webdriver/firefox/binary.rb +45 -60
  81. data/lib/selenium/webdriver/firefox/driver.rb +50 -0
  82. data/lib/selenium/webdriver/firefox/extension/prefs.json +3 -12
  83. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  84. data/lib/selenium/webdriver/firefox/extension.rb +20 -10
  85. data/lib/selenium/webdriver/firefox/launcher.rb +16 -22
  86. data/lib/selenium/webdriver/firefox/legacy/driver.rb +83 -0
  87. data/lib/selenium/webdriver/firefox/marionette/bridge.rb +49 -0
  88. data/lib/selenium/webdriver/firefox/marionette/driver.rb +90 -0
  89. data/lib/selenium/webdriver/firefox/options.rb +162 -0
  90. data/lib/selenium/webdriver/firefox/profile.rb +47 -48
  91. data/lib/selenium/webdriver/firefox/profiles_ini.rb +11 -18
  92. data/lib/selenium/webdriver/firefox/service.rb +24 -95
  93. data/lib/selenium/webdriver/firefox/util.rb +2 -4
  94. data/lib/selenium/webdriver/firefox.rb +27 -12
  95. data/lib/selenium/webdriver/ie/driver.rb +85 -0
  96. data/lib/selenium/webdriver/ie/options.rb +138 -0
  97. data/lib/selenium/webdriver/ie/service.rb +54 -0
  98. data/lib/selenium/webdriver/ie.rb +12 -10
  99. data/lib/selenium/webdriver/remote/bridge.rb +100 -564
  100. data/lib/selenium/webdriver/remote/capabilities.rb +98 -100
  101. data/lib/selenium/webdriver/remote/driver.rb +51 -0
  102. data/lib/selenium/webdriver/remote/http/common.rb +34 -22
  103. data/lib/selenium/webdriver/remote/http/curb.rb +13 -14
  104. data/lib/selenium/webdriver/remote/http/default.rb +62 -43
  105. data/lib/selenium/webdriver/remote/http/persistent.rb +12 -9
  106. data/lib/selenium/webdriver/remote/oss/bridge.rb +594 -0
  107. data/lib/selenium/webdriver/remote/oss/commands.rb +223 -0
  108. data/lib/selenium/webdriver/remote/response.rb +48 -28
  109. data/lib/selenium/webdriver/remote/server_error.rb +3 -5
  110. data/lib/selenium/webdriver/remote/w3c/bridge.rb +605 -0
  111. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +310 -0
  112. data/lib/selenium/webdriver/remote/w3c/commands.rb +157 -0
  113. data/lib/selenium/webdriver/remote.rb +10 -16
  114. data/lib/selenium/webdriver/safari/bridge.rb +17 -101
  115. data/lib/selenium/webdriver/{firefox/w3c_bridge.rb → safari/driver.rb} +27 -25
  116. data/lib/selenium/webdriver/safari/options.rb +29 -31
  117. data/lib/selenium/webdriver/safari/service.rb +38 -0
  118. data/lib/selenium/webdriver/safari.rb +27 -27
  119. data/lib/selenium/webdriver/support/abstract_event_listener.rb +19 -4
  120. data/lib/selenium/webdriver/support/block_event_listener.rb +3 -5
  121. data/lib/selenium/webdriver/support/color.rb +60 -43
  122. data/lib/selenium/webdriver/support/escaper.rb +43 -0
  123. data/lib/selenium/webdriver/support/event_firing_bridge.rb +39 -41
  124. data/lib/selenium/webdriver/support/select.rb +45 -97
  125. data/lib/selenium/webdriver/support.rb +3 -2
  126. data/lib/selenium/webdriver/{iphone.rb → version.rb} +3 -7
  127. data/lib/selenium/webdriver.rb +36 -23
  128. data/lib/selenium-webdriver.rb +2 -2
  129. data/selenium-webdriver.gemspec +42 -29
  130. metadata +331 -262
  131. data/lib/selenium/client/base.rb +0 -151
  132. data/lib/selenium/client/driver.rb +0 -29
  133. data/lib/selenium/client/errors.rb +0 -28
  134. data/lib/selenium/client/extensions.rb +0 -132
  135. data/lib/selenium/client/idiomatic.rb +0 -507
  136. data/lib/selenium/client/javascript_expression_builder.rb +0 -135
  137. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -32
  138. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -32
  139. data/lib/selenium/client/legacy_driver.rb +0 -1722
  140. data/lib/selenium/client/protocol.rb +0 -123
  141. data/lib/selenium/client/selenium_helper.rb +0 -49
  142. data/lib/selenium/client.rb +0 -57
  143. data/lib/selenium/rake/server_task.rb +0 -176
  144. data/lib/selenium/webdriver/android/bridge.rb +0 -68
  145. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
  146. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
  147. data/lib/selenium/webdriver/common/html5/location.rb +0 -19
  148. data/lib/selenium/webdriver/common/w3c_error.rb +0 -194
  149. data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
  150. data/lib/selenium/webdriver/firefox/bridge.rb +0 -89
  151. data/lib/selenium/webdriver/ie/bridge.rb +0 -88
  152. data/lib/selenium/webdriver/ie/server.rb +0 -133
  153. data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
  154. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -78
  155. data/lib/selenium/webdriver/phantomjs/service.rb +0 -130
  156. data/lib/selenium/webdriver/remote/commands.rb +0 -211
  157. data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -668
  158. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -236
  159. data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -132
  160. data/lib/selenium/webdriver/safari/resources/client.js +0 -7255
  161. data/lib/selenium/webdriver/safari/server.rb +0 -187
  162. data/lib/selenium-client.rb +0 -21
@@ -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,119 +20,48 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Chrome
23
-
24
- # @api private
25
- class Bridge < Remote::Bridge
26
-
27
- def initialize(opts = {})
28
- http_client = opts.delete(:http_client)
29
-
30
- if opts.has_key?(:url)
31
- url = opts.delete(:url)
32
- else
33
- @service = Service.default_service(*extract_service_args(opts))
34
- @service.start
35
-
36
- url = @service.uri
37
- end
38
-
39
- caps = create_capabilities(opts)
40
-
41
- remote_opts = {
42
- :url => url,
43
- :desired_capabilities => caps
44
- }
45
-
46
- remote_opts.merge!(:http_client => http_client) if http_client
47
-
48
- super(remote_opts)
23
+ module Bridge
24
+
25
+ COMMANDS = {
26
+ get_network_conditions: [:get, 'session/:session_id/chromium/network_conditions'],
27
+ set_network_conditions: [:post, 'session/:session_id/chromium/network_conditions'],
28
+ send_command: [:post, 'session/:session_id/goog/cdp/execute'],
29
+ get_available_log_types: [:get, 'session/:session_id/se/log/types'],
30
+ get_log: [:post, 'session/:session_id/se/log']
31
+ }.freeze
32
+
33
+ def commands(command)
34
+ COMMANDS[command] || super
49
35
  end
50
36
 
51
- def browser
52
- :chrome
37
+ def network_conditions
38
+ execute :get_network_conditions
53
39
  end
54
40
 
55
- def driver_extensions
56
- [
57
- DriverExtensions::TakesScreenshot,
58
- DriverExtensions::HasInputDevices,
59
- DriverExtensions::HasWebStorage
60
- ]
41
+ def send_command(command_params)
42
+ execute :send_command, {}, command_params
61
43
  end
62
44
 
63
- def capabilities
64
- @capabilities ||= Remote::Capabilities.chrome
45
+ def network_conditions=(conditions)
46
+ execute :set_network_conditions, {}, {network_conditions: conditions}
65
47
  end
66
48
 
67
- def quit
68
- super
69
- ensure
70
- @service.stop if @service
49
+ def available_log_types
50
+ types = execute :get_available_log_types
51
+ Array(types).map(&:to_sym)
71
52
  end
72
53
 
73
- private
74
-
75
- def create_capabilities(opts)
76
- caps = opts.delete(:desired_capabilities) { Remote::Capabilities.chrome }
77
- args = opts.delete(:args) || opts.delete(:switches)
78
- native_events = opts.delete(:native_events)
79
- verbose = opts.delete(:verbose)
80
- profile = opts.delete(:profile)
81
- detach = opts.delete(:detach)
82
- proxy = opts.delete(:proxy)
83
- no_website_testing_defaults = opts.delete(:no_website_testing_defaults)
84
- prefs = opts.delete(:prefs)
85
-
86
- unless opts.empty?
87
- raise ArgumentError, "unknown option#{'s' if opts.size != 1}: #{opts.inspect}"
88
- end
89
-
90
- chrome_options = caps['chromeOptions'] || {}
54
+ def log(type)
55
+ data = execute :get_log, {}, {type: type.to_s}
91
56
 
92
- if args
93
- unless args.kind_of? Array
94
- raise ArgumentError, ":args must be an Array of Strings"
57
+ Array(data).map do |l|
58
+ begin
59
+ LogEntry.new l.fetch('level', 'UNKNOWN'), l.fetch('timestamp'), l.fetch('message')
60
+ rescue KeyError
61
+ next
95
62
  end
96
-
97
- chrome_options['args'] = args.map { |e| e.to_s }
98
- end
99
-
100
- if profile
101
- data = profile.as_json
102
-
103
- chrome_options.merge! 'profile' => data['zip'],
104
- 'extensions' => data['extensions']
105
- end
106
-
107
- chrome_options['binary'] = Chrome.path if Chrome.path
108
- chrome_options['nativeEvents'] = true if native_events
109
- chrome_options['verbose'] = true if verbose
110
- chrome_options['detach'] = detach.nil? || !!detach
111
- chrome_options['noWebsiteTestingDefaults'] = true if no_website_testing_defaults
112
- chrome_options['prefs'] = prefs if prefs
113
-
114
- caps['chromeOptions'] = chrome_options
115
- caps['proxy'] = proxy if proxy
116
-
117
- # legacy options - for chromedriver < 17.0.963.0
118
- caps["chrome.switches"] = chrome_options['args'] if chrome_options.member?('args')
119
- %w[binary detach extensions nativeEvents noWebsiteTestingDefaults prefs profile verbose].each do |key|
120
- caps["chrome.#{key}"] = chrome_options[key] if chrome_options.member?(key)
121
63
  end
122
-
123
- caps
124
64
  end
125
-
126
- def extract_service_args(opts)
127
- args = []
128
-
129
- if opts.has_key?(:service_log_path)
130
- args << "--log-path=#{opts.delete(:service_log_path)}"
131
- end
132
-
133
- args
134
- end
135
-
136
65
  end # Bridge
137
66
  end # Chrome
138
67
  end # WebDriver
@@ -0,0 +1,127 @@
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
+ module Chrome
23
+
24
+ #
25
+ # Driver implementation for Chrome.
26
+ # @api private
27
+ #
28
+
29
+ class Driver < WebDriver::Driver
30
+ include DriverExtensions::HasNetworkConditions
31
+ include DriverExtensions::HasTouchScreen
32
+ include DriverExtensions::HasWebStorage
33
+ include DriverExtensions::HasLocation
34
+ include DriverExtensions::TakesScreenshot
35
+ include DriverExtensions::DownloadsFiles
36
+
37
+ def initialize(opts = {})
38
+ opts[:desired_capabilities] = create_capabilities(opts)
39
+
40
+ opts[:url] ||= service_url(opts)
41
+
42
+ listener = opts.delete(:listener)
43
+ @bridge = Remote::Bridge.handshake(**opts)
44
+ @bridge.extend Bridge
45
+
46
+ super(@bridge, listener: listener)
47
+ end
48
+
49
+ def browser
50
+ :chrome
51
+ end
52
+
53
+ def quit
54
+ super
55
+ ensure
56
+ @service&.stop
57
+ end
58
+
59
+ def execute_cdp(cmd, **params)
60
+ @bridge.send_command(cmd: cmd, params: params)
61
+ end
62
+
63
+ private
64
+
65
+ def create_capabilities(opts)
66
+ caps = opts.delete(:desired_capabilities) { Remote::Capabilities.chrome }
67
+ options = opts.delete(:options) { Options.new }
68
+
69
+ args = opts.delete(:args) || opts.delete(:switches)
70
+ if args
71
+ WebDriver.logger.deprecate ':args or :switches', 'Selenium::WebDriver::Chrome::Options#add_argument'
72
+ raise ArgumentError, ':args must be an Array of Strings' unless args.is_a? Array
73
+
74
+ args.each { |arg| options.add_argument(arg.to_s) }
75
+ end
76
+
77
+ profile = opts.delete(:profile)
78
+ if profile
79
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Driver#new with `:profile` parameter',
80
+ 'Selenium::WebDriver::Chrome::Options#profile or Options#add_option'
81
+
82
+ profile = profile.as_json
83
+
84
+ if options.args.none?(&/user-data-dir/.method(:match?))
85
+ options.add_argument("--user-data-dir=#{profile['directory']}")
86
+ end
87
+
88
+ if profile['extensions']
89
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Profile#extensions',
90
+ 'Selenium::WebDriver::Chrome::Options#add_extension'
91
+ profile['extensions'].each do |extension|
92
+ options.add_encoded_extension(extension)
93
+ end
94
+ end
95
+ end
96
+
97
+ if opts.key?(:detach)
98
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Driver#new with `:detach` parameter',
99
+ 'Selenium::WebDriver::Chrome::Options#new or Options#add_option'
100
+ options.add_option(:detach, opts.delete(:detach))
101
+ end
102
+
103
+ prefs = opts.delete(:prefs)
104
+ if prefs
105
+ WebDriver.logger.deprecate ':prefs', 'Selenium::WebDriver::Chrome::Options#add_preference'
106
+ prefs.each do |key, value|
107
+ options.add_preference(key, value)
108
+ end
109
+ end
110
+
111
+ options = options.as_json
112
+ caps.merge!(options) unless options[Options::KEY].empty?
113
+
114
+ if opts.key?(:proxy) || opts.key?('proxy')
115
+ WebDriver.logger.deprecate 'Selenium::WebDriver::Chrome::Driver#new with `:proxy` parameter',
116
+ 'Selenium::WebDriver::Chrome::Capabilities#proxy='
117
+
118
+ caps[:proxy] = opts.delete(:proxy) if opts.key?(:proxy)
119
+ caps[:proxy] ||= opts.delete('proxy') if opts.key?('proxy')
120
+ end
121
+
122
+ caps
123
+ end
124
+ end # Driver
125
+ end # Chrome
126
+ end # WebDriver
127
+ end # Selenium
@@ -0,0 +1,190 @@
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
+ module Chrome
23
+ class Options < WebDriver::Common::Options
24
+ attr_reader :args, :prefs, :options, :emulation, :extensions, :encoded_extensions
25
+ attr_accessor :binary, :profile, :detach
26
+
27
+ KEY = 'goog:chromeOptions'
28
+
29
+ #
30
+ # Create a new Options instance.
31
+ #
32
+ # @example
33
+ # options = Selenium::WebDriver::Chrome::Options.new(args: ['start-maximized', 'user-data-dir=/tmp/temp_profile'])
34
+ # driver = Selenium::WebDriver.for(:chrome, options: options)
35
+ #
36
+ # @param [Hash] opts the pre-defined options to create the Chrome::Options with
37
+ # @option opts [Array<String>] :args List of command-line arguments to use when starting Chrome
38
+ # @option opts [String] :binary Path to the Chrome executable to use
39
+ # @option opts [Hash] :prefs A hash with each entry consisting of the name of the preference and its value
40
+ # @option opts [Array<String>] :extensions A list of paths to (.crx) Chrome extensions to install on startup
41
+ # @option opts [Hash] :options A hash for raw options
42
+ # @option opts [Hash] :emulation A hash for raw emulation options
43
+ #
44
+
45
+ def initialize(**opts)
46
+ @args = Set.new(opts.delete(:args) || [])
47
+ @binary = opts.delete(:binary) || Chrome.path
48
+ @prefs = opts.delete(:prefs) || {}
49
+ @extensions = opts.delete(:extensions) || []
50
+ @options = opts.delete(:options) || {}
51
+ @emulation = opts.delete(:emulation) || {}
52
+ @detach = opts.delete(:detach)
53
+ @profile = opts.delete(:profile)
54
+ @encoded_extensions = []
55
+ end
56
+
57
+ #
58
+ # Add an extension by local path.
59
+ #
60
+ # @example
61
+ # options = Selenium::WebDriver::Chrome::Options.new
62
+ # options.add_extension('/path/to/extension.crx')
63
+ #
64
+ # @param [String] path The local path to the .crx file
65
+ #
66
+
67
+ def add_extension(path)
68
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
69
+ raise Error::WebDriverError, "file was not an extension #{path.inspect}" unless File.extname(path) == '.crx'
70
+
71
+ @extensions << path
72
+ end
73
+
74
+ #
75
+ # Add an extension by Base64-encoded string.
76
+ #
77
+ # @example
78
+ # options = Selenium::WebDriver::Chrome::Options.new
79
+ # options.add_encoded_extension(encoded_string)
80
+ #
81
+ # @param [String] encoded The Base64-encoded string of the .crx file
82
+ #
83
+
84
+ def add_encoded_extension(encoded)
85
+ @encoded_extensions << encoded
86
+ end
87
+
88
+ #
89
+ # Add a command-line argument to use when starting Chrome.
90
+ #
91
+ # @example Start Chrome maximized
92
+ # options = Selenium::WebDriver::Chrome::Options.new
93
+ # options.add_argument('start-maximized')
94
+ #
95
+ # @param [String] arg The command-line argument to add
96
+ #
97
+
98
+ def add_argument(arg)
99
+ @args << arg
100
+ end
101
+
102
+ #
103
+ # Add a new option not yet handled by bindings.
104
+ #
105
+ # @example Leave Chrome open when chromedriver is killed
106
+ # options = Selenium::WebDriver::Chrome::Options.new
107
+ # options.add_option(:detach, true)
108
+ #
109
+ # @param [String, Symbol] name Name of the option
110
+ # @param [Boolean, String, Integer] value Value of the option
111
+ #
112
+
113
+ def add_option(name, value)
114
+ @options[name] = value
115
+ end
116
+
117
+ #
118
+ # Add a preference that is only applied to the user profile in use.
119
+ #
120
+ # @example Set the default homepage
121
+ # options = Selenium::WebDriver::Chrome::Options.new
122
+ # options.add_preference('homepage', 'http://www.seleniumhq.com/')
123
+ #
124
+ # @param [String] name Key of the preference
125
+ # @param [Boolean, String, Integer] value Value of the preference
126
+ #
127
+
128
+ def add_preference(name, value)
129
+ prefs[name] = value
130
+ end
131
+
132
+ #
133
+ # Run Chrome in headless mode.
134
+ #
135
+ # @example Enable headless mode
136
+ # options = Selenium::WebDriver::Chrome::Options.new
137
+ # options.headless!
138
+ #
139
+
140
+ def headless!
141
+ add_argument '--headless'
142
+ end
143
+
144
+ #
145
+ # Add an emulation device name
146
+ #
147
+ # @example Start Chrome in mobile emulation mode by device name
148
+ # options = Selenium::WebDriver::Chrome::Options.new
149
+ # options.add_emulation(device_name: 'iPhone 6')
150
+ #
151
+ # @example Start Chrome in mobile emulation mode by device metrics
152
+ # options = Selenium::WebDriver::Chrome::Options.new
153
+ # options.add_emulation(device_metrics: {width: 400, height: 800, pixelRatio: 1, touch: true})
154
+ #
155
+ # @param [String] device_name Name of the device or a hash containing width, height, pixelRatio, touch
156
+ # @param [Hash] device_metrics Hash containing width, height, pixelRatio, touch
157
+ # @param [String] user_agent Full user agent
158
+ #
159
+
160
+ def add_emulation(device_name: nil, device_metrics: nil, user_agent: nil)
161
+ @emulation[:deviceName] = device_name if device_name
162
+ @emulation[:deviceMetrics] = device_metrics if device_metrics
163
+ @emulation[:userAgent] = user_agent if user_agent
164
+ end
165
+
166
+ #
167
+ # @api private
168
+ #
169
+
170
+ def as_json(*)
171
+ extensions = @extensions.map do |crx_path|
172
+ File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
173
+ end
174
+ extensions.concat(@encoded_extensions)
175
+ add_argument("--user-data-dir=#{@profile[:directory]}") if @profile
176
+
177
+ opts = @options
178
+ opts[:binary] = @binary if @binary
179
+ opts[:args] = @args.to_a if @args.any?
180
+ opts[:extensions] = extensions if extensions.any?
181
+ opts[:mobileEmulation] = @emulation unless @emulation.empty?
182
+ opts[:prefs] = @prefs unless @prefs.empty?
183
+ opts[:detach] = @detach if !@detach.nil? && @detach != false
184
+
185
+ {KEY => generate_as_json(opts)}
186
+ end
187
+ end # Options
188
+ end # Chrome
189
+ end # WebDriver
190
+ 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
@@ -20,7 +20,6 @@
20
20
  module Selenium
21
21
  module WebDriver
22
22
  module Chrome
23
-
24
23
  #
25
24
  # @private
26
25
  #
@@ -28,16 +27,16 @@ module Selenium
28
27
  class Profile
29
28
  include ProfileHelper
30
29
 
30
+ attr_reader :directory
31
+
31
32
  def initialize(model = nil)
32
- @model = verify_model(model)
33
+ @model = verify_model(model)
33
34
  @extensions = []
34
35
  @encoded_extensions = []
35
36
  end
36
37
 
37
38
  def add_extension(path)
38
- unless File.file?(path)
39
- raise Error::WebDriverError, "could not find extension at #{path.inspect}"
40
- end
39
+ raise Error::WebDriverError, "could not find extension at #{path.inspect}" unless File.file?(path)
41
40
 
42
41
  @extensions << path
43
42
  end
@@ -53,32 +52,34 @@ module Selenium
53
52
  #
54
53
 
55
54
  def []=(key, value)
56
- parts = key.split(".")
57
- parts[0..-2].inject(prefs) { |pr, k| pr[k] ||= {} }[parts.last] = value
55
+ parts = key.split('.')
56
+ parts[0..-2].inject(prefs) { |a, e| a[e] ||= {} }[parts.last] = value
58
57
  end
59
58
 
60
59
  def [](key)
61
- parts = key.split(".")
62
- parts.inject(prefs) { |pr, k| pr.fetch(k) }
60
+ parts = key.split('.')
61
+ parts.inject(prefs) { |a, e| a.fetch(e) }
63
62
  end
64
63
 
65
64
  def layout_on_disk
66
- dir = @model ? create_tmp_copy(@model) : Dir.mktmpdir("webdriver-chrome-profile")
67
- FileReaper << dir
65
+ @directory = @model ? create_tmp_copy(@model) : Dir.mktmpdir('webdriver-chrome-profile')
66
+ FileReaper << @directory
68
67
 
69
- write_prefs_to dir
68
+ write_prefs_to @directory
70
69
 
71
- dir
70
+ @directory
72
71
  end
73
72
 
74
- def as_json(opts = nil)
73
+ def as_json(*)
75
74
  extensions = @extensions.map do |crx_path|
76
- File.open(crx_path, "rb") { |crx_file| Base64.strict_encode64 crx_file.read }
75
+ File.open(crx_path, 'rb') { |crx_file| Base64.strict_encode64 crx_file.read }
77
76
  end
78
77
 
79
78
  extensions.concat(@encoded_extensions)
80
79
 
81
- super.merge('extensions' => extensions)
80
+ opts = {'directory' => directory || layout_on_disk}
81
+ opts['extensions'] = extensions if extensions.any?
82
+ opts
82
83
  end
83
84
 
84
85
  private
@@ -87,7 +88,7 @@ module Selenium
87
88
  prefs_file = prefs_file_for(dir)
88
89
 
89
90
  FileUtils.mkdir_p File.dirname(prefs_file)
90
- File.open(prefs_file, "w") { |file| file << JSON.generate(prefs) }
91
+ File.open(prefs_file, 'w') { |file| file << JSON.generate(prefs) }
91
92
  end
92
93
 
93
94
  def prefs
@@ -96,6 +97,7 @@ module Selenium
96
97
 
97
98
  def read_model_prefs
98
99
  return {} unless @model
100
+
99
101
  JSON.parse File.read(prefs_file_for(@model))
100
102
  end
101
103
 
@@ -103,7 +105,6 @@ module Selenium
103
105
  File.join dir, 'Default', 'Preferences'
104
106
  end
105
107
  end # Profile
106
-
107
108
  end # Chrome
108
109
  end # WebDriver
109
110
  end # Selenium