testa_appium_driver 0.1.21 → 0.1.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +23 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/bin/console +17 -0
- data/bin/setup +8 -0
- data/lib/testa_appium_driver/android/class_selectors.rb +438 -0
- data/lib/testa_appium_driver/android/driver.rb +71 -0
- data/lib/testa_appium_driver/android/locator/attributes.rb +115 -0
- data/lib/testa_appium_driver/android/locator.rb +142 -0
- data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +62 -0
- data/lib/testa_appium_driver/android/selenium_element.rb +12 -0
- data/lib/testa_appium_driver/common/bounds.rb +150 -0
- data/lib/testa_appium_driver/common/constants.rb +38 -0
- data/lib/testa_appium_driver/common/exceptions/strategy_mix_exception.rb +12 -0
- data/lib/testa_appium_driver/common/helpers.rb +272 -0
- data/lib/testa_appium_driver/common/locator/scroll_actions.rb +390 -0
- data/lib/testa_appium_driver/common/locator.rb +640 -0
- data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +4 -0
- data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +371 -0
- data/lib/testa_appium_driver/common/scroll_actions.rb +271 -0
- data/lib/testa_appium_driver/common/selenium_element.rb +19 -0
- data/lib/testa_appium_driver/driver.rb +338 -0
- data/lib/testa_appium_driver/ios/driver.rb +49 -0
- data/lib/testa_appium_driver/ios/locator/attributes.rb +89 -0
- data/lib/testa_appium_driver/ios/locator.rb +73 -0
- data/lib/testa_appium_driver/ios/selenium_element.rb +8 -0
- data/lib/testa_appium_driver/ios/type_selectors.rb +201 -0
- data/lib/testa_appium_driver.rb +4 -0
- data/testa_appium_driver.gemspec +6 -2
- metadata +39 -11
- data/appium-driver.iml +0 -79
@@ -0,0 +1,115 @@
|
|
1
|
+
module TestaAppiumDriver
|
2
|
+
module Attributes
|
3
|
+
|
4
|
+
#noinspection RubyNilAnalysis
|
5
|
+
def testa_attribute(name, *args)
|
6
|
+
if self.instance_of?(::Selenium::WebDriver::Element) || self.instance_of?(::Appium::Core::Element)
|
7
|
+
@driver = get_driver # does not get correct driver
|
8
|
+
elements = self
|
9
|
+
else
|
10
|
+
elements = execute(*args)
|
11
|
+
raise "Element not found" if elements.nil?
|
12
|
+
end
|
13
|
+
|
14
|
+
if elements.kind_of?(::Selenium::WebDriver::Element) || elements.kind_of?(::Appium::Core::Element)
|
15
|
+
r = elements.send(:attribute, name.to_s)
|
16
|
+
r = TestaAppiumDriver::Bounds.from_android(r, @driver) if name.to_s == "bounds"
|
17
|
+
else
|
18
|
+
r = elements.map { |e| e.send(:attribute, name.to_s) }
|
19
|
+
r.map! { |b| TestaAppiumDriver::Bounds.from_android(b, @driver) } if name.to_s == "bounds"
|
20
|
+
end
|
21
|
+
r
|
22
|
+
end
|
23
|
+
|
24
|
+
def text(*args)
|
25
|
+
testa_attribute("text", *args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def package(*args)
|
29
|
+
testa_attribute("package", *args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def class_name(*args)
|
33
|
+
testa_attribute("className", *args)
|
34
|
+
end
|
35
|
+
|
36
|
+
def checkable?(*args)
|
37
|
+
testa_attribute("checkable", *args).to_s == "true"
|
38
|
+
end
|
39
|
+
|
40
|
+
def checked?(*args)
|
41
|
+
testa_attribute("checked", *args).to_s == "true"
|
42
|
+
end
|
43
|
+
|
44
|
+
def clickable?(*args)
|
45
|
+
testa_attribute("clickable", *args).to_s == "true"
|
46
|
+
end
|
47
|
+
|
48
|
+
def desc(*args)
|
49
|
+
testa_attribute("contentDescription", *args)
|
50
|
+
end
|
51
|
+
|
52
|
+
def enabled?(*args)
|
53
|
+
testa_attribute("enabled", *args).to_s == "true"
|
54
|
+
end
|
55
|
+
|
56
|
+
def focusable?(*args)
|
57
|
+
testa_attribute("focusable", *args).to_s == "true"
|
58
|
+
end
|
59
|
+
|
60
|
+
def focused?(*args)
|
61
|
+
testa_attribute("focused", *args).to_s == "true"
|
62
|
+
end
|
63
|
+
|
64
|
+
def long_clickable?(*args)
|
65
|
+
testa_attribute("longClickable", *args).to_s == "true"
|
66
|
+
end
|
67
|
+
|
68
|
+
def password?(*args)
|
69
|
+
testa_attribute("password", *args).to_s == "true"
|
70
|
+
end
|
71
|
+
|
72
|
+
def id(*args)
|
73
|
+
testa_attribute("resourceId", *args)
|
74
|
+
end
|
75
|
+
|
76
|
+
def scrollable?(*args)
|
77
|
+
testa_attribute("scrollable", *args).to_s == "true"
|
78
|
+
end
|
79
|
+
|
80
|
+
def selected?(*args)
|
81
|
+
testa_attribute("selected", *args).to_s == "true"
|
82
|
+
end
|
83
|
+
|
84
|
+
def displayed?(*args)
|
85
|
+
testa_attribute("displayed", *args).to_s == "true"
|
86
|
+
end
|
87
|
+
|
88
|
+
def selection_start(*args)
|
89
|
+
testa_attribute("selection-start", *args)
|
90
|
+
end
|
91
|
+
|
92
|
+
def selection_end(*args)
|
93
|
+
testa_attribute("selection-end", *args)
|
94
|
+
end
|
95
|
+
|
96
|
+
def bounds(*args)
|
97
|
+
testa_attribute("bounds", *args)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Locator
|
102
|
+
|
103
|
+
# element index in parent element, starts from 0
|
104
|
+
#noinspection RubyNilAnalysis,RubyYardReturnMatch
|
105
|
+
# @return [Integer, nil] index of element
|
106
|
+
def index(*args)
|
107
|
+
raise "Index not supported for uiautomator strategy" if @strategy == FIND_STRATEGY_UIAUTOMATOR
|
108
|
+
this = execute(*args)
|
109
|
+
children = self.dup.parent.children.execute
|
110
|
+
index = children.index(this)
|
111
|
+
raise "Index not found" if index.nil?
|
112
|
+
index.to_i
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require_relative 'locator/attributes'
|
2
|
+
|
3
|
+
module TestaAppiumDriver
|
4
|
+
#noinspection RubyTooManyInstanceVariablesInspection
|
5
|
+
class Locator
|
6
|
+
attr_accessor :closing_parenthesis
|
7
|
+
include ClassSelectors
|
8
|
+
include Attributes
|
9
|
+
|
10
|
+
def init(params, selectors, single)
|
11
|
+
@closing_parenthesis = 0
|
12
|
+
|
13
|
+
|
14
|
+
@ui_selector = hash_to_uiautomator(selectors, single)
|
15
|
+
|
16
|
+
if is_scrollable_selector?(selectors, single)
|
17
|
+
if selectors[:class] == "android.widget.HorizontalScrollView"
|
18
|
+
@scroll_orientation = :horizontal
|
19
|
+
else
|
20
|
+
@scroll_orientation = :vertical
|
21
|
+
end
|
22
|
+
|
23
|
+
if !params[:top].nil? || !params[:bottom].nil? || !params[:right].nil? || !params[:left].nil?
|
24
|
+
@scroll_deadzone = {}
|
25
|
+
@scroll_deadzone[:top] = params[:top].to_f unless params[:top].nil?
|
26
|
+
@scroll_deadzone[:bottom] = params[:bottom].to_f unless params[:bottom].nil?
|
27
|
+
@scroll_deadzone[:right] = params[:right].to_f unless params[:right].nil?
|
28
|
+
@scroll_deadzone[:left] = params[:left].to_f unless params[:left].nil?
|
29
|
+
end
|
30
|
+
|
31
|
+
params[:scrollable_locator] = self.dup
|
32
|
+
end
|
33
|
+
|
34
|
+
@scrollable_locator = params[:scrollable_locator] if params[:scrollable_locator]
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# resolve selector which will be used for finding element
|
39
|
+
def strategies_and_selectors
|
40
|
+
ss = []
|
41
|
+
if @can_use_id_strategy
|
42
|
+
ss.push({"#{FIND_STRATEGY_ID}": @can_use_id_strategy})
|
43
|
+
end
|
44
|
+
if @strategy.nil? || @strategy == FIND_STRATEGY_UIAUTOMATOR
|
45
|
+
ss.push({"#{FIND_STRATEGY_UIAUTOMATOR}": ui_selector})
|
46
|
+
end
|
47
|
+
|
48
|
+
if @strategy.nil? || @strategy == FIND_STRATEGY_XPATH
|
49
|
+
ss.push({"#{FIND_STRATEGY_XPATH}": @xpath_selector})
|
50
|
+
end
|
51
|
+
|
52
|
+
if @strategy == FIND_STRATEGY_IMAGE
|
53
|
+
ss.push({"#{FIND_STRATEGY_IMAGE}": @image_selector})
|
54
|
+
end
|
55
|
+
ss
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
# @param [Boolean] include_semicolon should the semicolon be included at the end
|
60
|
+
# @return ui_selector for uiautomator find strategy
|
61
|
+
def ui_selector(include_semicolon = true)
|
62
|
+
@ui_selector + ")" * @closing_parenthesis + (include_semicolon ? ";" : "");
|
63
|
+
end
|
64
|
+
|
65
|
+
def ui_selector=(value)
|
66
|
+
@ui_selector = value
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
# @return [TestaAppiumDriver::Locator]
|
73
|
+
def from_parent(selectors = {})
|
74
|
+
raise "Cannot add from_parent selector to array" unless @single
|
75
|
+
raise StrategyMixException.new(@strategy, @strategy_reason, FIND_STRATEGY_UIAUTOMATOR, "from_parent") if @strategy != FIND_STRATEGY_UIAUTOMATOR
|
76
|
+
|
77
|
+
locator = self.dup
|
78
|
+
locator.strategy = FIND_STRATEGY_UIAUTOMATOR
|
79
|
+
locator.strategy_reason = "from_parent"
|
80
|
+
locator.closing_parenthesis += 1
|
81
|
+
locator.ui_selector = "#{locator.ui_selector}.fromParent(#{hash_to_uiautomator(selectors)}"
|
82
|
+
locator
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
# @return [Locator] new child locator element
|
87
|
+
def add_child_selector(params)
|
88
|
+
params, selectors = extract_selectors_from_params(params)
|
89
|
+
single = params[:single]
|
90
|
+
raise "Cannot add child selector to Array" if single && !@single
|
91
|
+
|
92
|
+
locator = self.dup
|
93
|
+
locator.can_use_id_strategy = false
|
94
|
+
if (@strategy.nil? && !single) || @strategy == FIND_STRATEGY_XPATH
|
95
|
+
locator.strategy = FIND_STRATEGY_XPATH
|
96
|
+
locator.strategy_reason = "multiple child selector"
|
97
|
+
add_xpath_child_selectors(locator, selectors, single)
|
98
|
+
elsif @strategy == FIND_STRATEGY_UIAUTOMATOR
|
99
|
+
locator = add_uiautomator_child_selector(locator, selectors, single)
|
100
|
+
elsif @strategy == FIND_STRATEGY_IMAGE
|
101
|
+
locator = add_image_child_selector(locator, selectors, single)
|
102
|
+
else
|
103
|
+
# both paths are valid
|
104
|
+
add_xpath_child_selectors(locator, selectors, single)
|
105
|
+
locator = add_uiautomator_child_selector(locator, selectors, single)
|
106
|
+
end
|
107
|
+
|
108
|
+
if is_scrollable_selector?(selectors, single)
|
109
|
+
locator.scrollable_locator = locator
|
110
|
+
if selectors[:class] == "android.widget.HorizontalScrollView"
|
111
|
+
locator.scrollable_locator.scroll_orientation = :horizontal
|
112
|
+
else
|
113
|
+
locator.scrollable_locator.scroll_orientation = :vertical
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
locator.last_selector_adjacent = false
|
118
|
+
locator
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
private
|
123
|
+
def add_uiautomator_child_selector(locator, selectors, single)
|
124
|
+
if locator.single && !single
|
125
|
+
# current locator stays single, the child locator looks for multiple
|
126
|
+
params = selectors.merge({single: single, scrollable_locator: locator.scrollable_locator})
|
127
|
+
params[:default_find_strategy] = locator.default_find_strategy
|
128
|
+
params[:default_scroll_strategy] = locator.default_scroll_strategy
|
129
|
+
Locator.new(@driver, self, params)
|
130
|
+
else
|
131
|
+
locator.single = true
|
132
|
+
locator.ui_selector = "#{locator.ui_selector(false)}.childSelector(#{hash_to_uiautomator(selectors, single)})"
|
133
|
+
locator
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def add_image_child_selector(locator, selectors, single)
|
138
|
+
params = selectors.merge({single: single, scrollable_locator: locator.scrollable_locator})
|
139
|
+
Locator.new(@driver, self, params)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module TestaAppiumDriver
|
2
|
+
#noinspection RubyInstanceMethodNamingConvention
|
3
|
+
class ScrollActions
|
4
|
+
private
|
5
|
+
|
6
|
+
def uiautomator_scroll_to_start_or_end(type)
|
7
|
+
|
8
|
+
scrollable_selector = @scrollable.ui_selector(false)
|
9
|
+
orientation = @scrollable.scroll_orientation == :vertical ? ".setAsVerticalList()" : ".setAsHorizontalList()"
|
10
|
+
scroll_command = type == :start ? ".scrollToBeginning(#{DEFAULT_UIAUTOMATOR_MAX_SWIPES})" : ".scrollToEnd(#{DEFAULT_UIAUTOMATOR_MAX_SWIPES})"
|
11
|
+
cmd = "new UiScrollable(#{scrollable_selector})#{orientation}#{scroll_command};"
|
12
|
+
begin
|
13
|
+
puts "Scroll execute[uiautomator_#{type}]: #{cmd}"
|
14
|
+
@driver.find_element(uiautomator: cmd)
|
15
|
+
rescue
|
16
|
+
# Ignored
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
def uiautomator_scroll_to
|
24
|
+
raise "UiAutomator scroll cannot work with specified direction" unless @direction.nil?
|
25
|
+
|
26
|
+
scrollable_selector = @scrollable.ui_selector(false)
|
27
|
+
element_selector = @locator.ui_selector(false)
|
28
|
+
orientation_command = @scrollable.scroll_orientation == :vertical ? ".setAsVerticalList()" : ".setAsHorizontalList()"
|
29
|
+
cmd = "new UiScrollable(#{scrollable_selector})#{orientation_command}.scrollIntoView(#{element_selector});"
|
30
|
+
begin
|
31
|
+
puts "Scroll execute[uiautomator_scroll_to]: #{cmd}"
|
32
|
+
@driver.find_element(uiautomator: cmd)
|
33
|
+
rescue
|
34
|
+
# Ignored
|
35
|
+
ensure
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
def uiautomator_page_or_fling(type, direction)
|
41
|
+
scrollable_selector = @scrollable.ui_selector(false)
|
42
|
+
orientation = direction == :up || direction == :down ? ".setAsVerticalList()" : ".setAsHorizontalList()"
|
43
|
+
if type == SCROLL_ACTION_TYPE_SCROLL
|
44
|
+
direction_command = direction == :down || direction == :right ? ".scrollForward()" : ".scrollBackward()"
|
45
|
+
elsif type == SCROLL_ACTION_TYPE_FLING
|
46
|
+
direction_command = direction == :down || direction == :right ? ".flingForward()" : ".flingBackward()"
|
47
|
+
else
|
48
|
+
raise "Unknown scroll action type #{type}"
|
49
|
+
end
|
50
|
+
cmd = "new UiScrollable(#{scrollable_selector})#{orientation}#{direction_command};"
|
51
|
+
begin
|
52
|
+
puts "Scroll execute[uiautomator_#{type}]: #{cmd}"
|
53
|
+
@driver.find_element(uiautomator: cmd)
|
54
|
+
rescue
|
55
|
+
# Ignored
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
module TestaAppiumDriver
|
5
|
+
class Bounds
|
6
|
+
|
7
|
+
attr_reader :width
|
8
|
+
attr_reader :height
|
9
|
+
attr_reader :offset
|
10
|
+
|
11
|
+
|
12
|
+
# @param top_left [Coordinates]
|
13
|
+
# @param bottom_right [Coordinates]
|
14
|
+
# @param window_width [Integer]
|
15
|
+
# @param window_height [Integer]
|
16
|
+
def initialize(top_left, bottom_right, window_width, window_height)
|
17
|
+
@top_left = top_left
|
18
|
+
@bottom_right = bottom_right
|
19
|
+
@width = bottom_right.x - top_left.x
|
20
|
+
@height = bottom_right.y - top_left.y
|
21
|
+
@offset = Offset.new(self, window_width, window_height)
|
22
|
+
@center = TestaAppiumDriver::Coordinates.new(@top_left.x + @width/2, @top_left.y + @height / 2)
|
23
|
+
end
|
24
|
+
|
25
|
+
def as_json
|
26
|
+
{
|
27
|
+
width: @width,
|
28
|
+
height: @height,
|
29
|
+
top_left: @top_left.as_json,
|
30
|
+
bottom_right: @bottom_right.as_json,
|
31
|
+
offset: @offset.as_json
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
# @return [TestaAppiumDriver::Offset]
|
36
|
+
def offset
|
37
|
+
@offset
|
38
|
+
end
|
39
|
+
|
40
|
+
# @return [TestaAppiumDriver::Coordinates]
|
41
|
+
def top_left
|
42
|
+
@top_left
|
43
|
+
end
|
44
|
+
# @return [TestaAppiumDriver::Coordinates]
|
45
|
+
def bottom_right
|
46
|
+
@bottom_right
|
47
|
+
end
|
48
|
+
|
49
|
+
# @return [TestaAppiumDriver::Coordinates]
|
50
|
+
def center
|
51
|
+
@center
|
52
|
+
end
|
53
|
+
|
54
|
+
def to_s
|
55
|
+
JSON.dump(as_json)
|
56
|
+
end
|
57
|
+
|
58
|
+
# @param bounds [String] bounds that driver.attribute("bounds") return
|
59
|
+
# @param driver [TestaAppiumDriver::Driver]
|
60
|
+
def self.from_android(bounds, driver)
|
61
|
+
matches = bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/)
|
62
|
+
raise "Unexpected bounds: #{bounds}" unless matches
|
63
|
+
|
64
|
+
captures = matches.captures
|
65
|
+
top_left = Coordinates.new(captures[0], captures[1])
|
66
|
+
bottom_right = Coordinates.new(captures[2], captures[3])
|
67
|
+
ws = driver.window_size
|
68
|
+
window_width = ws.width.to_i
|
69
|
+
window_height = ws.height.to_i
|
70
|
+
Bounds.new(top_left, bottom_right, window_width, window_height)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.from_ios(rect, driver)
|
74
|
+
rect = JSON.parse(rect)
|
75
|
+
top_left = Coordinates.new(rect["x"], rect["y"])
|
76
|
+
bottom_right = Coordinates.new(top_left.x + rect["width"].to_i, top_left.y + rect["height"].to_i)
|
77
|
+
ws = driver.window_size
|
78
|
+
window_width = ws.width.to_i
|
79
|
+
window_height = ws.height.to_i
|
80
|
+
Bounds.new(top_left, bottom_right, window_width, window_height)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
#noinspection ALL
|
85
|
+
class Coordinates
|
86
|
+
def initialize(x, y)
|
87
|
+
@x = x.to_i
|
88
|
+
@y = y.to_i
|
89
|
+
end
|
90
|
+
|
91
|
+
def as_json
|
92
|
+
{
|
93
|
+
x: @x,
|
94
|
+
y: @y
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
# @return [Integer]
|
100
|
+
def x
|
101
|
+
@x
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Integer]
|
105
|
+
def y
|
106
|
+
@y
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
class Offset
|
112
|
+
def initialize(bounds, window_width, window_height)
|
113
|
+
@top = bounds.top_left.y
|
114
|
+
@right = window_width - bounds.bottom_right.x
|
115
|
+
@bottom = window_height - bounds.bottom_right.y
|
116
|
+
@left = bounds.top_left.x
|
117
|
+
end
|
118
|
+
|
119
|
+
def as_json
|
120
|
+
{
|
121
|
+
top: @top,
|
122
|
+
right: @right,
|
123
|
+
bottom: @bottom,
|
124
|
+
left: @left
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
|
129
|
+
# @return [Integer]
|
130
|
+
def top
|
131
|
+
@top
|
132
|
+
end
|
133
|
+
|
134
|
+
# @return [Integer]
|
135
|
+
def right
|
136
|
+
@right
|
137
|
+
end
|
138
|
+
|
139
|
+
# @return [Integer]
|
140
|
+
def bottom
|
141
|
+
@bottom
|
142
|
+
end
|
143
|
+
|
144
|
+
# @return [Integer]
|
145
|
+
def left
|
146
|
+
@left
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#noinspection ALL
|
4
|
+
module TestaAppiumDriver
|
5
|
+
FIND_STRATEGY_UIAUTOMATOR = :uiautomator
|
6
|
+
FIND_STRATEGY_XPATH = :xpath
|
7
|
+
FIND_STRATEGY_ID = :id
|
8
|
+
FIND_STRATEGY_NAME = :name
|
9
|
+
FIND_STRATEGY_IMAGE = :image
|
10
|
+
FIND_STRATEGY_CLASS_CHAIN = :class_chain
|
11
|
+
|
12
|
+
SCROLL_STRATEGY_UIAUTOMATOR = :uiautomator
|
13
|
+
SCROLL_STRATEGY_W3C = :w3c
|
14
|
+
|
15
|
+
|
16
|
+
SCROLL_CORRECTION_W3C = 30
|
17
|
+
SCROLL_ALIGNMENT_THRESHOLD = 25
|
18
|
+
|
19
|
+
SCROLL_ACTION_TYPE_SCROLL = :scroll
|
20
|
+
SCROLL_ACTION_TYPE_FLING = :fling
|
21
|
+
SCROLL_ACTION_TYPE_DRAG = :drag
|
22
|
+
|
23
|
+
|
24
|
+
DEFAULT_UIAUTOMATOR_MAX_SWIPES = 20
|
25
|
+
|
26
|
+
DEFAULT_ANDROID_FIND_STRATEGY = FIND_STRATEGY_UIAUTOMATOR
|
27
|
+
#DEFAULT_ANDROID_SCROLL_STRATEGY = SCROLL_STRATEGY_UIAUTOMATOR
|
28
|
+
DEFAULT_ANDROID_SCROLL_STRATEGY = SCROLL_STRATEGY_W3C
|
29
|
+
|
30
|
+
|
31
|
+
DEFAULT_IOS_FIND_STRATEGY = FIND_STRATEGY_XPATH
|
32
|
+
DEFAULT_IOS_SCROLL_STRATEGY = SCROLL_STRATEGY_W3C
|
33
|
+
|
34
|
+
DEFAULT_W3C_MAX_SCROLLS = 7
|
35
|
+
|
36
|
+
EXISTS_WAIT = 0.5
|
37
|
+
LONG_TAP_DURATION = 1.5
|
38
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TestaAppiumDriver
|
4
|
+
class StrategyMixException < Exception
|
5
|
+
def initialize(strategy, strategy_reason, mixed_strategy, mixed_reason)
|
6
|
+
|
7
|
+
# example: parent is only available in xpath strategy and cannot be used with from_element which is only available in uiautomator strategy
|
8
|
+
msg = "strategy mix exception: '#{strategy_reason}' is only available in #{strategy} strategy and cannot be used with '#{mixed_reason}' which is only available in #{mixed_strategy} strategy"
|
9
|
+
super(msg)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|