testa_appium_driver 0.1.21 → 0.1.24
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.
- checksums.yaml +4 -4
- data/.gitattributes +23 -0
- data/.gitignore +17 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/Gemfile.lock +1 -1
- 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 +380 -0
- data/lib/testa_appium_driver/common/scroll_actions.rb +275 -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
|