awetestlib 0.1.29pre3 → 0.1.29pre4

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 (38) hide show
  1. data/README.md +16 -8
  2. data/awetestlib.windows.gemspec +42 -41
  3. data/awetestlib_osx.gemspec +41 -47
  4. data/bin/awetestlib-android-setup.rb +2 -1
  5. data/bin/awetestlib-cucumber-setup.rb +2 -1
  6. data/bin/awetestlib-driver-setup.rb +1 -0
  7. data/bin/awetestlib-helpers.rb +2 -2
  8. data/bin/awetestlib-mobile-app-setup.rb +1 -0
  9. data/bin/awetestlib-netbeans-setup.rb +2 -1
  10. data/bin/awetestlib-regression-setup.rb +26 -12
  11. data/bin/awetestlib-rubymine-setup.rb +9 -4
  12. data/images/netbeans1.jpg +0 -0
  13. data/images/netbeans2.jpg +0 -0
  14. data/images/netbeans3.jpg +0 -0
  15. data/images/netbeans4.jpg +0 -0
  16. data/images/netbeans5.jpg +0 -0
  17. data/images/rubymine1.jpg +0 -0
  18. data/images/rubymine2.jpg +0 -0
  19. data/images/rubymine3.jpg +0 -0
  20. data/images/rubymine4.jpg +0 -0
  21. data/images/scripting1.png +0 -0
  22. data/images/scripting2.png +0 -0
  23. data/images/scripting3.png +0 -0
  24. data/images/scripting4.png +0 -0
  25. data/lib/awetestlib/logging.rb +6 -6
  26. data/lib/awetestlib/regression/browser.rb +15 -12
  27. data/lib/awetestlib/regression/drag_and_drop.rb +421 -421
  28. data/lib/awetestlib/regression/runner.rb +311 -307
  29. data/lib/awetestlib/regression/tables.rb +627 -627
  30. data/lib/awetestlib/regression/user_input.rb +576 -576
  31. data/lib/awetestlib/regression/utilities.rb +1056 -1046
  32. data/lib/awetestlib/regression/validations.rb +2 -1
  33. data/lib/version.rb +2 -2
  34. data/netbeans_setup.md +30 -30
  35. data/rubymine_setup.md +24 -24
  36. data/setup_samples/sample_cucumber/features/step_definitions/predefined_steps.rb +303 -25
  37. metadata +160 -34
  38. checksums.yaml +0 -7
@@ -1,421 +1,421 @@
1
- module Awetestlib
2
- module Regression
3
- # Methods for moving and resizing elements, manipulating the mouse, and checking for relative positioning of elements,
4
- # including overlap, overlay, etc.
5
- # @note Still experimental. Works with IE but not fully tested with Firefox or Chrome in Windows using Watir-webdriver.
6
- # Not compatible with Mac
7
- # Rdoc is work in progress
8
- module DragAndDrop
9
-
10
- # Verify that specified *inner_element* is fully enclosed by *outer_element*.
11
- # @param [Watir::Element] inner_element A reference to a DOM element
12
- # @param [Watir::Element] outer_element A reference to a DOM element
13
- # @param [String] desc Contains a message or description intended to appear in the log and/or report output
14
- def verify_element_inside(inner_element, outer_element, desc = '')
15
- mark_testlevel("#{__method__.to_s.titleize}", 3)
16
- msg = build_message("#{inner_element.class.to_s} (:id=#{inner_element.id}) is fully enclosed by "+
17
- "#{outer_element.class.to_s} (:id=#{outer_element.id}).", desc)
18
- if overlay?(inner_element, outer_element, :inside)
19
- failed_to_log(msg)
20
- else
21
- passed_to_log(msg)
22
- true
23
- end
24
- rescue
25
- failed_to_log("Unable to verify that #{msg} '#{$!}'")
26
- end
27
-
28
- # Verify that two elements, identified by specified attribute and value, do not overlap on a given *side*.
29
- # @param [Symbol] above_element The element type for the first element, e.g. :div, :span, etc.
30
- # @param [Symbol] above_how The element attribute used to identify the *above_element*.
31
- # Valid values depend on the kind of element.
32
- # Common values: :text, :id, :title, :name, :class, :href (:link only)
33
- # @param [String, Regexp] above_what A string or a regular expression to be found in the *above_how* attribute that uniquely identifies the element.
34
- # @param [Symbol] below_element The element type for the second element, e.g. :div, :span, etc.
35
- # @param [Symbol] below_how The element attribute used to identify the *below_element*.
36
- # @param [String, Regexp] below_what A string or a regular expression to be found in the *below_how* attribute that uniquely identifies the element.
37
- # @param [Symbol] side :top, :bottom, :left, :right, :inside, or :outside
38
- # @param [String] desc Contains a message or description intended to appear in the log and/or report output
39
- def verify_no_element_overlap(browser, above_element, above_how, above_what, below_element, below_how, below_what, side, desc = '')
40
- mark_testlevel("#{__method__.to_s.titleize}", 3)
41
- msg = build_message("#{above_element.to_s.titleize} #{above_how}=>#{above_what} does not overlap "+
42
- "#{below_element.to_s.titleize} #{below_how}=>#{below_what} at the #{side}.", desc)
43
- above = browser.element(above_how, above_what)
44
- below = browser.element(below_how, below_what)
45
- if overlay?(above, below, side)
46
- failed_to_log(msg)
47
- else
48
- passed_to_log(msg)
49
- true
50
- end
51
- rescue
52
- failed_to_log("Unable to verify that #{msg} '#{$!}'")
53
- end
54
-
55
- def overlay?(inner, outer, side = :bottom)
56
- #mark_testlevel("#{__method__.to_s.titleize}", 3)
57
- inner_t, inner_b, inner_l, inner_r = inner.bounding_rectangle_offsets
58
- outer_t, outer_b, outer_l, outer_r = outer.bounding_rectangle_offsets
59
- #overlay = false
60
- case side
61
- when :bottom
62
- overlay = inner_b > outer_t
63
- when :top
64
- overlay = inner_t > outer_t
65
- when :left
66
- overlay = inner_l < outer_r
67
- when :right
68
- overlay = inner_r > outer_r
69
- when :inside
70
- overlay = !(inner_t > outer_t and
71
- inner_r < outer_r and
72
- inner_l > outer_l and
73
- inner_b < outer_b)
74
- else
75
- overlay = (inner_t > outer_b or
76
- inner_r > outer_l or
77
- inner_l < outer_r or
78
- inner_b < outer_t)
79
- end
80
- overlay
81
- rescue
82
- failed_to_log("Unable to determine overlay. '#{$!}'")
83
- end
84
-
85
- def hover(browser, element, wait = 2)
86
- w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
87
- @ai.MoveMouse(xc1, yc1)
88
- sleep_for(1)
89
- end
90
-
91
- def move_element_with_handle(browser, element, handle_id, dx, dy)
92
- # msg = "Move element "
93
- # w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
94
- # newx = w1 + dx
95
- # newy = h1 + dy
96
- # msg << " by [#{dx}, #{dy}] to expected [[#{newx}, #{newy}] "
97
- # handle = get_resize_handle(element, handle_id)
98
- # hw, hh, hx, hy, hxc, hyc, hxlr, hylr = get_element_coordinates(browser, handle, true)
99
-
100
- # drag_and_drop(hxc, hyc, dx, dy)
101
-
102
- # w2, h2, x2, y2, xc2, yc2, xlr2, ylr2 = get_element_coordinates(browser, element, true)
103
-
104
- # xerr = x2 - newx
105
- # yerr = y2 - newy
106
- # xdsp = (x1 - x2).abs
107
- # ydsp = (y1 - y2).abs
108
-
109
- # if x2 == newx and y2 == newy
110
- # msg << "succeeded."
111
- # passed_to_log(msg)
112
- # else
113
- # msg << "failed. "
114
- # failed_to_log(msg)
115
- # debug_to_log("x: actual #{x2}, error #{xerr}, displace #{xdsp}. y: actual #{y2}, error #{yerr}, displace #{ydsp}.")
116
- # end
117
-
118
- end
119
-
120
- def resize_element_with_handle(browser, element, target, dx, dy=nil)
121
- #TODO enhance to accept differing percentages in each direction
122
- msg = "Resize element "
123
- w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
124
- if dy
125
- deltax = dx
126
- deltay = dy
127
- neww = w1 + dx
128
- newh = h1 + dy
129
- msg << " by [#{dx}, #{dy}] " #"" to expected dimension [#{neww}, #{newh}] "
130
- else
131
- deltax, deltay, neww, newh = adjust_dimensions_by_percent(w1, h1, dx, true)
132
- msg << "by #{dx} percent " #"" to expected dimension [#{neww}, #{newh}] "
133
- end
134
- handle = get_resize_handle_by_class(element, target) #, true)
135
- sleep_for(0.5)
136
- hw, hh, hx, hy, hxc, hyc, hxlr, hylr = get_element_coordinates(browser, handle, true)
137
- hxlr_diff = 0
138
- hylr_diff = 0
139
-
140
- # TODO These adjustments are adhoc and empirical. Need to be derived more rigorously
141
- if @browserAbbrev == 'IE'
142
- hxlr_diff = (xlr1 - hxlr)
143
- hylr_diff = (ylr1 - hylr)
144
- x_start = hxlr - 2
145
- y_start = hylr - 2
146
- else
147
- hxlr_diff = (xlr1 - hxlr) / 2 unless (xlr1 - hxlr) == 0
148
- hylr_diff = (ylr1 - hylr) / 2 unless (ylr1 - hylr) == 0
149
- x_start = hxlr
150
- y_start = hylr
151
- end
152
-
153
- newxlr = xlr1 + deltax
154
- newylr = ylr1 + deltay
155
- # msg << ", lower right [#{newxlr}, #{newylr}] - "
156
- sleep_for(0.5)
157
-
158
- drag_and_drop(x_start, y_start, deltax, deltay)
159
-
160
- sleep_for(1.5)
161
- w2, h2, x2, y2, xc2, yc2, xlr2, ylr2 = get_element_coordinates(browser, element, true)
162
-
163
- werr = w2 - neww
164
- herr = h2 - newh
165
-
166
- # TODO This adjustment is adhoc and empirical. Needs to be derived more rigorously
167
- xlrerr = xlr2 - newxlr + hxlr_diff
168
- ylrerr = ylr2 - newylr + hylr_diff
169
-
170
- xlrdsp = (xlr1 - xlr2).abs
171
- ylrdsp = (ylr1 - ylr2).abs
172
-
173
- debug_to_log("\n" +
174
- "\t\t hxlr_diff: #{hxlr_diff}\n" +
175
- "\t\t hylr_diff: #{hylr_diff}\n" +
176
- "\t\t werr: #{werr}\n" +
177
- "\t\t herr: #{herr}\n" +
178
- "\t\t xlrerr: #{xlrerr}\n" +
179
- "\t\t ylrerr: #{ylrerr}\n" +
180
- "\t\t xlrdsp: #{xlrdsp}\n" +
181
- "\t\t ylrdsp: #{ylrdsp}\n" +
182
- "\t\t @min_width: #{@min_width}\n" +
183
- "\t\t@min_height: #{@min_height}\n" +
184
- "\t\t x tol: #{@x_tolerance}\n" +
185
- "\t\t y tol: #{@y_tolerance}\n"
186
- )
187
-
188
- #TODO Add check that window _was_ resized.
189
- x_ok, x_msg = validate_move(w2, xlrerr, @x_tolerance, @min_width, xlr2)
190
- y_ok, y_msg = validate_move(h2, ylrerr, @y_tolerance, @min_height, ylr2)
191
- msg = msg + "x: #{x_msg}, y: #{y_msg}"
192
-
193
- if x_ok and y_ok
194
- passed_to_log(msg)
195
- else
196
- failed_to_log(msg)
197
- debug_to_log("x - actual #{xlr2}, error #{xlrerr}, displace #{xlrdsp}, y - actual #{ylr2}, error #{ylrerr}, displace #{ylrdsp}.")
198
- end
199
- sleep_for(1)
200
- rescue
201
- failed_to_log("Unable to validate resize. #{$!} (#{__LINE__})")
202
- sleep_for(1)
203
- end
204
-
205
- # :category: GUI
206
- def get_resize_handle_by_id(element, id, dbg=nil)
207
- handle = get_div_by_id(element, id, dbg)
208
- sleep_for(1)
209
- handle.flash(5)
210
- return handle
211
- end
212
-
213
- # :category: GUI
214
- def get_resize_handle_by_class(element, strg, dbg=nil)
215
- handle = get_div_by_class(element, strg, dbg)
216
- sleep_for(0.5)
217
- handle.flash(5)
218
- return handle
219
- end
220
-
221
- # :category: GUI
222
- def get_element_coordinates(browser, element, dbg=nil)
223
- bx, by, bw, bh = get_browser_coord(browser, dbg)
224
- if @browserAbbrev == 'IE'
225
- x_hack = @horizontal_hack_ie
226
- y_hack = @vertical_hack_ie
227
- elsif @browserAbbrev == 'FF'
228
- x_hack = @horizontal_hack_ff
229
- y_hack = @vertical_hack_ff
230
- end
231
- sleep_for(1)
232
- w, h = element.dimensions.to_a
233
- xc, yc = element.client_offset.to_a
234
- # xcc, ycc = element.client_center.to_a
235
- xcc = xc + w/2
236
- ycc = yc + h/2
237
- # screen offset:
238
- xs = bx + x_hack + xc - 1
239
- ys = by + y_hack + yc - 1
240
- # screen center:
241
- xsc = xs + w/2
242
- ysc = ys + h/2
243
- xslr = xs + w
244
- yslr = ys + h
245
- if dbg
246
- debug_to_log(
247
- "\n\t\tElement: #{element.inspect}"+
248
- "\n\t\tbrowser screen offset: x: #{bx} y: #{by}"+
249
- "\n\t\t dimensions: x: #{w} y: #{h}"+
250
- "\n\t\t client offset x: #{xc} y: #{yc}"+
251
- "\n\t\t screen offset x: #{xs} y: #{ys}"+
252
- "\n\t\t client center x: #{xcc} y: #{ycc}"+
253
- "\n\t\t screen center x: #{xsc} y: #{ysc}"+
254
- "\n\t\t screen lower right x: #{xslr} y: #{yslr}")
255
- end
256
- [w, h, xs, ys, xsc, ysc, xslr, yslr]
257
- end
258
-
259
- def adjust_dimensions_by_percent(w, h, p, returnnew=nil)
260
- p += 100
261
- nw = (w * (p/100.0)).to_i
262
- nh = (h * (p/100.0)).to_i
263
- deltaw = nw - w
264
- deltah = nh - h
265
- if returnnew
266
- [deltaw, deltah, nw, nh]
267
- else
268
- [deltaw, deltah]
269
- end
270
- end
271
-
272
- def get_browser_coord(browser=nil, dbg=nil)
273
- browser = @myBrowser if not browser
274
- title = browser.title
275
- x = @ai.WinGetPosX(title)
276
- y = @ai.WinGetPosY(title)
277
- w = @ai.WinGetPosWidth(title)
278
- h = @ai.WinGetPosHeight(title)
279
- if dbg
280
- debug_to_log("\n\t\tBrowser #{browser.inspect}\n"+
281
- "\t\tdimensions: x: #{w} y: #{h}"+
282
- "\t\tscreen offset x: #{x} y: #{y}")
283
- end
284
- [x, y, w, h]
285
- end
286
-
287
- def drag_and_drop_div(browser, how, what, delta_x, delta_y, desc = '')
288
- #TODO: webdriver
289
- #TODO: assumes element is div
290
- msg = "Drag and drop element :#{how}=>#{what} by x=>#{delta_x} y=>#{delta_y}."
291
- msg << " #{desc}" if desc.length > 0
292
- drag_me = browser.div(how, what)
293
- drag_me.drag_and_drop_by(delta_x, delta_y)
294
- passed_to_log(msg)
295
- true
296
- rescue
297
- failed_to_log(unable_to)
298
- end
299
-
300
- def drag_and_drop(x1, y1, dx, dy, speed=nil)
301
- speed = 10 if not speed
302
- x2 = x1 + dx
303
- y2 = y1 + dy
304
- debug_to_log("drag_and_drop: start: [#{x1}, #{y1}] end: [#{x2}, #{y2}]")
305
-
306
- @ai.MouseMove(x1, y1, speed)
307
- @ai.MouseClick("primary", x1, y1)
308
- sleep_for(0.5)
309
- @ai.MouseClick("primary", x1, y1)
310
- sleep_for(0.5)
311
- @ai.MouseClickDrag("primary", x1, y1, x2, y2, speed)
312
- end
313
-
314
- def drag_and_drop_element(browser, element, dx, dy, speed = nil)
315
- speed = 10 if not speed
316
- w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
317
- msg = "Move #{element} by [#{dx}, #{dy}] from center[#{xc1}, #{yc1}] "
318
- newxc = xc1 + dx
319
- newyc = yc1 + dy
320
- msg << "to center[[#{newxc}, #{newyc}]"
321
- sleep_for(0.5)
322
-
323
- drag_and_drop(xc1, yc1, dx, dy)
324
-
325
- sleep_for(1)
326
- w2, h2, x2, y2, xc2, yc2, xlr2, ylr2 = get_element_coordinates(browser, element, true)
327
-
328
- # TODO This adjustment is adhoc and empirical. Needs to be derived more rigorously
329
- xcerr = xc2 - xc1
330
- ycerr = yc2 - yc1
331
-
332
- debug_to_log("\n" +
333
- "\t\t xc1: #{xc1}\n" +
334
- "\t\t yc1: #{yc1}\n" +
335
- "\t\t xc2: #{xc2}\n" +
336
- "\t\t yc2: #{yc2}\n" +
337
- "\t\t xcerr: #{xlrerr}\n" +
338
- "\t\t ycerr: #{ylrerr}\n" +
339
- "\t\t x tol: #{@x_tolerance}\n" +
340
- "\t\t y tol: #{@y_tolerance}\n"
341
- )
342
-
343
- #TODO Add check that window _was_ resized.
344
- x_ok, x_msg = validate_drag_drop(xcerr, @x_tolerance, newxc, xc2)
345
- y_ok, y_msg = validate_drag_drop(ycerr, @y_tolerance, newyc, yc2)
346
- msg = msg + "x: #{x_msg}, y: #{y_msg}"
347
-
348
- if x_ok and y_ok
349
- passed_to_log(msg)
350
- else
351
- failed_to_log(msg)
352
- end
353
- sleep_for(1)
354
- rescue
355
- failed_to_log("Unable to validate drag and drop. #{$!} (#{__LINE__})")
356
- sleep_for(1)
357
- end
358
-
359
- def right_click(element)
360
- x = element.left_edge_absolute + 2
361
- y = element.top_edge_absolute + 2
362
- @ai.MouseClick("secondary", x, y)
363
- end
364
-
365
- def left_click(element)
366
- x = element.left_edge_absolute + 2
367
- y = element.top_edge_absolute + 2
368
- @ai.MouseClick("primary", x, y)
369
- end
370
-
371
- def screen_offset(element, browser=nil)
372
- bx, by, bw, bh = get_browser_coord(browser)
373
- ex = element.left_edge
374
- ey = element.top_edge
375
- [bx + ex, by + ey]
376
- end
377
-
378
- def screen_center(element, browser=nil)
379
- bx, by, bw, bh = get_browser_coord(browser)
380
- w, h = element.dimensions.to_a
381
- cx = bx + w/2
382
- cy = by + h/2
383
- [cx, cy]
384
- end
385
-
386
- def screen_lower_right(element, browser=nil)
387
- bx, by, bw, bh = get_browser_coord(browser)
388
- w, h = element.dimensions.to_a
389
- [bx + w, by + h]
390
- end
391
-
392
- def verify_resize(d, err, tol, min, act)
393
- ary = [false, "failed, actual #{act} err #{err}"]
394
- if err == 0
395
- ary = [true, 'succeeded ']
396
- #TODO need to find way to calculate this adjustment
397
- elsif d <= min + 4
398
- ary = [true, "reached minimum (#{min}) "]
399
- elsif err.abs <= tol
400
- ary = [true, "within tolerance (+-#{tol}px) "]
401
- end
402
- ary
403
- end
404
-
405
- alias validate_move verify_resize
406
- alias validate_resize verify_resize
407
-
408
- def validate_drag_drop(err, tol, exp, act)
409
- ary = [false, "failed, expected: #{exp}, actual: #{act}, err: #{err}"]
410
- if err == 0
411
- ary = [true, 'succeeded ']
412
- elsif err.abs <= tol
413
- ary = [true, "within tolerance (+-#{tol}px) "]
414
- end
415
- ary
416
- end
417
-
418
- end
419
- end
420
- end
421
-
1
+ module Awetestlib
2
+ module Regression
3
+ # Methods for moving and resizing elements, manipulating the mouse, and checking for relative positioning of elements,
4
+ # including overlap, overlay, etc.
5
+ # @note Still experimental. Works with IE but not fully tested with Firefox or Chrome in Windows using Watir-webdriver.
6
+ # Not compatible with Mac
7
+ # Rdoc is work in progress
8
+ module DragAndDrop
9
+
10
+ # Verify that specified *inner_element* is fully enclosed by *outer_element*.
11
+ # @param [Watir::Element] inner_element A reference to a DOM element
12
+ # @param [Watir::Element] outer_element A reference to a DOM element
13
+ # @param [String] desc Contains a message or description intended to appear in the log and/or report output
14
+ def verify_element_inside(inner_element, outer_element, desc = '')
15
+ mark_testlevel("#{__method__.to_s.titleize}", 3)
16
+ msg = build_message("#{inner_element.class.to_s} (:id=#{inner_element.id}) is fully enclosed by "+
17
+ "#{outer_element.class.to_s} (:id=#{outer_element.id}).", desc)
18
+ if overlay?(inner_element, outer_element, :inside)
19
+ failed_to_log(msg)
20
+ else
21
+ passed_to_log(msg)
22
+ true
23
+ end
24
+ rescue
25
+ failed_to_log("Unable to verify that #{msg} '#{$!}'")
26
+ end
27
+
28
+ # Verify that two elements, identified by specified attribute and value, do not overlap on a given *side*.
29
+ # @param [Symbol] above_element The element type for the first element, e.g. :div, :span, etc.
30
+ # @param [Symbol] above_how The element attribute used to identify the *above_element*.
31
+ # Valid values depend on the kind of element.
32
+ # Common values: :text, :id, :title, :name, :class, :href (:link only)
33
+ # @param [String, Regexp] above_what A string or a regular expression to be found in the *above_how* attribute that uniquely identifies the element.
34
+ # @param [Symbol] below_element The element type for the second element, e.g. :div, :span, etc.
35
+ # @param [Symbol] below_how The element attribute used to identify the *below_element*.
36
+ # @param [String, Regexp] below_what A string or a regular expression to be found in the *below_how* attribute that uniquely identifies the element.
37
+ # @param [Symbol] side :top, :bottom, :left, :right, :inside, or :outside
38
+ # @param [String] desc Contains a message or description intended to appear in the log and/or report output
39
+ def verify_no_element_overlap(browser, above_element, above_how, above_what, below_element, below_how, below_what, side, desc = '')
40
+ mark_testlevel("#{__method__.to_s.titleize}", 3)
41
+ msg = build_message("#{above_element.to_s.titleize} #{above_how}=>#{above_what} does not overlap "+
42
+ "#{below_element.to_s.titleize} #{below_how}=>#{below_what} at the #{side}.", desc)
43
+ above = browser.element(above_how, above_what)
44
+ below = browser.element(below_how, below_what)
45
+ if overlay?(above, below, side)
46
+ failed_to_log(msg)
47
+ else
48
+ passed_to_log(msg)
49
+ true
50
+ end
51
+ rescue
52
+ failed_to_log("Unable to verify that #{msg} '#{$!}'")
53
+ end
54
+
55
+ def overlay?(inner, outer, side = :bottom)
56
+ #mark_testlevel("#{__method__.to_s.titleize}", 3)
57
+ inner_t, inner_b, inner_l, inner_r = inner.bounding_rectangle_offsets
58
+ outer_t, outer_b, outer_l, outer_r = outer.bounding_rectangle_offsets
59
+ #overlay = false
60
+ case side
61
+ when :bottom
62
+ overlay = inner_b > outer_t
63
+ when :top
64
+ overlay = inner_t > outer_t
65
+ when :left
66
+ overlay = inner_l < outer_r
67
+ when :right
68
+ overlay = inner_r > outer_r
69
+ when :inside
70
+ overlay = !(inner_t > outer_t and
71
+ inner_r < outer_r and
72
+ inner_l > outer_l and
73
+ inner_b < outer_b)
74
+ else
75
+ overlay = (inner_t > outer_b or
76
+ inner_r > outer_l or
77
+ inner_l < outer_r or
78
+ inner_b < outer_t)
79
+ end
80
+ overlay
81
+ rescue
82
+ failed_to_log("Unable to determine overlay. '#{$!}'")
83
+ end
84
+
85
+ def hover(browser, element, wait = 2)
86
+ w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
87
+ @ai.MoveMouse(xc1, yc1)
88
+ sleep_for(1)
89
+ end
90
+
91
+ def move_element_with_handle(browser, element, handle_id, dx, dy)
92
+ # msg = "Move element "
93
+ # w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
94
+ # newx = w1 + dx
95
+ # newy = h1 + dy
96
+ # msg << " by [#{dx}, #{dy}] to expected [[#{newx}, #{newy}] "
97
+ # handle = get_resize_handle(element, handle_id)
98
+ # hw, hh, hx, hy, hxc, hyc, hxlr, hylr = get_element_coordinates(browser, handle, true)
99
+
100
+ # drag_and_drop(hxc, hyc, dx, dy)
101
+
102
+ # w2, h2, x2, y2, xc2, yc2, xlr2, ylr2 = get_element_coordinates(browser, element, true)
103
+
104
+ # xerr = x2 - newx
105
+ # yerr = y2 - newy
106
+ # xdsp = (x1 - x2).abs
107
+ # ydsp = (y1 - y2).abs
108
+
109
+ # if x2 == newx and y2 == newy
110
+ # msg << "succeeded."
111
+ # passed_to_log(msg)
112
+ # else
113
+ # msg << "failed. "
114
+ # failed_to_log(msg)
115
+ # debug_to_log("x: actual #{x2}, error #{xerr}, displace #{xdsp}. y: actual #{y2}, error #{yerr}, displace #{ydsp}.")
116
+ # end
117
+
118
+ end
119
+
120
+ def resize_element_with_handle(browser, element, target, dx, dy=nil)
121
+ #TODO enhance to accept differing percentages in each direction
122
+ msg = "Resize element "
123
+ w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
124
+ if dy
125
+ deltax = dx
126
+ deltay = dy
127
+ neww = w1 + dx
128
+ newh = h1 + dy
129
+ msg << " by [#{dx}, #{dy}] " #"" to expected dimension [#{neww}, #{newh}] "
130
+ else
131
+ deltax, deltay, neww, newh = adjust_dimensions_by_percent(w1, h1, dx, true)
132
+ msg << "by #{dx} percent " #"" to expected dimension [#{neww}, #{newh}] "
133
+ end
134
+ handle = get_resize_handle_by_class(element, target) #, true)
135
+ sleep_for(0.5)
136
+ hw, hh, hx, hy, hxc, hyc, hxlr, hylr = get_element_coordinates(browser, handle, true)
137
+ hxlr_diff = 0
138
+ hylr_diff = 0
139
+
140
+ # TODO These adjustments are adhoc and empirical. Need to be derived more rigorously
141
+ if @browserAbbrev == 'IE'
142
+ hxlr_diff = (xlr1 - hxlr)
143
+ hylr_diff = (ylr1 - hylr)
144
+ x_start = hxlr - 2
145
+ y_start = hylr - 2
146
+ else
147
+ hxlr_diff = (xlr1 - hxlr) / 2 unless (xlr1 - hxlr) == 0
148
+ hylr_diff = (ylr1 - hylr) / 2 unless (ylr1 - hylr) == 0
149
+ x_start = hxlr
150
+ y_start = hylr
151
+ end
152
+
153
+ newxlr = xlr1 + deltax
154
+ newylr = ylr1 + deltay
155
+ # msg << ", lower right [#{newxlr}, #{newylr}] - "
156
+ sleep_for(0.5)
157
+
158
+ drag_and_drop(x_start, y_start, deltax, deltay)
159
+
160
+ sleep_for(1.5)
161
+ w2, h2, x2, y2, xc2, yc2, xlr2, ylr2 = get_element_coordinates(browser, element, true)
162
+
163
+ werr = w2 - neww
164
+ herr = h2 - newh
165
+
166
+ # TODO This adjustment is adhoc and empirical. Needs to be derived more rigorously
167
+ xlrerr = xlr2 - newxlr + hxlr_diff
168
+ ylrerr = ylr2 - newylr + hylr_diff
169
+
170
+ xlrdsp = (xlr1 - xlr2).abs
171
+ ylrdsp = (ylr1 - ylr2).abs
172
+
173
+ debug_to_log("\n" +
174
+ "\t\t hxlr_diff: #{hxlr_diff}\n" +
175
+ "\t\t hylr_diff: #{hylr_diff}\n" +
176
+ "\t\t werr: #{werr}\n" +
177
+ "\t\t herr: #{herr}\n" +
178
+ "\t\t xlrerr: #{xlrerr}\n" +
179
+ "\t\t ylrerr: #{ylrerr}\n" +
180
+ "\t\t xlrdsp: #{xlrdsp}\n" +
181
+ "\t\t ylrdsp: #{ylrdsp}\n" +
182
+ "\t\t @min_width: #{@min_width}\n" +
183
+ "\t\t@min_height: #{@min_height}\n" +
184
+ "\t\t x tol: #{@x_tolerance}\n" +
185
+ "\t\t y tol: #{@y_tolerance}\n"
186
+ )
187
+
188
+ #TODO Add check that window _was_ resized.
189
+ x_ok, x_msg = validate_move(w2, xlrerr, @x_tolerance, @min_width, xlr2)
190
+ y_ok, y_msg = validate_move(h2, ylrerr, @y_tolerance, @min_height, ylr2)
191
+ msg = msg + "x: #{x_msg}, y: #{y_msg}"
192
+
193
+ if x_ok and y_ok
194
+ passed_to_log(msg)
195
+ else
196
+ failed_to_log(msg)
197
+ debug_to_log("x - actual #{xlr2}, error #{xlrerr}, displace #{xlrdsp}, y - actual #{ylr2}, error #{ylrerr}, displace #{ylrdsp}.")
198
+ end
199
+ sleep_for(1)
200
+ rescue
201
+ failed_to_log("Unable to validate resize. #{$!} (#{__LINE__})")
202
+ sleep_for(1)
203
+ end
204
+
205
+ # :category: GUI
206
+ def get_resize_handle_by_id(element, id, dbg=nil)
207
+ handle = get_div_by_id(element, id, dbg)
208
+ sleep_for(1)
209
+ handle.flash(5)
210
+ return handle
211
+ end
212
+
213
+ # :category: GUI
214
+ def get_resize_handle_by_class(element, strg, dbg=nil)
215
+ handle = get_div_by_class(element, strg, dbg)
216
+ sleep_for(0.5)
217
+ handle.flash(5)
218
+ return handle
219
+ end
220
+
221
+ # :category: GUI
222
+ def get_element_coordinates(browser, element, dbg=nil)
223
+ bx, by, bw, bh = get_browser_coord(browser, dbg)
224
+ if @browserAbbrev == 'IE'
225
+ x_hack = @horizontal_hack_ie
226
+ y_hack = @vertical_hack_ie
227
+ elsif @browserAbbrev == 'FF'
228
+ x_hack = @horizontal_hack_ff
229
+ y_hack = @vertical_hack_ff
230
+ end
231
+ sleep_for(1)
232
+ w, h = element.dimensions.to_a
233
+ xc, yc = element.client_offset.to_a
234
+ # xcc, ycc = element.client_center.to_a
235
+ xcc = xc + w/2
236
+ ycc = yc + h/2
237
+ # screen offset:
238
+ xs = bx + x_hack + xc - 1
239
+ ys = by + y_hack + yc - 1
240
+ # screen center:
241
+ xsc = xs + w/2
242
+ ysc = ys + h/2
243
+ xslr = xs + w
244
+ yslr = ys + h
245
+ if dbg
246
+ debug_to_log(
247
+ "\n\t\tElement: #{element.inspect}"+
248
+ "\n\t\tbrowser screen offset: x: #{bx} y: #{by}"+
249
+ "\n\t\t dimensions: x: #{w} y: #{h}"+
250
+ "\n\t\t client offset x: #{xc} y: #{yc}"+
251
+ "\n\t\t screen offset x: #{xs} y: #{ys}"+
252
+ "\n\t\t client center x: #{xcc} y: #{ycc}"+
253
+ "\n\t\t screen center x: #{xsc} y: #{ysc}"+
254
+ "\n\t\t screen lower right x: #{xslr} y: #{yslr}")
255
+ end
256
+ [w, h, xs, ys, xsc, ysc, xslr, yslr]
257
+ end
258
+
259
+ def adjust_dimensions_by_percent(w, h, p, returnnew=nil)
260
+ p += 100
261
+ nw = (w * (p/100.0)).to_i
262
+ nh = (h * (p/100.0)).to_i
263
+ deltaw = nw - w
264
+ deltah = nh - h
265
+ if returnnew
266
+ [deltaw, deltah, nw, nh]
267
+ else
268
+ [deltaw, deltah]
269
+ end
270
+ end
271
+
272
+ def get_browser_coord(browser=nil, dbg=nil)
273
+ browser = @myBrowser if not browser
274
+ title = browser.title
275
+ x = @ai.WinGetPosX(title)
276
+ y = @ai.WinGetPosY(title)
277
+ w = @ai.WinGetPosWidth(title)
278
+ h = @ai.WinGetPosHeight(title)
279
+ if dbg
280
+ debug_to_log("\n\t\tBrowser #{browser.inspect}\n"+
281
+ "\t\tdimensions: x: #{w} y: #{h}"+
282
+ "\t\tscreen offset x: #{x} y: #{y}")
283
+ end
284
+ [x, y, w, h]
285
+ end
286
+
287
+ def drag_and_drop_div(browser, how, what, delta_x, delta_y, desc = '')
288
+ #TODO: webdriver
289
+ #TODO: assumes element is div
290
+ msg = "Drag and drop element :#{how}=>#{what} by x=>#{delta_x} y=>#{delta_y}."
291
+ msg << " #{desc}" if desc.length > 0
292
+ drag_me = browser.div(how, what)
293
+ drag_me.drag_and_drop_by(delta_x, delta_y)
294
+ passed_to_log(msg)
295
+ true
296
+ rescue
297
+ failed_to_log(unable_to)
298
+ end
299
+
300
+ def drag_and_drop(x1, y1, dx, dy, speed=nil)
301
+ speed = 10 if not speed
302
+ x2 = x1 + dx
303
+ y2 = y1 + dy
304
+ debug_to_log("drag_and_drop: start: [#{x1}, #{y1}] end: [#{x2}, #{y2}]")
305
+
306
+ @ai.MouseMove(x1, y1, speed)
307
+ @ai.MouseClick("primary", x1, y1)
308
+ sleep_for(0.5)
309
+ @ai.MouseClick("primary", x1, y1)
310
+ sleep_for(0.5)
311
+ @ai.MouseClickDrag("primary", x1, y1, x2, y2, speed)
312
+ end
313
+
314
+ def drag_and_drop_element(browser, element, dx, dy, speed = nil)
315
+ speed = 10 if not speed
316
+ w1, h1, x1, y1, xc1, yc1, xlr1, ylr1 = get_element_coordinates(browser, element, true)
317
+ msg = "Move #{element} by [#{dx}, #{dy}] from center[#{xc1}, #{yc1}] "
318
+ newxc = xc1 + dx
319
+ newyc = yc1 + dy
320
+ msg << "to center[[#{newxc}, #{newyc}]"
321
+ sleep_for(0.5)
322
+
323
+ drag_and_drop(xc1, yc1, dx, dy)
324
+
325
+ sleep_for(1)
326
+ w2, h2, x2, y2, xc2, yc2, xlr2, ylr2 = get_element_coordinates(browser, element, true)
327
+
328
+ # TODO This adjustment is adhoc and empirical. Needs to be derived more rigorously
329
+ xcerr = xc2 - xc1
330
+ ycerr = yc2 - yc1
331
+
332
+ debug_to_log("\n" +
333
+ "\t\t xc1: #{xc1}\n" +
334
+ "\t\t yc1: #{yc1}\n" +
335
+ "\t\t xc2: #{xc2}\n" +
336
+ "\t\t yc2: #{yc2}\n" +
337
+ "\t\t xcerr: #{xlrerr}\n" +
338
+ "\t\t ycerr: #{ylrerr}\n" +
339
+ "\t\t x tol: #{@x_tolerance}\n" +
340
+ "\t\t y tol: #{@y_tolerance}\n"
341
+ )
342
+
343
+ #TODO Add check that window _was_ resized.
344
+ x_ok, x_msg = validate_drag_drop(xcerr, @x_tolerance, newxc, xc2)
345
+ y_ok, y_msg = validate_drag_drop(ycerr, @y_tolerance, newyc, yc2)
346
+ msg = msg + "x: #{x_msg}, y: #{y_msg}"
347
+
348
+ if x_ok and y_ok
349
+ passed_to_log(msg)
350
+ else
351
+ failed_to_log(msg)
352
+ end
353
+ sleep_for(1)
354
+ rescue
355
+ failed_to_log("Unable to validate drag and drop. #{$!} (#{__LINE__})")
356
+ sleep_for(1)
357
+ end
358
+
359
+ def right_click(element)
360
+ x = element.left_edge_absolute + 2
361
+ y = element.top_edge_absolute + 2
362
+ @ai.MouseClick("secondary", x, y)
363
+ end
364
+
365
+ def left_click(element)
366
+ x = element.left_edge_absolute + 2
367
+ y = element.top_edge_absolute + 2
368
+ @ai.MouseClick("primary", x, y)
369
+ end
370
+
371
+ def screen_offset(element, browser=nil)
372
+ bx, by, bw, bh = get_browser_coord(browser)
373
+ ex = element.left_edge
374
+ ey = element.top_edge
375
+ [bx + ex, by + ey]
376
+ end
377
+
378
+ def screen_center(element, browser=nil)
379
+ bx, by, bw, bh = get_browser_coord(browser)
380
+ w, h = element.dimensions.to_a
381
+ cx = bx + w/2
382
+ cy = by + h/2
383
+ [cx, cy]
384
+ end
385
+
386
+ def screen_lower_right(element, browser=nil)
387
+ bx, by, bw, bh = get_browser_coord(browser)
388
+ w, h = element.dimensions.to_a
389
+ [bx + w, by + h]
390
+ end
391
+
392
+ def verify_resize(d, err, tol, min, act)
393
+ ary = [false, "failed, actual #{act} err #{err}"]
394
+ if err == 0
395
+ ary = [true, 'succeeded ']
396
+ #TODO need to find way to calculate this adjustment
397
+ elsif d <= min + 4
398
+ ary = [true, "reached minimum (#{min}) "]
399
+ elsif err.abs <= tol
400
+ ary = [true, "within tolerance (+-#{tol}px) "]
401
+ end
402
+ ary
403
+ end
404
+
405
+ alias validate_move verify_resize
406
+ alias validate_resize verify_resize
407
+
408
+ def validate_drag_drop(err, tol, exp, act)
409
+ ary = [false, "failed, expected: #{exp}, actual: #{act}, err: #{err}"]
410
+ if err == 0
411
+ ary = [true, 'succeeded ']
412
+ elsif err.abs <= tol
413
+ ary = [true, "within tolerance (+-#{tol}px) "]
414
+ end
415
+ ary
416
+ end
417
+
418
+ end
419
+ end
420
+ end
421
+