selenium-webdriver 2.53.4 → 3.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +363 -10
  3. data/LICENSE +1 -1
  4. data/README.md +2 -3
  5. data/lib/selenium-webdriver.rb +0 -2
  6. data/lib/selenium/server.rb +69 -70
  7. data/lib/selenium/webdriver.rb +32 -23
  8. data/lib/selenium/webdriver/atoms.rb +18 -0
  9. data/lib/selenium/webdriver/atoms/getAttribute.js +8 -0
  10. data/lib/selenium/webdriver/chrome.rb +8 -6
  11. data/lib/selenium/webdriver/chrome/driver.rb +112 -0
  12. data/lib/selenium/webdriver/chrome/options.rb +168 -0
  13. data/lib/selenium/webdriver/chrome/profile.rb +17 -17
  14. data/lib/selenium/webdriver/chrome/service.rb +22 -89
  15. data/lib/selenium/webdriver/common.rb +13 -6
  16. data/lib/selenium/webdriver/common/action_builder.rb +49 -57
  17. data/lib/selenium/webdriver/common/alert.rb +5 -15
  18. data/lib/selenium/webdriver/common/bridge_helper.rb +10 -17
  19. data/lib/selenium/webdriver/common/driver.rb +53 -68
  20. data/lib/selenium/webdriver/common/driver_extensions/{has_input_devices.rb → has_addons.rb} +13 -23
  21. data/lib/selenium/webdriver/common/driver_extensions/has_location.rb +4 -8
  22. data/lib/selenium/webdriver/common/driver_extensions/has_network_connection.rb +4 -7
  23. data/lib/selenium/webdriver/common/driver_extensions/has_remote_status.rb +0 -4
  24. data/lib/selenium/webdriver/common/driver_extensions/has_session_id.rb +0 -4
  25. data/lib/selenium/webdriver/common/driver_extensions/has_touch_screen.rb +1 -5
  26. data/lib/selenium/webdriver/common/driver_extensions/has_web_storage.rb +0 -5
  27. data/lib/selenium/webdriver/common/driver_extensions/rotatable.rb +4 -9
  28. data/lib/selenium/webdriver/common/driver_extensions/takes_screenshot.rb +7 -7
  29. data/lib/selenium/webdriver/common/driver_extensions/uploads_files.rb +2 -7
  30. data/lib/selenium/webdriver/common/element.rb +57 -39
  31. data/lib/selenium/webdriver/common/error.rb +204 -106
  32. data/lib/selenium/webdriver/common/file_reaper.rb +3 -11
  33. data/lib/selenium/webdriver/common/html5/local_storage.rb +6 -10
  34. data/lib/selenium/webdriver/common/html5/session_storage.rb +6 -10
  35. data/lib/selenium/webdriver/common/html5/shared_web_storage.rb +7 -18
  36. data/lib/selenium/webdriver/{safari/options.rb → common/interactions/input_device.rb} +20 -31
  37. data/lib/selenium/webdriver/common/interactions/interaction.rb +50 -0
  38. data/lib/selenium/webdriver/{safari/browser.rb → common/interactions/interactions.rb} +16 -15
  39. data/lib/selenium/webdriver/common/interactions/key_actions.rb +143 -0
  40. data/lib/selenium/webdriver/common/interactions/key_input.rb +62 -0
  41. data/lib/selenium/webdriver/{android.rb → common/interactions/none_input.rb} +11 -6
  42. data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +353 -0
  43. data/lib/selenium/webdriver/common/interactions/pointer_input.rb +132 -0
  44. data/lib/selenium/webdriver/common/keyboard.rb +7 -14
  45. data/lib/selenium/webdriver/common/keys.rb +99 -82
  46. data/lib/selenium/webdriver/common/log_entry.rb +3 -6
  47. data/lib/selenium/webdriver/common/logger.rb +140 -0
  48. data/lib/selenium/webdriver/common/logs.rb +2 -6
  49. data/lib/selenium/webdriver/common/mouse.rb +9 -14
  50. data/lib/selenium/webdriver/common/navigation.rb +2 -6
  51. data/lib/selenium/webdriver/common/options.rb +20 -23
  52. data/lib/selenium/webdriver/common/platform.rb +70 -97
  53. data/lib/selenium/webdriver/common/port_prober.rb +3 -4
  54. data/lib/selenium/webdriver/common/profile_helper.rb +6 -11
  55. data/lib/selenium/webdriver/common/proxy.rb +58 -72
  56. data/lib/selenium/webdriver/common/search_context.rb +22 -29
  57. data/lib/selenium/webdriver/common/service.rb +161 -0
  58. data/lib/selenium/webdriver/common/socket_lock.rb +6 -14
  59. data/lib/selenium/webdriver/common/socket_poller.rb +5 -12
  60. data/lib/selenium/webdriver/common/target_locator.rb +11 -15
  61. data/lib/selenium/webdriver/common/timeouts.rb +4 -8
  62. data/lib/selenium/webdriver/common/touch_action_builder.rb +2 -6
  63. data/lib/selenium/webdriver/common/touch_screen.rb +19 -23
  64. data/lib/selenium/webdriver/common/w3c_action_builder.rb +209 -0
  65. data/lib/selenium/webdriver/{phantomjs.rb → common/w3c_options.rb} +16 -14
  66. data/lib/selenium/webdriver/common/wait.rb +6 -13
  67. data/lib/selenium/webdriver/common/window.rb +48 -17
  68. data/lib/selenium/webdriver/common/zipper.rb +6 -10
  69. data/lib/selenium/webdriver/edge.rb +5 -12
  70. data/lib/selenium/webdriver/edge/bridge.rb +32 -63
  71. data/lib/selenium/webdriver/edge/driver.rb +73 -0
  72. data/lib/selenium/webdriver/edge/service.rb +18 -87
  73. data/lib/selenium/webdriver/firefox.rb +20 -11
  74. data/lib/selenium/webdriver/firefox/binary.rb +40 -56
  75. data/lib/selenium/webdriver/firefox/driver.rb +48 -0
  76. data/lib/selenium/webdriver/firefox/extension.rb +18 -8
  77. data/lib/selenium/webdriver/firefox/extension/prefs.json +3 -11
  78. data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
  79. data/lib/selenium/webdriver/firefox/launcher.rb +13 -22
  80. data/lib/selenium/webdriver/firefox/legacy/driver.rb +79 -0
  81. data/lib/selenium/webdriver/{iphone.rb → firefox/marionette/bridge.rb} +25 -6
  82. data/lib/selenium/webdriver/firefox/marionette/driver.rb +96 -0
  83. data/lib/selenium/webdriver/firefox/options.rb +149 -0
  84. data/lib/selenium/webdriver/firefox/profile.rb +46 -46
  85. data/lib/selenium/webdriver/firefox/profiles_ini.rb +8 -18
  86. data/lib/selenium/webdriver/firefox/service.rb +23 -83
  87. data/lib/selenium/webdriver/firefox/util.rb +0 -4
  88. data/lib/selenium/webdriver/ie.rb +4 -8
  89. data/lib/selenium/webdriver/ie/driver.rb +90 -0
  90. data/lib/selenium/webdriver/ie/options.rb +136 -0
  91. data/lib/selenium/webdriver/ie/service.rb +58 -0
  92. data/lib/selenium/webdriver/remote.rb +8 -16
  93. data/lib/selenium/webdriver/remote/bridge.rb +96 -565
  94. data/lib/selenium/webdriver/remote/capabilities.rb +76 -94
  95. data/lib/selenium/webdriver/remote/driver.rb +49 -0
  96. data/lib/selenium/webdriver/remote/http/common.rb +22 -20
  97. data/lib/selenium/webdriver/remote/http/curb.rb +9 -12
  98. data/lib/selenium/webdriver/remote/http/default.rb +54 -41
  99. data/lib/selenium/webdriver/remote/http/persistent.rb +9 -8
  100. data/lib/selenium/webdriver/remote/oss/bridge.rb +586 -0
  101. data/lib/selenium/webdriver/remote/oss/commands.rb +221 -0
  102. data/lib/selenium/webdriver/remote/response.rb +39 -27
  103. data/lib/selenium/webdriver/remote/server_error.rb +1 -5
  104. data/lib/selenium/webdriver/remote/w3c/bridge.rb +573 -0
  105. data/lib/selenium/webdriver/remote/w3c/capabilities.rb +290 -0
  106. data/lib/selenium/webdriver/remote/w3c/commands.rb +148 -0
  107. data/lib/selenium/webdriver/safari.rb +20 -29
  108. data/lib/selenium/webdriver/{firefox/w3c_bridge.rb → safari/driver.rb} +21 -30
  109. data/lib/selenium/webdriver/safari/service.rb +57 -0
  110. data/lib/selenium/webdriver/support.rb +1 -2
  111. data/lib/selenium/webdriver/support/abstract_event_listener.rb +17 -4
  112. data/lib/selenium/webdriver/support/block_event_listener.rb +1 -5
  113. data/lib/selenium/webdriver/support/color.rb +57 -42
  114. data/lib/selenium/webdriver/support/escaper.rb +41 -0
  115. data/lib/selenium/webdriver/support/event_firing_bridge.rb +36 -40
  116. data/lib/selenium/webdriver/support/select.rb +33 -86
  117. data/selenium-webdriver.gemspec +22 -25
  118. metadata +254 -261
  119. data/lib/selenium-client.rb +0 -21
  120. data/lib/selenium/client.rb +0 -57
  121. data/lib/selenium/client/base.rb +0 -151
  122. data/lib/selenium/client/driver.rb +0 -29
  123. data/lib/selenium/client/errors.rb +0 -28
  124. data/lib/selenium/client/extensions.rb +0 -132
  125. data/lib/selenium/client/idiomatic.rb +0 -507
  126. data/lib/selenium/client/javascript_expression_builder.rb +0 -135
  127. data/lib/selenium/client/javascript_frameworks/jquery.rb +0 -32
  128. data/lib/selenium/client/javascript_frameworks/prototype.rb +0 -32
  129. data/lib/selenium/client/legacy_driver.rb +0 -1722
  130. data/lib/selenium/client/protocol.rb +0 -123
  131. data/lib/selenium/client/selenium_helper.rb +0 -49
  132. data/lib/selenium/rake/server_task.rb +0 -176
  133. data/lib/selenium/webdriver/android/bridge.rb +0 -68
  134. data/lib/selenium/webdriver/chrome/bridge.rb +0 -139
  135. data/lib/selenium/webdriver/common/core_ext/base64.rb +0 -28
  136. data/lib/selenium/webdriver/common/core_ext/dir.rb +0 -61
  137. data/lib/selenium/webdriver/common/html5/location.rb +0 -19
  138. data/lib/selenium/webdriver/common/w3c_error.rb +0 -194
  139. data/lib/selenium/webdriver/edge/legacy_support.rb +0 -117
  140. data/lib/selenium/webdriver/firefox/bridge.rb +0 -89
  141. data/lib/selenium/webdriver/ie/bridge.rb +0 -88
  142. data/lib/selenium/webdriver/ie/server.rb +0 -133
  143. data/lib/selenium/webdriver/iphone/bridge.rb +0 -64
  144. data/lib/selenium/webdriver/phantomjs/bridge.rb +0 -78
  145. data/lib/selenium/webdriver/phantomjs/service.rb +0 -130
  146. data/lib/selenium/webdriver/remote/commands.rb +0 -211
  147. data/lib/selenium/webdriver/remote/w3c_bridge.rb +0 -668
  148. data/lib/selenium/webdriver/remote/w3c_capabilities.rb +0 -236
  149. data/lib/selenium/webdriver/remote/w3c_commands.rb +0 -132
  150. data/lib/selenium/webdriver/safari/bridge.rb +0 -135
  151. data/lib/selenium/webdriver/safari/resources/client.js +0 -7255
  152. data/lib/selenium/webdriver/safari/server.rb +0 -187
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -20,7 +18,6 @@
20
18
  module Selenium
21
19
  module WebDriver
22
20
  module HTML5
23
-
24
21
  class LocalStorage
25
22
  include SharedWebStorage
26
23
 
@@ -32,29 +29,28 @@ module Selenium
32
29
  end
33
30
 
34
31
  def [](key)
35
- @bridge.getLocalStorageItem key
32
+ @bridge.local_storage_item key
36
33
  end
37
34
 
38
35
  def []=(key, value)
39
- @bridge.setLocalStorageItem key, value
36
+ @bridge.local_storage_item key, value
40
37
  end
41
38
 
42
39
  def delete(key)
43
- @bridge.removeLocalStorageItem key
40
+ @bridge.remove_local_storage_item key
44
41
  end
45
42
 
46
43
  def clear
47
- @bridge.clearLocalStorage
44
+ @bridge.clear_local_storage
48
45
  end
49
46
 
50
47
  def size
51
- @bridge.getLocalStorageSize
48
+ @bridge.local_storage_size
52
49
  end
53
50
 
54
51
  def keys
55
- @bridge.getLocalStorageKeys.reverse
52
+ @bridge.local_storage_keys.reverse
56
53
  end
57
-
58
54
  end # LocalStorage
59
55
  end # HTML5
60
56
  end # WebDriver
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -20,33 +18,32 @@
20
18
  module Selenium
21
19
  module WebDriver
22
20
  module HTML5
23
-
24
21
  class SessionStorage
25
22
  include Enumerable
26
23
  include SharedWebStorage
27
24
 
28
25
  def [](key)
29
- @bridge.getSessionStorageItem key
26
+ @bridge.session_storage_item key
30
27
  end
31
28
 
32
29
  def []=(key, value)
33
- @bridge.setSessionStorageItem key, value
30
+ @bridge.session_storage_item key, value
34
31
  end
35
32
 
36
33
  def delete(key)
37
- @bridge.removeSessionStorageItem key
34
+ @bridge.remove_session_storage_item key
38
35
  end
39
36
 
40
37
  def clear
41
- @bridge.clearSessionStorage
38
+ @bridge.clear_session_storage
42
39
  end
43
40
 
44
41
  def size
45
- @bridge.getSessionStorageSize
42
+ @bridge.session_storage_size
46
43
  end
47
44
 
48
45
  def keys
49
- @bridge.getSessionStorageKeys.reverse
46
+ @bridge.session_storage_keys.reverse
50
47
  end
51
48
 
52
49
  #
@@ -56,7 +53,6 @@ module Selenium
56
53
  def initialize(bridge)
57
54
  @bridge = bridge
58
55
  end
59
-
60
56
  end # SessionStorage
61
57
  end # HTML5
62
58
  end # WebDriver
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -20,7 +18,6 @@
20
18
  module Selenium
21
19
  module WebDriver
22
20
  module HTML5
23
-
24
21
  module SharedWebStorage
25
22
  include Enumerable
26
23
 
@@ -30,31 +27,23 @@ module Selenium
30
27
  alias_method :member?, :key?
31
28
  alias_method :has_key?, :key?
32
29
 
33
- def fetch(key, &blk)
34
- if self.key? key
35
- return self[key]
36
- end
37
-
38
- if block_given?
39
- yield key
40
- else
41
- # should be KeyError, but it's 1.9-specific
42
- raise IndexError, "missing key #{key.inspect}"
43
- end
30
+ def fetch(key)
31
+ return self[key] if key? key
32
+ return yield(key) if block_given?
33
+ raise KeyError, "missing key #{key.inspect}"
44
34
  end
45
35
 
46
36
  def empty?
47
- size == 0
37
+ to_a.empty?
48
38
  end
49
39
 
50
- def each(&blk)
40
+ def each
51
41
  return enum_for(:each) unless block_given?
52
42
 
53
- keys.each do |k|
43
+ keys.each do |k| # rubocop:disable Performance/HashEachMethods
54
44
  yield k, self[k]
55
45
  end
56
46
  end
57
-
58
47
  end # SharedWebStorage
59
48
  end # HTML5
60
49
  end # WebDriver
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -17,46 +15,37 @@
17
15
  # specific language governing permissions and limitations
18
16
  # under the License.
19
17
 
18
+ require 'securerandom'
19
+
20
20
  module Selenium
21
21
  module WebDriver
22
- module Safari
23
- class Options
24
- DEFAULT_PORT = 56485
25
-
26
- attr_accessor :port, :data_dir, :skip_extension_installation
22
+ module Interactions
23
+ class InputDevice
24
+ attr_reader :name, :actions
27
25
 
28
- def initialize(opts = {})
29
- extract_options(opts)
26
+ def initialize(name = nil)
27
+ @name = name || SecureRandom.uuid
28
+ @actions = []
30
29
  end
31
30
 
32
- def clean_session?
33
- !!@clean_session
31
+ def add_action(action)
32
+ raise TypeError, "#{action.inspect} is not a valid action" unless action.class < Interaction
33
+ @actions << action
34
34
  end
35
35
 
36
- def to_capabilities
37
- caps = Remote::Capabilities.safari
38
- caps.merge!('safari.options' => as_json)
39
-
40
- caps
36
+ def clear_actions
37
+ @actions.clear
41
38
  end
42
39
 
43
- def as_json
44
- {
45
- 'port' => port,
46
- 'dataDir' => data_dir,
47
- 'cleanSession' => clean_session?,
48
- }
40
+ def create_pause(duration = nil)
41
+ add_action(Pause.new(self, duration))
49
42
  end
50
43
 
51
- private
52
-
53
- def extract_options(opts)
54
- @port = Integer(opts[:port] || DEFAULT_PORT)
55
- @data_dir = opts[:custom_data_dir] || opts[:data_dir]
56
- @clean_session = opts[:clean_session]
44
+ def no_actions? # Determine if only pauses are present
45
+ actions = @actions.reject { |action| action.type == Interaction::PAUSE }
46
+ actions.empty?
57
47
  end
58
-
59
- end # Options
60
- end # Safari
48
+ end # InputDevice
49
+ end # Interactions
61
50
  end # WebDriver
62
51
  end # Selenium
@@ -0,0 +1,50 @@
1
+ # Licensed to the Software Freedom Conservancy (SFC) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The SFC licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ module Selenium
19
+ module WebDriver
20
+ module Interactions
21
+ class Interaction
22
+ PAUSE = :pause
23
+
24
+ attr_reader :source
25
+
26
+ def initialize(source)
27
+ raise TypeError, "#{source.type} is not a valid input type" unless Interactions::SOURCE_TYPES.include? source.type
28
+ @source = source
29
+ end
30
+ end
31
+
32
+ class Pause < Interaction
33
+ def initialize(source, duration = nil)
34
+ super(source)
35
+ @duration = duration
36
+ end
37
+
38
+ def type
39
+ PAUSE
40
+ end
41
+
42
+ def encode
43
+ output = {type: type}
44
+ output[:duration] = (@duration * 1000).to_i if @duration
45
+ output
46
+ end
47
+ end # Interaction
48
+ end # Interactions
49
+ end # WebDriver
50
+ end # Selenium
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
- #
3
1
  # Licensed to the Software Freedom Conservancy (SFC) under one
4
2
  # or more contributor license agreements. See the NOTICE file
5
3
  # distributed with this work for additional information
@@ -15,26 +13,29 @@
15
13
  # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
14
  # KIND, either express or implied. See the License for the
17
15
  # specific language governing permissions and limitations
18
- # under the License.
16
+ # under the License
19
17
 
20
18
  module Selenium
21
19
  module WebDriver
22
- module Safari
23
-
24
- class Browser
25
- def start(*args)
26
- Platform.exit_hook { stop } # make sure we don't leave the browser running
20
+ module Interactions
21
+ KEY = :key
22
+ POINTER = :pointer
23
+ NONE = :none
24
+ SOURCE_TYPES = [KEY, POINTER, NONE].freeze
27
25
 
28
- @process = ChildProcess.new(Safari.path, *args)
29
- @process.io.inherit! if $DEBUG
30
- @process.start
26
+ class << self
27
+ def key(name)
28
+ KeyInput.new(name)
31
29
  end
32
30
 
33
- def stop
34
- @process.stop if @process
31
+ def pointer(kind, **kwargs)
32
+ PointerInput.new(kind, **kwargs)
35
33
  end
36
34
 
37
- end # Browser
38
- end # Safari
35
+ def none(name = nil)
36
+ NoneInput.new(name)
37
+ end
38
+ end
39
+ end # Interactions
39
40
  end # WebDriver
40
41
  end # Selenium
@@ -0,0 +1,143 @@
1
+ # Licensed to the Software Freedom Conservancy (SFC) under one
2
+ # or more contributor license agreements. See the NOTICE file
3
+ # distributed with this work for additional information
4
+ # regarding copyright ownership. The SFC licenses this file
5
+ # to you under the Apache License, Version 2.0 (the
6
+ # "License"); you may not use this file except in compliance
7
+ # with the License. You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing,
12
+ # software distributed under the License is distributed on an
13
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
+ # KIND, either express or implied. See the License for the
15
+ # specific language governing permissions and limitations
16
+ # under the License.
17
+
18
+ module Selenium
19
+ module WebDriver
20
+ module KeyActions
21
+ #
22
+ # Performs a key press. Does not release the key - subsequent interactions may assume it's kept pressed.
23
+ # Note that the key is never released implicitly - either W3CActionBuilder#key_up(key) or W3CActionBuilder#release_actions
24
+ # must be called to release the key.
25
+ #
26
+ # @example Press a key
27
+ #
28
+ # driver.action.key_down(:control).perform
29
+ #
30
+ # @example Press a key on an element
31
+ #
32
+ # el = driver.find_element(id: "some_id")
33
+ # driver.action.key_down(el, :shift).perform
34
+ #
35
+ # @overload key_down(key, device: nil)
36
+ # @param [Symbol, String] key The key to press
37
+ # @param [Symbol, String] device Optional name of the KeyInput device to press the key on
38
+ # @overload key_down(element, key, device: nil)
39
+ # @param [Element] element An optional element to move to first
40
+ # @param [Symbol, String] key The key to press
41
+ # @param [Symbol, String] device Optional name of the KeyInput device to press the key on
42
+ # @return [W3CActionBuilder] A self reference
43
+ #
44
+
45
+ def key_down(*args, device: nil)
46
+ key_action(*args, action: :create_key_down, device: device)
47
+ end
48
+
49
+ #
50
+ # Performs a key release.
51
+ # Releasing a non-depressed key will yield undefined behaviour.
52
+ #
53
+ # @example Release a key
54
+ #
55
+ # driver.action.key_up(:shift).perform
56
+ #
57
+ # @example Release a key from an element
58
+ #
59
+ # el = driver.find_element(id: "some_id")
60
+ # driver.action.key_up(el, :alt).perform
61
+ #
62
+ # @overload key_up(key, device: nil)
63
+ # @param [Symbol, String] key The key to press
64
+ # @param [Symbol, String] device Optional name of the KeyInput device to press the key on
65
+ # @overload key_up(element, key, device: nil)
66
+ # @param [Element] element An optional element to move to first
67
+ # @param [Symbol, String] key The key to release
68
+ # @param [Symbol, String] device Optional name of the KeyInput device to release the key on
69
+ # @return [W3CActionBuilder] A self reference
70
+ #
71
+
72
+ def key_up(*args, device: nil)
73
+ key_action(*args, action: :create_key_up, device: device)
74
+ end
75
+
76
+ #
77
+ # Sends keys to the active element. This differs from calling
78
+ # Element#send_keys(keys) on the active element in two ways:
79
+ #
80
+ # * The modifier keys included in this call are not released.
81
+ # * There is no attempt to re-focus the element - so send_keys(:tab) for switching elements should work.
82
+ #
83
+ # @example Send the text "help" to an element
84
+ #
85
+ # el = driver.find_element(id: "some_id")
86
+ # driver.action.send_keys(el, "help").perform
87
+ #
88
+ # @example Send the text "help" to the currently focused element
89
+ #
90
+ # driver.action.send_keys("help").perform
91
+ #
92
+ # @overload send_keys(keys, device: nil)
93
+ # @param [Array, Symbol, String] keys The key(s) to press and release
94
+ # @param [Symbol, String] device Optional name of the KeyInput device to press and release the keys on
95
+ # @overload send_keys(element, keys, device: nil)
96
+ # @param [Element] element An optional element to move to first
97
+ # @param [Array, Symbol, String] keys The key(s) to press and release
98
+ # @param [Symbol, String] device Optional name of the KeyInput device to press and release the keys on
99
+ # @return [W3CActionBuilder] A self reference
100
+ #
101
+
102
+ def send_keys(*args, device: nil)
103
+ click(args.shift) if args.first.is_a? Element
104
+ args.map { |x| x.is_a?(String) ? x.chars : x }.flatten.each do |arg|
105
+ key_down(arg, device: device)
106
+ key_up(arg, device: device)
107
+ end
108
+ self
109
+ end
110
+
111
+ private
112
+
113
+ #
114
+ # @api private
115
+ #
116
+ # @overload key_down(key, action: nil, device: nil)
117
+ # @param [Symbol, String] key The key to press
118
+ # @param [Symbol] action The name of the key action to perform
119
+ # @param [Symbol, String] device Optional name of the KeyInput device to press the key on
120
+ # @overload key_down(element, key, action: nil, device: nil)
121
+ # @param [Element] element An optional element to move to first
122
+ # @param [Symbol, String] key The key to press
123
+ # @param [Symbol] action The name of the key action to perform
124
+ # @param [Symbol, String] device Optional name of the KeyInput device to press the key on
125
+ #
126
+ # @param [Array] args
127
+ # @option args [Element] element An optional element to move to first
128
+ # @option args [Symbol, String] key The key to perform the action with
129
+ # @param [Symbol] action The name of the key action to perform
130
+ # @param [Symbol, String] device optional name of the KeyInput device to press the key on
131
+ # @return [W3CActionBuilder] A self reference
132
+ #
133
+
134
+ def key_action(*args, action: nil, device: nil)
135
+ key_input = get_device(device) || key_inputs.first
136
+ click(args.shift) if args.first.is_a? Element
137
+ key_input.send(action, args.last)
138
+ tick(key_input)
139
+ self
140
+ end
141
+ end # KeyActions
142
+ end # WebDriver
143
+ end # Selenium