selenium-webdriver 3.0.8 → 3.1.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.
- data/CHANGES +9 -3
- data/lib/selenium/webdriver/chrome/bridge.rb +0 -1
- data/lib/selenium/webdriver/common.rb +9 -1
- data/lib/selenium/webdriver/common/action_builder.rb +1 -3
- data/lib/selenium/webdriver/common/driver.rb +17 -0
- data/lib/selenium/webdriver/common/interactions/input_device.rb +53 -0
- data/lib/selenium/webdriver/common/interactions/interaction.rb +52 -0
- data/lib/selenium/webdriver/common/interactions/interactions.rb +43 -0
- data/lib/selenium/webdriver/common/interactions/key_actions.rb +112 -0
- data/lib/selenium/webdriver/common/interactions/key_input.rb +64 -0
- data/lib/selenium/webdriver/common/{driver_extensions/has_input_devices.rb → interactions/none_input.rb} +9 -29
- data/lib/selenium/webdriver/common/interactions/pointer_actions.rb +355 -0
- data/lib/selenium/webdriver/common/interactions/pointer_input.rb +134 -0
- data/lib/selenium/webdriver/common/keys.rb +33 -12
- data/lib/selenium/webdriver/common/w3c_action_builder.rb +211 -0
- data/lib/selenium/webdriver/edge/bridge.rb +1 -4
- data/lib/selenium/webdriver/firefox/bridge.rb +1 -2
- data/lib/selenium/webdriver/firefox/extension/webdriver.xpi +0 -0
- data/lib/selenium/webdriver/firefox/w3c_bridge.rb +0 -1
- data/lib/selenium/webdriver/ie/bridge.rb +1 -1
- data/lib/selenium/webdriver/phantomjs/bridge.rb +1 -4
- data/lib/selenium/webdriver/remote/bridge.rb +25 -1
- data/lib/selenium/webdriver/remote/w3c_bridge.rb +16 -29
- data/lib/selenium/webdriver/remote/w3c_commands.rb +1 -0
- data/selenium-webdriver.gemspec +1 -1
- metadata +11 -3
data/CHANGES
CHANGED
@@ -1,16 +1,22 @@
|
|
1
|
-
3.0
|
1
|
+
3.1.0 (2017-02-14)
|
2
|
+
===================
|
3
|
+
|
4
|
+
Firefox:
|
5
|
+
* implement W3C actions endpoint
|
6
|
+
|
7
|
+
3.0.8 (2017-02-08)
|
2
8
|
===================
|
3
9
|
|
4
10
|
Firefox:
|
5
11
|
* Fix signature of element returned from #active_element
|
6
12
|
|
7
|
-
3.0.7 (
|
13
|
+
3.0.7 (2017-02-06)
|
8
14
|
===================
|
9
15
|
|
10
16
|
Firefox:
|
11
17
|
* Fix signature of element arrays returned from #find_elements (issue 3471)
|
12
18
|
|
13
|
-
3.0.6 (
|
19
|
+
3.0.6 (2017-02-05)
|
14
20
|
===================
|
15
21
|
|
16
22
|
Firefox:
|
@@ -42,13 +42,15 @@ require 'selenium/webdriver/common/options'
|
|
42
42
|
require 'selenium/webdriver/common/w3c_options'
|
43
43
|
require 'selenium/webdriver/common/search_context'
|
44
44
|
require 'selenium/webdriver/common/action_builder'
|
45
|
+
require 'selenium/webdriver/common/interactions/key_actions'
|
46
|
+
require 'selenium/webdriver/common/interactions/pointer_actions'
|
47
|
+
require 'selenium/webdriver/common/w3c_action_builder'
|
45
48
|
require 'selenium/webdriver/common/touch_action_builder'
|
46
49
|
require 'selenium/webdriver/common/html5/shared_web_storage'
|
47
50
|
require 'selenium/webdriver/common/html5/local_storage'
|
48
51
|
require 'selenium/webdriver/common/html5/session_storage'
|
49
52
|
require 'selenium/webdriver/common/driver_extensions/takes_screenshot'
|
50
53
|
require 'selenium/webdriver/common/driver_extensions/rotatable'
|
51
|
-
require 'selenium/webdriver/common/driver_extensions/has_input_devices'
|
52
54
|
require 'selenium/webdriver/common/driver_extensions/has_web_storage'
|
53
55
|
require 'selenium/webdriver/common/driver_extensions/has_location'
|
54
56
|
require 'selenium/webdriver/common/driver_extensions/has_session_id'
|
@@ -56,6 +58,12 @@ require 'selenium/webdriver/common/driver_extensions/has_touch_screen'
|
|
56
58
|
require 'selenium/webdriver/common/driver_extensions/has_remote_status'
|
57
59
|
require 'selenium/webdriver/common/driver_extensions/has_network_connection'
|
58
60
|
require 'selenium/webdriver/common/driver_extensions/uploads_files'
|
61
|
+
require 'selenium/webdriver/common/interactions/interactions'
|
62
|
+
require 'selenium/webdriver/common/interactions/input_device'
|
63
|
+
require 'selenium/webdriver/common/interactions/interaction'
|
64
|
+
require 'selenium/webdriver/common/interactions/none_input'
|
65
|
+
require 'selenium/webdriver/common/interactions/key_input'
|
66
|
+
require 'selenium/webdriver/common/interactions/pointer_input'
|
59
67
|
require 'selenium/webdriver/common/keys'
|
60
68
|
require 'selenium/webdriver/common/bridge_helper'
|
61
69
|
require 'selenium/webdriver/common/profile_helper'
|
@@ -23,9 +23,7 @@ module Selenium
|
|
23
23
|
# The ActionBuilder provides the user a way to set up and perform
|
24
24
|
# complex user interactions.
|
25
25
|
#
|
26
|
-
# This class should not be instantiated directly, but is created by
|
27
|
-
# Selenium::WebDriver::DriverExtensions::HasInputDevices#action, which
|
28
|
-
# is available on Driver instances that support the user interaction API.
|
26
|
+
# This class should not be instantiated directly, but is created by Driver#action
|
29
27
|
#
|
30
28
|
# @example
|
31
29
|
#
|
@@ -124,6 +124,23 @@ module Selenium
|
|
124
124
|
bridge.options
|
125
125
|
end
|
126
126
|
|
127
|
+
#
|
128
|
+
# @return [ActionBuilder, W3CActionBuilder]
|
129
|
+
# @see ActionBuilder, W3CActionBuilder
|
130
|
+
#
|
131
|
+
|
132
|
+
def action
|
133
|
+
bridge.action
|
134
|
+
end
|
135
|
+
|
136
|
+
def mouse
|
137
|
+
bridge.mouse
|
138
|
+
end
|
139
|
+
|
140
|
+
def keyboard
|
141
|
+
bridge.keyboard
|
142
|
+
end
|
143
|
+
|
127
144
|
#
|
128
145
|
# Opens the specified URL in the browser.
|
129
146
|
#
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# encoding: utf-8
|
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 'securerandom'
|
21
|
+
|
22
|
+
module Selenium
|
23
|
+
module WebDriver
|
24
|
+
module Interactions
|
25
|
+
class InputDevice
|
26
|
+
attr_reader :name, :actions
|
27
|
+
|
28
|
+
def initialize(name = nil)
|
29
|
+
@name = name || SecureRandom.uuid
|
30
|
+
@actions = []
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_action(action)
|
34
|
+
raise TypeError, "#{action.inspect} is not a valid action" unless action.class < Interaction
|
35
|
+
@actions << action
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear_actions
|
39
|
+
@actions.clear
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_pause(duration = nil)
|
43
|
+
add_action(Pause.new(self, duration))
|
44
|
+
end
|
45
|
+
|
46
|
+
def no_actions? # Determine if only pauses are present
|
47
|
+
actions = @actions.reject { |action| action.type == Interaction::PAUSE }
|
48
|
+
actions.empty?
|
49
|
+
end
|
50
|
+
end # InputDevice
|
51
|
+
end # Interactions
|
52
|
+
end # WebDriver
|
53
|
+
end # Selenium
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
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 Interactions
|
23
|
+
class Interaction
|
24
|
+
PAUSE = :pause
|
25
|
+
|
26
|
+
attr_reader :source
|
27
|
+
|
28
|
+
def initialize(source)
|
29
|
+
raise TypeError, "#{source.type} is not a valid input type" unless Interactions::SOURCE_TYPES.include? source.type
|
30
|
+
@source = source
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Pause < Interaction
|
35
|
+
def initialize(source, duration = nil)
|
36
|
+
super(source)
|
37
|
+
@duration = duration
|
38
|
+
end
|
39
|
+
|
40
|
+
def type
|
41
|
+
PAUSE
|
42
|
+
end
|
43
|
+
|
44
|
+
def encode
|
45
|
+
output = {type: type}
|
46
|
+
output[:duration] = @duration * 1000 if @duration
|
47
|
+
output
|
48
|
+
end
|
49
|
+
end # Interaction
|
50
|
+
end # Interactions
|
51
|
+
end # WebDriver
|
52
|
+
end # Selenium
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: utf-8
|
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 Interactions
|
23
|
+
KEY = :key
|
24
|
+
POINTER = :pointer
|
25
|
+
NONE = :none
|
26
|
+
SOURCE_TYPES = [KEY, POINTER, NONE].freeze
|
27
|
+
|
28
|
+
class << self
|
29
|
+
def key(name)
|
30
|
+
KeyInput.new(name)
|
31
|
+
end
|
32
|
+
|
33
|
+
def pointer(kind, **kwargs)
|
34
|
+
PointerInput.new(kind, **kwargs)
|
35
|
+
end
|
36
|
+
|
37
|
+
def none(name = nil)
|
38
|
+
NoneInput.new(name)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end # Interactions
|
42
|
+
end # WebDriver
|
43
|
+
end # Selenium
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# encoding: utf-8
|
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 KeyActions
|
23
|
+
#
|
24
|
+
# Performs a key press. Does not release the key - subsequent interactions may assume it's kept pressed.
|
25
|
+
# Note that the modifier key is never released implicitly - either #key_up(key) or #release_actions must be
|
26
|
+
# called to release the key.
|
27
|
+
#
|
28
|
+
# @example Press a key
|
29
|
+
#
|
30
|
+
# driver.action.key_down(:control).perform
|
31
|
+
#
|
32
|
+
# @example Press a key on an element
|
33
|
+
#
|
34
|
+
# el = driver.find_element(id: "some_id")
|
35
|
+
# driver.action.key_down(el, :shift).perform
|
36
|
+
#
|
37
|
+
# @param [Selenium::WebDriver::Element] element An optional element
|
38
|
+
# @param [:shift, :alt, :control, :command, :meta, 'a'] key The key to press.
|
39
|
+
# @param [Symbol || String] device optional name of the KeyInput device to press the key on
|
40
|
+
# @return [W3CActionBuilder] A self reference.
|
41
|
+
#
|
42
|
+
|
43
|
+
def key_down(*args, device: nil)
|
44
|
+
key_action(*args, action: :create_key_down, device: device)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Performs a modifier key release.
|
49
|
+
# Releasing a non-depressed modifier key will yield undefined behaviour.
|
50
|
+
#
|
51
|
+
# @example Release a key
|
52
|
+
#
|
53
|
+
# driver.action.key_up(:shift).perform
|
54
|
+
#
|
55
|
+
# @example Release a key from an element
|
56
|
+
#
|
57
|
+
# el = driver.find_element(id: "some_id")
|
58
|
+
# driver.action.key_up(el, :alt).perform
|
59
|
+
#
|
60
|
+
# @param [Selenium::WebDriver::Element] element An optional element
|
61
|
+
# @param [:shift, :alt, :control, :command, :meta, 'a'] key The modifier key to release.
|
62
|
+
# @param [Symbol || String] device optional name of the KeyInput device to release the key on
|
63
|
+
# @return [W3CActionBuilder] A self reference.
|
64
|
+
#
|
65
|
+
|
66
|
+
def key_up(*args, device: nil)
|
67
|
+
key_action(*args, action: :create_key_up, device: device)
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Sends keys to the active element. This differs from calling
|
72
|
+
# Element#send_keys(keys) on the active element in two ways:
|
73
|
+
#
|
74
|
+
# * The modifier keys included in this call are not released.
|
75
|
+
# * There is no attempt to re-focus the element - so send_keys(:tab) for switching elements should work.
|
76
|
+
#
|
77
|
+
# @example Send the text "help" to an element
|
78
|
+
#
|
79
|
+
# el = driver.find_element(id: "some_id")
|
80
|
+
# driver.action.send_keys(el, "help").perform
|
81
|
+
#
|
82
|
+
# @example Send the text "help" to the currently focused element
|
83
|
+
#
|
84
|
+
# driver.action.send_keys("help").perform
|
85
|
+
#
|
86
|
+
# @param [Selenium::WebDriver::Element] element An optional element
|
87
|
+
# @param [String] keys The keys to be sent.
|
88
|
+
# @param [Symbol || String] device optional name of the KeyInput device to send keys with
|
89
|
+
# @return [W3CActionBuilder] A self reference.
|
90
|
+
#
|
91
|
+
|
92
|
+
def send_keys(*args, device: nil)
|
93
|
+
click(args.shift) if args.first.is_a? Element
|
94
|
+
args.map { |x| x.is_a?(String) ? x.chars : x }.flatten.each do |arg|
|
95
|
+
key_down(arg, device: device)
|
96
|
+
key_up(arg, device: device)
|
97
|
+
end
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def key_action(*args, action: nil, device: nil)
|
104
|
+
key_input = get_device(device) || key_inputs.first
|
105
|
+
click(args.shift) if args.first.is_a? Element
|
106
|
+
key_input.send(action, args.last)
|
107
|
+
tick(key_input)
|
108
|
+
self
|
109
|
+
end
|
110
|
+
end # KeyActions
|
111
|
+
end # WebDriver
|
112
|
+
end # Selenium
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: utf-8
|
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 Interactions
|
23
|
+
class KeyInput < InputDevice
|
24
|
+
SUBTYPES = {down: :keyDown, up: :keyUp, pause: :pause}.freeze
|
25
|
+
|
26
|
+
def type
|
27
|
+
Interactions::KEY
|
28
|
+
end
|
29
|
+
|
30
|
+
def encode
|
31
|
+
return nil if no_actions?
|
32
|
+
{type: type, id: name, actions: @actions.map(&:encode)}
|
33
|
+
end
|
34
|
+
|
35
|
+
def create_key_down(key)
|
36
|
+
add_action(TypingInteraction.new(self, :down, key))
|
37
|
+
end
|
38
|
+
|
39
|
+
def create_key_up(key)
|
40
|
+
add_action(TypingInteraction.new(self, :up, key))
|
41
|
+
end
|
42
|
+
|
43
|
+
class TypingInteraction < Interaction
|
44
|
+
attr_reader :type
|
45
|
+
|
46
|
+
def initialize(source, type, key)
|
47
|
+
super(source)
|
48
|
+
@type = assert_type(type)
|
49
|
+
@key = Keys.encode_key(key)
|
50
|
+
end
|
51
|
+
|
52
|
+
def assert_type(type)
|
53
|
+
raise TypeError, "#{type.inspect} is not a valid key subtype" unless KeyInput::SUBTYPES.key? type
|
54
|
+
KeyInput::SUBTYPES[type]
|
55
|
+
end
|
56
|
+
|
57
|
+
def encode
|
58
|
+
{type: @type, value: @key}
|
59
|
+
end
|
60
|
+
end # TypingInteraction
|
61
|
+
end # KeyInput
|
62
|
+
end # Interactions
|
63
|
+
end # WebDriver
|
64
|
+
end # Selenium
|
@@ -19,37 +19,17 @@
|
|
19
19
|
|
20
20
|
module Selenium
|
21
21
|
module WebDriver
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
module DriverExtensions
|
27
|
-
module HasInputDevices
|
28
|
-
#
|
29
|
-
# @return [ActionBuilder]
|
30
|
-
# @api public
|
31
|
-
#
|
32
|
-
|
33
|
-
def action
|
34
|
-
ActionBuilder.new mouse, keyboard
|
35
|
-
end
|
36
|
-
|
37
|
-
#
|
38
|
-
# @api private
|
39
|
-
#
|
40
|
-
|
41
|
-
def mouse
|
42
|
-
Mouse.new @bridge
|
22
|
+
module Interactions
|
23
|
+
class NoneInput < InputDevice
|
24
|
+
def type
|
25
|
+
Interactions::NONE
|
43
26
|
end
|
44
27
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
def keyboard
|
50
|
-
Keyboard.new @bridge
|
28
|
+
def encode
|
29
|
+
return nil if no_actions?
|
30
|
+
{type: type, id: name, actions: @actions.map(&:encode)}
|
51
31
|
end
|
52
|
-
end #
|
53
|
-
end #
|
32
|
+
end # NoneInput
|
33
|
+
end # Interactions
|
54
34
|
end # WebDriver
|
55
35
|
end # Selenium
|