awetestlib 0.1.29pre3 → 0.1.29pre4

Sign up to get free protection for your applications and to get access to all the features.
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
+