testa_appium_driver 0.1.11 → 0.1.14

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +23 -0
  3. data/.gitignore +16 -16
  4. data/.rspec +3 -3
  5. data/.rubocop.yml +13 -13
  6. data/CHANGELOG.md +5 -5
  7. data/CODE_OF_CONDUCT.md +102 -102
  8. data/Gemfile +12 -12
  9. data/Gemfile.lock +74 -0
  10. data/LICENSE.txt +21 -21
  11. data/README.md +402 -378
  12. data/Rakefile +12 -12
  13. data/{testa_appium_driver.iml → appium-driver.iml} +71 -78
  14. data/bin/console +17 -17
  15. data/bin/setup +8 -8
  16. data/lib/testa_appium_driver/android/class_selectors.rb +437 -437
  17. data/lib/testa_appium_driver/android/driver.rb +70 -69
  18. data/lib/testa_appium_driver/android/locator/attributes.rb +117 -113
  19. data/lib/testa_appium_driver/android/locator.rb +141 -141
  20. data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +61 -61
  21. data/lib/testa_appium_driver/android/selenium_element.rb +11 -7
  22. data/lib/testa_appium_driver/common/bounds.rb +149 -149
  23. data/lib/testa_appium_driver/common/constants.rb +37 -36
  24. data/lib/testa_appium_driver/common/exceptions/strategy_mix_exception.rb +11 -11
  25. data/lib/testa_appium_driver/common/helpers.rb +270 -270
  26. data/lib/testa_appium_driver/common/locator/scroll_actions.rb +397 -397
  27. data/lib/testa_appium_driver/common/locator.rb +627 -610
  28. data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +3 -3
  29. data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +304 -237
  30. data/lib/testa_appium_driver/common/scroll_actions.rb +253 -246
  31. data/lib/testa_appium_driver/common/selenium_element.rb +19 -19
  32. data/lib/testa_appium_driver/driver.rb +328 -312
  33. data/lib/testa_appium_driver/ios/driver.rb +48 -48
  34. data/lib/testa_appium_driver/ios/locator/attributes.rb +84 -80
  35. data/lib/testa_appium_driver/ios/locator.rb +71 -70
  36. data/lib/testa_appium_driver/ios/selenium_element.rb +6 -6
  37. data/lib/testa_appium_driver/ios/type_selectors.rb +187 -187
  38. data/lib/testa_appium_driver/version.rb +5 -5
  39. data/lib/testa_appium_driver.rb +6 -6
  40. data/testa_appium_driver.gemspec +41 -41
  41. metadata +9 -16
  42. data/.idea/deployment.xml +0 -22
  43. data/.idea/inspectionProfiles/Project_Default.xml +0 -9
  44. data/.idea/misc.xml +0 -6
  45. data/.idea/modules.xml +0 -8
  46. data/.idea/runConfigurations/Android_Test.xml +0 -42
  47. data/.idea/runConfigurations.xml +0 -10
  48. data/.idea/sshConfigs.xml +0 -13
  49. data/.idea/vcs.xml +0 -6
  50. data/.idea/webServers.xml +0 -21
@@ -1,62 +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
-
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
62
  end
@@ -1,8 +1,12 @@
1
- module Selenium
2
- module WebDriver
3
- class Element
4
- include TestaAppiumDriver::ClassSelectors
5
- include TestaAppiumDriver::Attributes
6
- end
7
- end
1
+ module ::Appium
2
+ module Core
3
+ class Element
4
+ include TestaAppiumDriver::ClassSelectors
5
+ include TestaAppiumDriver::Attributes
6
+
7
+ def parent
8
+ self.find_element(xpath: "./..")
9
+ end
10
+ end
11
+ end
8
12
  end
@@ -1,150 +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
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
150
  end
@@ -1,37 +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
-
29
-
30
- DEFAULT_IOS_FIND_STRATEGY = FIND_STRATEGY_XPATH
31
- DEFAULT_IOS_SCROLL_STRATEGY = SCROLL_STRATEGY_W3C
32
-
33
- DEFAULT_W3C_MAX_SCROLLS = 7
34
-
35
- EXISTS_WAIT = 0.5
36
- LONG_TAP_DURATION = 1.5
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
37
38
  end
@@ -1,12 +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
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
12
  end