testa_appium_driver 0.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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.idea/deployment.xml +21 -0
  4. data/.idea/inspectionProfiles/Project_Default.xml +9 -0
  5. data/.idea/misc.xml +6 -0
  6. data/.idea/modules.xml +8 -0
  7. data/.idea/runConfigurations/Android_Test.xml +42 -0
  8. data/.idea/sshConfigs.xml +10 -0
  9. data/.idea/vcs.xml +6 -0
  10. data/.idea/webServers.xml +14 -0
  11. data/.rspec +3 -0
  12. data/.rubocop.yml +13 -0
  13. data/CHANGELOG.md +5 -0
  14. data/CODE_OF_CONDUCT.md +102 -0
  15. data/Gemfile +12 -0
  16. data/LICENSE.txt +21 -0
  17. data/README.md +52 -0
  18. data/Rakefile +12 -0
  19. data/bin/console +17 -0
  20. data/bin/setup +8 -0
  21. data/lib/testa_appium_driver.rb +6 -0
  22. data/lib/testa_appium_driver/android/class_selectors.rb +353 -0
  23. data/lib/testa_appium_driver/android/driver.rb +52 -0
  24. data/lib/testa_appium_driver/android/locator.rb +115 -0
  25. data/lib/testa_appium_driver/android/locator/attributes.rb +116 -0
  26. data/lib/testa_appium_driver/android/scroll_actions/uiautomator_scroll_actions.rb +77 -0
  27. data/lib/testa_appium_driver/android/selenium_element.rb +8 -0
  28. data/lib/testa_appium_driver/common/bounds.rb +150 -0
  29. data/lib/testa_appium_driver/common/constants.rb +33 -0
  30. data/lib/testa_appium_driver/common/exceptions/strategy_mix_exception.rb +12 -0
  31. data/lib/testa_appium_driver/common/helpers.rb +242 -0
  32. data/lib/testa_appium_driver/common/locator.rb +371 -0
  33. data/lib/testa_appium_driver/common/locator/scroll_actions.rb +287 -0
  34. data/lib/testa_appium_driver/common/scroll_actions.rb +253 -0
  35. data/lib/testa_appium_driver/common/scroll_actions/json_wire_scroll_actions.rb +4 -0
  36. data/lib/testa_appium_driver/common/scroll_actions/w3c_scroll_actions.rb +261 -0
  37. data/lib/testa_appium_driver/driver.rb +226 -0
  38. data/lib/testa_appium_driver/ios/driver.rb +35 -0
  39. data/lib/testa_appium_driver/ios/locator.rb +40 -0
  40. data/lib/testa_appium_driver/ios/locator/attributes.rb +79 -0
  41. data/lib/testa_appium_driver/ios/selenium_element.rb +7 -0
  42. data/lib/testa_appium_driver/ios/type_selectors.rb +167 -0
  43. data/lib/testa_appium_driver/version.rb +5 -0
  44. data/testa_appium_driver.gemspec +40 -0
  45. data/testa_appium_driver.iml +79 -0
  46. metadata +147 -0
@@ -0,0 +1,287 @@
1
+ module TestaAppiumDriver
2
+ #noinspection RubyTooManyMethodsInspection
3
+ class Locator
4
+
5
+ # @param [Float] duration in seconds
6
+ def long_tap(duration = LONG_TAP_DURATION)
7
+ action_builder = @driver.action
8
+ b = bounds
9
+ f1 = action_builder.add_pointer_input(:touch, "finger1")
10
+ f1.create_pointer_move(duration: 0, x: b.center.x, y: b.center.y, origin: ::Selenium::WebDriver::Interactions::PointerMove::VIEWPORT)
11
+ f1.create_pointer_down(:left)
12
+ f1.create_pause(duration)
13
+ f1.create_pointer_up(:left)
14
+ puts "long tap execute: {x: #{b.center.x}, y: #{b.center.y}}"
15
+ @driver.perform_actions [f1]
16
+ end
17
+
18
+ # @return [Array] array of [Selenium::WebDriver::Element]
19
+ def each(deadzone: nil, skip_scroll_to_start: false, &block)
20
+ raise "Each can only be performed on multiple elements locator" if @single
21
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
22
+ sa = ScrollActions.new(@scrollable_locator,
23
+ locator: self,
24
+ deadzone: deadzone,
25
+ default_scroll_strategy: @default_scroll_strategy)
26
+ sa.each(skip_scroll_to_start, &block)
27
+ end
28
+
29
+
30
+ # Aligns element (by default) on top of the scrollable container, if the element does not exists it will scroll to find it
31
+ # @return [TestaAppiumDriver::Locator]
32
+ def align(with = :top, deadzone: nil, raise: false)
33
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
34
+ sa = ScrollActions.new(@scrollable_locator,
35
+ locator: self,
36
+ deadzone: deadzone,
37
+ default_scroll_strategy: @default_scroll_strategy,
38
+ raise: raise)
39
+ sa.align(with)
40
+ self
41
+ end
42
+
43
+ # Aligns element on top of the scrollable container, if the element does not exists it will scroll to find it
44
+ # @return [TestaAppiumDriver::Locator]
45
+ def align_top(deadzone: nil)
46
+ align(:top, deadzone: deadzone)
47
+ end
48
+
49
+ # Aligns element on bottom of the scrollable container, if the element does not exists it will scroll to find it
50
+ # @return [TestaAppiumDriver::Locator]
51
+ def align_bottom(deadzone: nil)
52
+ align(:bottom, deadzone: deadzone)
53
+ end
54
+
55
+ # Aligns element on left of the scrollable container, if the element does not exists it will scroll to find it
56
+ # @return [TestaAppiumDriver::Locator]
57
+ def align_left(deadzone: nil)
58
+ align(:left, deadzone: deadzone)
59
+ end
60
+
61
+ # Aligns element on right of the scrollable container, if the element does not exists it will scroll to find it
62
+ # @return [TestaAppiumDriver::Locator]
63
+ def align_right(deadzone: nil)
64
+ align(:right, deadzone: deadzone)
65
+ end
66
+
67
+ # Aligns element (by default) on top of the scrollable container, if the element does not exists it raise an exception
68
+ # @return [TestaAppiumDriver::Locator]
69
+ def align!(with = :top, deadzone: nil)
70
+ align(with, deadzone: deadzone, raise: true)
71
+ end
72
+
73
+ # Aligns element on top of the scrollable container, if the element does not exists it raise an exception
74
+ # @return [TestaAppiumDriver::Locator]
75
+ def align_top!(deadzone: nil)
76
+ align(:top, deadzone: deadzone, raise: true)
77
+ end
78
+
79
+ # Aligns element on bottom of the scrollable container, if the element does not exists it raise an exception
80
+ # @return [TestaAppiumDriver::Locator]
81
+ def align_bottom!(deadzone: nil)
82
+ align(:bottom, deadzone: deadzone, raise: true)
83
+ end
84
+
85
+ # Aligns element on left of the scrollable container, if the element does not exists it raise an exception
86
+ # @return [TestaAppiumDriver::Locator]
87
+ def align_left!(deadzone: nil)
88
+ align(:left, deadzone: deadzone, raise: true)
89
+ end
90
+
91
+ # Aligns element on right of the scrollable container, if the element does not exists it raise an exception
92
+ # @return [TestaAppiumDriver::Locator]
93
+ def align_right!(deadzone: nil)
94
+ align(:right, deadzone: deadzone, raise: true)
95
+ end
96
+
97
+
98
+ # First scrolls to the beginning of the scrollable container and then scrolls down until element is found or end is reached
99
+ # @return [TestaAppiumDriver::Locator]
100
+ def scroll_to(deadzone: nil, max_scrolls: nil, direction: nil)
101
+ _scroll_to(deadzone, max_scrolls, direction)
102
+ end
103
+
104
+
105
+ # Scrolls down until element is found or end is reached
106
+ # @return [TestaAppiumDriver::Locator]
107
+ def scroll_down_to(deadzone: nil, max_scrolls: nil)
108
+ _scroll_to(deadzone, max_scrolls, :down)
109
+ end
110
+
111
+ # Scrolls up until element is found or end is reached
112
+ # @return [TestaAppiumDriver::Locator]
113
+ def scroll_up_to(deadzone: nil, max_scrolls: nil)
114
+ _scroll_to(deadzone, max_scrolls, :up)
115
+ end
116
+
117
+ # Scrolls right until element is found or end is reached
118
+ # @return [TestaAppiumDriver::Locator]
119
+ def scroll_right_to(deadzone: nil, max_scrolls: nil)
120
+ _scroll_to(deadzone, max_scrolls, :right)
121
+ end
122
+
123
+
124
+ # Scrolls left until element is found or end is reached
125
+ # @return [TestaAppiumDriver::Locator]
126
+ def scroll_left_to(deadzone: nil, max_scrolls: nil)
127
+ _scroll_to(deadzone, max_scrolls, :left)
128
+ end
129
+
130
+ # Scrolls to the start of the scrollable container (top on vertical container, left on horizontal)
131
+ # @return [TestaAppiumDriver::Locator]
132
+ def scroll_to_start(deadzone: nil)
133
+ _scroll_to_start_or_end(:start, deadzone)
134
+ end
135
+
136
+ # Scrolls to the end of the scrollable container (bottom on vertical container, right on horizontal)
137
+ # @return [TestaAppiumDriver::Locator]
138
+ def scroll_to_end(deadzone: nil)
139
+ _scroll_to_start_or_end(:end, deadzone)
140
+ end
141
+
142
+
143
+ # @return [TestaAppiumDriver::Locator]
144
+ def page_down(deadzone: nil)
145
+ _page(:down, deadzone)
146
+ end
147
+
148
+ # @return [TestaAppiumDriver::Locator]
149
+ def page_up(deadzone: nil)
150
+ _page(:up, deadzone)
151
+ end
152
+
153
+ # @return [TestaAppiumDriver::Locator]
154
+ def page_left(deadzone: nil)
155
+ _page(:left, deadzone)
156
+ end
157
+
158
+ # @return [TestaAppiumDriver::Locator]
159
+ def page_right(deadzone: nil)
160
+ _page(:right, deadzone)
161
+ end
162
+
163
+ # @return [TestaAppiumDriver::Locator]
164
+ def fling_down(deadzone: nil)
165
+ _fling(:down, deadzone)
166
+ end
167
+
168
+ # @return [TestaAppiumDriver::Locator]
169
+ def fling_up(deadzone: nil)
170
+ _fling(:up, deadzone)
171
+ end
172
+
173
+ # @return [TestaAppiumDriver::Locator]
174
+ def fling_left(deadzone: nil)
175
+ _fling(:left, deadzone)
176
+ end
177
+
178
+ # @return [TestaAppiumDriver::Locator]
179
+ def fling_right(deadzone: nil)
180
+ _fling(:right, deadzone)
181
+ end
182
+
183
+
184
+ # @param [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element, String] to
185
+ #noinspection RubyYardParamTypeMatch,RubyScope
186
+ def drag_to(to)
187
+ if !to.kind_of?(Selenium::WebDriver::Element) && !to.kind_of?(TestaAppiumDriver::Locator) && !to.kind_of?(Hash)
188
+ raise "Parameter not accepted, acceptable instances of [TestaAppiumDriver::Locator, Hash, Selenium::WebDriver::Element]"
189
+ end
190
+ if to.kind_of?(Selenium::WebDriver::Element)
191
+ bounds = TestaAppiumDriver::Bounds.from_android(to.bounds, @driver)
192
+ x = bounds.center.x
193
+ y = bounds.center.y
194
+ end
195
+ if to.kind_of?(TestaAppiumDriver::Locator)
196
+ bounds = to.bounds
197
+ x = bounds.center.x
198
+ y = bounds.center.y
199
+ end
200
+ if to.kind_of?(Hash)
201
+ raise "Missing x coordinate" if to[:x].nil?
202
+ raise "Missing y coordinate" if to[:y].nil?
203
+ x = to[:x]
204
+ y = to[:y]
205
+ end
206
+ _drag_to(x, y)
207
+ end
208
+
209
+ def drag_by(amount, direction: :top)
210
+ b = bounds
211
+ x = b.center.x
212
+ y = b.center.y
213
+ case direction
214
+ when :top
215
+ y -= amount.to_i
216
+ when :bottom
217
+ y += amount.to_i
218
+ when :left
219
+ x -= amount.to_i
220
+ when :right
221
+ x += amount.to_i
222
+ else
223
+ raise "Unknown direction #{direction}"
224
+ end
225
+ _drag_to(x, y)
226
+ end
227
+
228
+
229
+
230
+ private
231
+ def _drag_to(x, y)
232
+ sa = ScrollActions.new(@scrollable_locator,
233
+ locator: self,
234
+ default_scroll_strategy: @default_scroll_strategy)
235
+ sa.drag_to(x, y)
236
+ self
237
+ end
238
+ def _page(direction, deadzone)
239
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
240
+ sa = ScrollActions.new(@scrollable_locator,
241
+ locator: self,
242
+ deadzone: deadzone,
243
+ direction: direction.to_sym,
244
+ default_scroll_strategy: @default_scroll_strategy)
245
+ sa.send("page_#{direction}")
246
+ self
247
+ end
248
+
249
+ def _fling(direction, deadzone)
250
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
251
+ sa = ScrollActions.new(@scrollable_locator,
252
+ locator: self,
253
+ deadzone: deadzone,
254
+ direction: direction.to_sym,
255
+ default_scroll_strategy: @default_scroll_strategy)
256
+ sa.send("fling_#{direction}")
257
+ self
258
+ end
259
+
260
+ def _scroll_to_start_or_end(type, deadzone)
261
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
262
+ sa = ScrollActions.new(@scrollable_locator,
263
+ locator: self,
264
+ deadzone: deadzone,
265
+ direction: :left,
266
+ default_scroll_strategy: @default_scroll_strategy)
267
+ if type == :start
268
+ sa.scroll_to_start
269
+ else
270
+ sa.scroll_to_end
271
+ end
272
+ self
273
+ end
274
+
275
+ def _scroll_to(deadzone, max_scrolls, direction)
276
+ deadzone = @scrollable_locator.scroll_deadzone if deadzone.nil? && !@scrollable_locator.nil?
277
+ sa = ScrollActions.new(@scrollable_locator,
278
+ locator: self,
279
+ deadzone: deadzone,
280
+ max_scrolls: max_scrolls,
281
+ direction: direction,
282
+ default_scroll_strategy: @default_scroll_strategy)
283
+ sa.scroll_to
284
+ self
285
+ end
286
+ end
287
+ end
@@ -0,0 +1,253 @@
1
+ require_relative 'scroll_actions/json_wire_scroll_actions'
2
+ require_relative 'scroll_actions/w3c_scroll_actions'
3
+
4
+
5
+ module TestaAppiumDriver
6
+ #noinspection RubyResolve,RubyTooManyInstanceVariablesInspection
7
+ class ScrollActions
8
+
9
+ def initialize(scrollable, params = {})
10
+ @scrollable = scrollable
11
+ @locator = params[:locator]
12
+ @deadzone = params[:deadzone]
13
+ @direction = params[:direction]
14
+ @max_scrolls = params[:max_scrolls]
15
+ @default_scroll_strategy = params[:default_scroll_strategy]
16
+ @driver = @locator.driver
17
+
18
+ @raise = params[:raise]
19
+
20
+ if @scrollable.nil?
21
+ # if we dont have a scrollable element or if we do have it, but it is not compatible with uiautomator
22
+ # then find first scrollable in document
23
+ @scrollable = @driver.scrollable
24
+ end
25
+
26
+ @strategy = nil
27
+ if @scrollable.strategy == FIND_STRATEGY_XPATH || # uiautomator cannot resolve scrollable from a xpath locator
28
+ !@deadzone.nil? ||
29
+ !@scrollable.from_element.instance_of?(TestaAppiumDriver::Driver) # uiautomator cannot resolve nested scrollable
30
+ @strategy = SCROLL_STRATEGY_W3C
31
+ end
32
+
33
+
34
+ @bounds = @scrollable.bounds
35
+ end
36
+
37
+
38
+ def align(with)
39
+ w3c_align(with)
40
+ @locator
41
+ end
42
+
43
+ # @return [Array]
44
+ def each(skip_scroll_to_start, &block)
45
+ w3c_each(skip_scroll_to_start, &block)
46
+ end
47
+
48
+ def resolve_strategy
49
+ if @strategy.nil?
50
+ @default_scroll_strategy
51
+ else
52
+ @strategy
53
+ end
54
+ end
55
+
56
+
57
+ def scroll_to
58
+ if @locator.strategy != FIND_STRATEGY_XPATH && resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
59
+ uiautomator_scroll_to
60
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
61
+ w3c_scroll_to(nil)
62
+ end
63
+ end
64
+
65
+ def scroll_down_to
66
+ if resolve_strategy == SCROLL_STRATEGY_W3C
67
+ # we have direction enabled, uiautomator does not support direction specific element search
68
+ w3c_scroll_to(:down)
69
+ elsif resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
70
+ raise "scroll_down_to is not supported for uiautomator scroll strategy. Use scroll_to without deadzone"
71
+ end
72
+ end
73
+
74
+ def scroll_up_to
75
+ if resolve_strategy == SCROLL_STRATEGY_W3C
76
+ # we have direction enabled, uiautomator does not support direction specific element search
77
+ w3c_scroll_to(:up)
78
+ elsif resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
79
+ raise "scroll_up_to is not supported for uiautomator scroll strategy. Use scroll_to without deadzone"
80
+ end
81
+ end
82
+
83
+ def scroll_right_to
84
+ if resolve_strategy == SCROLL_STRATEGY_W3C
85
+ # we have direction enabled, uiautomator does not support direction specific element search
86
+ w3c_scroll_to(:right)
87
+ elsif resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
88
+ raise "scroll_right_to is not supported for uiautomator scroll strategy. Use scroll_to without deadzone"
89
+ end
90
+ end
91
+
92
+ def scroll_left_to
93
+ if resolve_strategy == SCROLL_STRATEGY_W3C
94
+ # we have direction enabled, uiautomator does not support direction specific element search
95
+ w3c_scroll_to(:left)
96
+ elsif resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
97
+ raise "scroll_left_to is not supported for uiautomator scroll strategy. Use scroll_to without deadzone"
98
+ end
99
+ end
100
+
101
+ def page_next
102
+ if @scrollable.scroll_orientation == :vertical
103
+ page_down
104
+ else
105
+ page_left
106
+ end
107
+ end
108
+
109
+ def page_back
110
+ if @scrollable.scroll_orientation == :vertical
111
+ page_up
112
+ else
113
+ page_right
114
+ end
115
+ end
116
+
117
+
118
+ def page_down
119
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
120
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :down)
121
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
122
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :down)
123
+ end
124
+ end
125
+
126
+ def page_right
127
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
128
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :right)
129
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
130
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :right)
131
+ end
132
+ end
133
+
134
+ def page_up
135
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
136
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :up)
137
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
138
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :up)
139
+ end
140
+ end
141
+
142
+ def page_left
143
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
144
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :left)
145
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
146
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_SCROLL, :left)
147
+ end
148
+ end
149
+
150
+
151
+ def scroll_to_start
152
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
153
+ uiautomator_scroll_to_start_or_end(:start)
154
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
155
+ w3c_scroll_to_start_or_end(:start)
156
+ end
157
+ end
158
+
159
+ def scroll_to_end
160
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
161
+ uiautomator_scroll_to_start_or_end(:end)
162
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
163
+ w3c_scroll_to_start_or_end(:end)
164
+ end
165
+ end
166
+
167
+ def fling_down
168
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
169
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :down)
170
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
171
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :down)
172
+ end
173
+ end
174
+
175
+ def fling_right
176
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
177
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :right)
178
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
179
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :right)
180
+ end
181
+ end
182
+
183
+ def fling_up
184
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
185
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :up)
186
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
187
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :up)
188
+ end
189
+ end
190
+
191
+ def fling_left
192
+ if resolve_strategy == SCROLL_STRATEGY_UIAUTOMATOR
193
+ uiautomator_page_or_fling(SCROLL_ACTION_TYPE_FLING, :left)
194
+ elsif resolve_strategy == SCROLL_STRATEGY_W3C
195
+ w3c_page_or_fling(SCROLL_ACTION_TYPE_FLING, :left)
196
+ end
197
+ end
198
+
199
+ def drag_to(x, y)
200
+ w3c_drag_to(x, y)
201
+ end
202
+
203
+
204
+ private
205
+ def is_end_of_scroll?
206
+ old_elements = @previous_elements
207
+ @previous_elements = @scrollable.first_and_last_leaf
208
+ old_elements == @previous_elements
209
+ end
210
+
211
+
212
+ def default_deadzone!
213
+ @deadzone = {} if @deadzone.nil?
214
+ if @deadzone[:top].nil?
215
+ @deadzone[:top] = 1
216
+ else
217
+ @deadzone[:top] = @deadzone[:top].to_f
218
+ end
219
+ if @deadzone[:bottom].nil?
220
+ @deadzone[:bottom] = 1
221
+ else
222
+ @deadzone[:bottom] = @deadzone[:bottom].to_f
223
+ end
224
+ if @deadzone[:right].nil?
225
+ @deadzone[:right] = 1
226
+ else
227
+ @deadzone[:right] = @deadzone[:right].to_f
228
+ end
229
+ if @deadzone[:left].nil?
230
+ @deadzone[:left] = 1
231
+ else
232
+ @deadzone[:left] = @deadzone[:left].to_f
233
+ end
234
+ end
235
+
236
+ def is_aligned?(with, element)
237
+ align_bounds = @locator.bounds(force_cache_element: element)
238
+ case with
239
+ when :top
240
+ @align_offset = align_bounds.top_left.y - @bounds.top_left.y + @deadzone[:top]
241
+ when :bottom
242
+ @align_offset = @bounds.bottom_right.y - @deadzone[:bottom] - align_bounds.bottom_right.y
243
+ when :right
244
+ @align_offset = @bounds.bottom_right.x - @deadzone[:right] - align_bounds.bottom_right.x
245
+ when :left
246
+ @align_offset = align_bounds.top_left.x - @bounds.top_left.x + @deadzone[:left]
247
+ else
248
+ raise "Unsupported align with option: #{with}"
249
+ end
250
+ @align_offset < SCROLL_ALIGNMENT_THRESHOLD
251
+ end
252
+ end
253
+ end