awetestlib 0.1.3-x86-mingw32 → 0.1.5-x86-mingw32

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 (50) hide show
  1. data/awetestlib.windows.gemspec +1 -1
  2. data/bin/awetestlib +11 -4
  3. data/bin/awetestlib-helpers.rb +28 -1
  4. data/bin/awetestlib-netbeans-setup.rb +39 -0
  5. data/bin/awetestlib-rubymine-setup.rb +33 -0
  6. data/images/logo.png +0 -0
  7. data/lib/awetestlib/html_report.rb +171 -0
  8. data/lib/{regression → awetestlib}/logging.rb +10 -43
  9. data/lib/awetestlib/regression/browser.rb +1233 -0
  10. data/lib/awetestlib/regression/drag_and_drop.rb +379 -0
  11. data/lib/awetestlib/regression/find.rb +431 -0
  12. data/lib/awetestlib/regression/legacy.rb +45 -0
  13. data/lib/awetestlib/regression/page_data.rb +190 -0
  14. data/lib/awetestlib/regression/runner.rb +306 -0
  15. data/lib/awetestlib/regression/tables.rb +491 -0
  16. data/lib/awetestlib/regression/user_input.rb +1256 -0
  17. data/lib/awetestlib/regression/utilities.rb +895 -0
  18. data/lib/awetestlib/regression/validations.rb +1184 -0
  19. data/lib/awetestlib/regression/waits.rb +391 -0
  20. data/lib/awetestlib/runner.rb +16 -0
  21. data/lib/awetestlib.rb +4 -4
  22. data/lib/version.rb +2 -2
  23. data/setup_samples/sample_netbeans/demo.rb +86 -0
  24. data/setup_samples/sample_netbeans/nbproject/configs/Demo.properties +2 -0
  25. data/setup_samples/sample_netbeans/nbproject/private/config.properties +1 -0
  26. data/setup_samples/sample_netbeans/nbproject/private/configs/Demo.properties +1 -0
  27. data/setup_samples/sample_netbeans/nbproject/private/private.properties +2 -0
  28. data/setup_samples/sample_netbeans/nbproject/project.properties +5 -0
  29. data/setup_samples/sample_netbeans/nbproject/project.xml +13 -0
  30. data/setup_samples/sample_rubymine/.idea/.name +1 -0
  31. data/setup_samples/sample_rubymine/.idea/encodings.xml +5 -0
  32. data/setup_samples/sample_rubymine/.idea/misc.xml +5 -0
  33. data/setup_samples/sample_rubymine/.idea/modules.xml +9 -0
  34. data/setup_samples/sample_rubymine/.idea/sample_rubymine.iml +9 -0
  35. data/setup_samples/sample_rubymine/.idea/scopes/scope_settings.xml +5 -0
  36. data/setup_samples/sample_rubymine/.idea/vcs.xml +7 -0
  37. data/setup_samples/sample_rubymine/.idea/workspace.xml +213 -0
  38. data/setup_samples/sample_rubymine/demo.rb +86 -0
  39. metadata +44 -19
  40. data/lib/regression/browser.rb +0 -1259
  41. data/lib/regression/drag_and_drop.rb +0 -374
  42. data/lib/regression/find.rb +0 -426
  43. data/lib/regression/legacy.rb +0 -40
  44. data/lib/regression/page_data.rb +0 -185
  45. data/lib/regression/runner.rb +0 -278
  46. data/lib/regression/tables.rb +0 -486
  47. data/lib/regression/user_input.rb +0 -1255
  48. data/lib/regression/utilities.rb +0 -891
  49. data/lib/regression/validations.rb +0 -1179
  50. data/lib/regression/waits.rb +0 -387
@@ -0,0 +1,895 @@
1
+ module Awetestlib
2
+ module Regression
3
+ module Utilities
4
+
5
+ # Place holder to prevent method not found error in scripts
6
+ def set_script_variables
7
+ # TODO: replace with method_missing?
8
+ end
9
+
10
+ def setup
11
+ # if @os_sysname =~ /Windows.+Server\s+2003/
12
+ ## 'Microsoft(R) Windows(R) Server 2003, Enterprise Edition'
13
+ # @vertical_hack_ie = 110
14
+ # @vertical_hack_ff = 138
15
+ # @horizontal_hack_ie = 5
16
+ # @horizontal_hack_ff = 4
17
+ # elsif @os_sysname =~ /Windows XP Professional/
18
+ # 'Microsoft Windows XP Professional'
19
+ @vertical_hack_ie = 118
20
+ @vertical_hack_ff = 144
21
+ @horizontal_hack_ie = 5
22
+ @horizontal_hack_ff = 4
23
+ #end
24
+
25
+ @settings_display_ids = Hash[
26
+ "Currency" => "row-currencyName",
27
+ "Description" => "row-description",
28
+ "Tx Date" => "row-fmtDate",
29
+ "Total" => "row-amount",
30
+ "[currencyCode]" => "row-currencyCode",
31
+ "Date in Millis" => "row-dateInMilliseconds",
32
+ ]
33
+ @column_data_display_ids = Hash[
34
+ "Currency" => "yui-dt0-th-currencyName",
35
+ "Description" => "yui-dt0-th-description",
36
+ "Tx Date" => "yui-dt0-th-fmtDate",
37
+ "Total" => "yui-dt0-th-fmtDate",
38
+ "[currencyCode]" => "yui-dt0-th-currencyCode",
39
+ "Date in Millis" => "yui-dt0-th-dateInMilliseconds",
40
+ ]
41
+ @settings_panel_index = 0
42
+ @x_tolerance = 4
43
+ @y_tolerance = 4
44
+ end
45
+
46
+ def get_trace(lnbr)
47
+ callertrace = "\nCaller trace: (#{lnbr})\n"
48
+ Kernel.caller.each_index do |x|
49
+ callertrace << ' >> ' + Kernel.caller[x].to_s + "\n"
50
+ end
51
+ callertrace
52
+ end
53
+
54
+ alias dump_caller get_trace
55
+
56
+ def get_mdyy(t = Time.now)
57
+ "#{t.month}/#{t.day}/#{t.year}"
58
+ end
59
+
60
+ def get_prefix(strg, offset)
61
+ a_slice = strg.slice(0, offset)
62
+ a_slice.downcase
63
+ end
64
+
65
+ def get_timestamp(format = 'long', offset = nil, offset_unit = :years)
66
+ t = DateTime.now
67
+ if offset
68
+ t = t.advance(offset_unit => offset)
69
+ end
70
+ case format
71
+ when 'dateonly'
72
+ t.strftime("%m/%d/%Y")
73
+ when 'condensed'
74
+ t.strftime("%Y%m%d%H%M")
75
+ when 'condensed_seconds'
76
+ t.strftime("%Y%m%d%H%M%S")
77
+ when 'long'
78
+ t.strftime("%m/%d/%Y %I:%M %p")
79
+ when 'mdyy'
80
+ get_mdyy(t)
81
+ when 'm/d/y'
82
+ get_mdyy(t)
83
+ else
84
+ Time.now.strftime("%m/%d/%Y %H:%M:%S")
85
+ end
86
+ end
87
+
88
+ def calc_index(index, every = 1)
89
+ (index / every) + (every - 1)
90
+ end
91
+
92
+ def get_variables(file, login = :role, dbg = true)
93
+ debug_to_log("#{__method__}: file = #{file}")
94
+ debug_to_log("#{__method__}: role = #{login}")
95
+
96
+ @var = Hash.new
97
+ workbook = Excel.new(file)
98
+ data_index = find_sheet_with_name(workbook, 'Data')
99
+ workbook.default_sheet = workbook.sheets[data_index]
100
+ var_col = 0
101
+
102
+ 2.upto(workbook.last_column) do |col|
103
+ scriptName = workbook.cell(1, col)
104
+ if scriptName == @myName
105
+ var_col = col
106
+ break
107
+ end
108
+ end
109
+
110
+ 2.upto(workbook.last_row) do |line|
111
+ name = workbook.cell(line, 'A')
112
+ value = workbook.cell(line, var_col).to_s.strip
113
+ @var[name] = value
114
+ end
115
+
116
+ @var.keys.sort.each do |name|
117
+ message_tolog("@var #{name}: '#{@var[name]}'")
118
+ end if dbg
119
+
120
+ @login = Hash.new
121
+ login_col = 0
122
+ role_col = 0
123
+ userid_col = 0
124
+ password_col = 0
125
+ url_col = 0
126
+ name_col = 0
127
+ role_index = find_sheet_with_name(workbook, 'Login')
128
+ if role_index >= 0
129
+ workbook.default_sheet = workbook.sheets[role_index]
130
+
131
+ 1.upto(workbook.last_column) do |col|
132
+ a_cell = workbook.cell(1, col)
133
+ case a_cell
134
+ when @myName
135
+ login_col = col
136
+ break
137
+ when 'role'
138
+ role_col = col
139
+ when 'userid'
140
+ userid_col = col
141
+ when 'password'
142
+ password_col = col
143
+ when 'url'
144
+ url_col = col
145
+ when 'name'
146
+ name_col = col
147
+ end
148
+ end
149
+
150
+ 2.upto(workbook.last_row) do |line|
151
+ role = workbook.cell(line, role_col)
152
+ userid = workbook.cell(line, userid_col)
153
+ password = workbook.cell(line, password_col)
154
+ url = workbook.cell(line, url_col)
155
+ username = workbook.cell(line, name_col)
156
+ enabled = workbook.cell(line, login_col).to_s
157
+
158
+ case login
159
+ when :id
160
+ key = userid
161
+ when :role
162
+ key = role
163
+ else
164
+ key = role
165
+ end
166
+
167
+ @login[key] = Hash.new
168
+ @login[key]['role'] = role
169
+ @login[key]['userid'] = userid
170
+ @login[key]['password'] = password
171
+ @login[key]['url'] = url
172
+ @login[key]['name'] = username
173
+ @login[key]['enabled'] = enabled
174
+
175
+ end
176
+
177
+ @login.keys.sort.each do |key|
178
+ message_tolog("@login (by #{login}): #{key}=>'#{@login[key].to_yaml}'")
179
+ end if dbg
180
+ end
181
+
182
+ rescue
183
+ fatal_to_log("#{__method__}: '#{$!}'")
184
+ end
185
+
186
+ def translate_var_list(key)
187
+ if @var[key] and @var[key].length > 0
188
+ list = @var[key].dup
189
+ unless list =~ /^\[.+\]$/
190
+ list = "[#{list}]"
191
+ end
192
+ eval(list)
193
+ end
194
+ rescue
195
+ failed_to_log("#{__method__}: '#{$!}'")
196
+ end
197
+
198
+ def grab_window_list(strg)
199
+ @ai.AutoItSetOption("WinTitleMatchMode", 2)
200
+ list = @ai.WinList(strg)
201
+ stuff = ''
202
+ names = list[0]
203
+ handles = list[1]
204
+ max = names.length - 1
205
+ rng = Range.new(0, max)
206
+ rng.each do |idx|
207
+ window_handle = "[HANDLE:#{handles[idx]}]"
208
+ full_text = @ai.WinGetText(window_handle)
209
+ stuff << "[#{handles[idx]}]=>#{names[idx]}=>'#{full_text}'\n"
210
+ end
211
+ debug_to_log("\n#{stuff}")
212
+ @ai.AutoItSetOption("WinTitleMatchMode", 1)
213
+ stuff
214
+ end
215
+
216
+ def debug_call_list(msg)
217
+ call_array = get_call_array
218
+ debug_to_log("#{msg}\n#{dump_array(call_array)}")
219
+ end
220
+
221
+ def sec2hms(s)
222
+ Time.at(s.to_i).gmtime.strftime('%H:%M:%S')
223
+ end
224
+
225
+ def close_log(scriptName, lnbr = '')
226
+ cmplTS = Time.now.to_f.to_s
227
+ puts ("#{scriptName} finished. Closing log. #{lnbr.to_s}")
228
+ passed_to_log("#{scriptName} run complete [#{cmplTS}]")
229
+ @myLog.close()
230
+ sleep(2)
231
+ end
232
+
233
+ protected :close_log
234
+
235
+ def find_sheet_with_name(workbook, sheet_name)
236
+ sheets = workbook.sheets
237
+ idx = 0
238
+ found = false
239
+ sheets.each do |s|
240
+ if s == sheet_name
241
+ found = true
242
+ break
243
+ end
244
+ idx += 1
245
+ end
246
+ if found
247
+ idx
248
+ else
249
+ -1
250
+ end
251
+ end
252
+
253
+ def nice_array(arr, space_to_underscore = false)
254
+ new_arr = Array.new
255
+ if space_to_underscore
256
+ arr.each do |nty|
257
+ new_arr << nty.gsub(/\s/, '_')
258
+ end
259
+ else
260
+ new_arr = arr
261
+ end
262
+ "['#{new_arr.join("','")}']"
263
+ end
264
+
265
+ def string_count_in_string(strg, substrg)
266
+ count = strg.scan(substrg).length
267
+ count
268
+ end
269
+
270
+ def rescue_me(e, me = nil, what = nil, where = nil, who = nil)
271
+ #TODO: these are rescues from exceptions raised in Watir/Firewatir
272
+ debug_to_log("#{__method__}: Begin rescue")
273
+ ok = false
274
+ begin
275
+ gaak = who.inspect
276
+ located = gaak =~ /located=true/i
277
+ rescue
278
+ debug_to_log("#{__method__}: gaak: '#{gaak}'")
279
+ end
280
+ msg = e.message
281
+ debug_to_log("#{__method__}: msg = #{msg}")
282
+ if msg =~ /undefined method\s+.join.\s+for/i # firewatir to_s implementation error
283
+ ok = true
284
+ elsif msg =~ /undefined method\s+.match.\s+for.+WIN32OLERuntimeError/i # watir and firewatir
285
+ ok = true
286
+ elsif msg =~ /undefined method\s+.match.\s+for.+UnknownObjectException/i # watir
287
+ ok = true
288
+ elsif msg =~ /window\.getBrowser is not a function/i # firewatir
289
+ ok = true
290
+ elsif msg =~ /WIN32OLERuntimeError/i # watir
291
+ ok = true
292
+ elsif msg =~ /undefined method\s+.match.\s+for/i # watir
293
+ ok = true
294
+ elsif msg =~ /wrong number of arguments \(1 for 0\)/i
295
+ ok = true
296
+ elsif (msg =~ /unable to locate element/i)
297
+ if located
298
+ ok = true
299
+ elsif where == 'Watir::Div'
300
+ ok = true
301
+ end
302
+ elsif (msg =~ /HRESULT error code:0x80070005/)
303
+ ok = true
304
+ #elsif msg =~ /missing\s+\;\s+before statement/
305
+ # ok = true
306
+ end
307
+ if ok
308
+ debug_to_log("#{__method__}: RESCUED: \n#{who.to_yaml}=> #{what} in #{me}()\n=> '#{$!}'")
309
+ debug_to_log("#{__method__}: #{who.inspect}") if who
310
+ debug_to_log("#{__method__}: #{where.inspect}")
311
+ debug_to_log("#{__method__}: #{get_callers(6, true)}")
312
+ else
313
+ debug_to_log("#{__method__}: NO RESCUE: #{e.message}")
314
+ debug_to_log("#{__method__}: NO RESCUE: \n#{get_callers(6, true)}")
315
+ end
316
+ debug_to_log("#{__method__}: Exit")
317
+ ok
318
+ end
319
+
320
+ def get_caller_line
321
+ last_caller = get_callers[0]
322
+ line = last_caller.split(':', 3)[1]
323
+ line
324
+ end
325
+
326
+ def get_call_list(depth = 9, dbg = false)
327
+ myList = []
328
+ call_list = Kernel.caller
329
+ puts call_list if dbg
330
+ call_list.each_index do |x|
331
+ myCaller = call_list[x].to_s
332
+ break if x > depth or myCaller =~ /:in .run.$/
333
+ myCaller =~ /([\(\)\w_\_\-\.]+\:\d+\:?.*?)$/
334
+ myList << "[#{$1.gsub(/eval/, @myName)}] "
335
+ end
336
+ myList
337
+ end
338
+
339
+ alias get_callers get_call_list
340
+
341
+ def get_call_list_new(depth = 9, dbg = false)
342
+ myList = []
343
+ call_list = Kernel.caller
344
+ puts call_list if dbg
345
+ call_list.each_index do |x|
346
+ myCaller = call_list[x].to_s
347
+ break if x > depth or myCaller =~ /:in .run.$/
348
+ if myCaller.include? @myName
349
+ myCaller =~ /([\(\)\w_\_\-\.]+\:\d+\:?.*?)$/
350
+ myList << "[#{$1.gsub(/eval/, @myName)}] "
351
+ break
352
+ end
353
+ end
354
+ if @projName
355
+ call_list.each_index do |x|
356
+ myCaller = call_list[x].to_s
357
+ break if x > depth or myCaller =~ /:in .run.$/
358
+ if myCaller.include? @projName
359
+ myCaller =~ /([\(\)\w_\_\-\.]+\:\d+\:?.*?)$/
360
+ myList << "[#{$1.gsub(/eval/, @projName)}] "
361
+ break
362
+ end
363
+ end
364
+ end
365
+ myList
366
+ end
367
+
368
+ def get_call_array(depth = 9)
369
+ arr = []
370
+ call_list = Kernel.caller
371
+ call_list.each_index do |x|
372
+ myCaller = call_list[x].to_s
373
+ break if x > depth or myCaller =~ /:in .run.$/
374
+ myCaller =~ /([\(\)\w_\_\-\.]+\:\d+\:?.*?)$/
375
+ arr << $1.gsub(/eval/, @myName)
376
+ end
377
+ arr
378
+ end
379
+
380
+ def get_debug_list(dbg = false)
381
+ calls = get_call_array(10)
382
+ puts "#{calls.to_yaml}" if dbg
383
+ arr = []
384
+ calls.each_index do |ix|
385
+ if ix > 1 # skip this method and the logging method
386
+ arr << calls[ix]
387
+ end
388
+ end
389
+ puts "#{arr.to_yaml}" if dbg
390
+ if arr.length > 0
391
+ list = 'TRACE:'
392
+ arr.reverse.each { |l| list << "=>#{l}" }
393
+ " [[#{list}]]"
394
+ else
395
+ nil
396
+ end
397
+ end
398
+
399
+ def dump_array(arr, space_to_underscore = false)
400
+ dump = " #{arr.inspect}\n"
401
+ arr.each_index do |x|
402
+ value = arr[x].to_s
403
+ value.gsub!(/\s/, '_') if space_to_underscore
404
+ dump << " #{x.to_s.rjust(5)}>> '#{arr[x].to_s}'\n"
405
+ end
406
+ dump
407
+ end
408
+
409
+ def dump_ole_methods(ole)
410
+ rtrn = ''
411
+ ole.ole_methods.each do |m|
412
+ prms = ''
413
+ m.params.each do |p|
414
+ prms << "#{p}, "
415
+ end
416
+ rtrn << "#{m.name}(#{prms.chop.chop})\n"
417
+ end
418
+ rtrn
419
+ end
420
+
421
+ def dump_ole_get_methods(ole)
422
+ rtrn = ''
423
+ ole.ole_get_methods.each do |m|
424
+ prms = ''
425
+ m.params.each do |p|
426
+ prms << "#{p}, "
427
+ end
428
+ rtrn << "#{m.name}(#{prms.chop.chop})\n"
429
+ end
430
+ rtrn
431
+ end
432
+
433
+ def dump_ole_help(ole)
434
+ rtrn = ''
435
+ ole.ole_obj_help.each do |m|
436
+ prms = ''
437
+ m.params.each do |p|
438
+ prms << "#{p}, "
439
+ end
440
+ rtrn << "#{m.name}(#{prms.chop.chop})\n"
441
+ end
442
+ rtrn
443
+ end
444
+
445
+ def dump_select_list_options(element)
446
+ msg = "#{element.inspect}"
447
+ options = element.options
448
+ cnt = 1
449
+ options.each do |o|
450
+ msg << "\n\t#{cnt}:\t'#{o}"
451
+ cnt += 1
452
+ end
453
+ debug_to_log(msg)
454
+ end
455
+
456
+ def dump_all_tables(browser, to_report = false)
457
+ tables = browser.tables
458
+ msg = ''
459
+ tbl_cnt = 0
460
+ tables.each do |tbl|
461
+ tbl_cnt += 1
462
+ row_cnt = 0
463
+ msg <<"\n=================\ntable: #{tbl_cnt}\n=================\n#{tbl}\ntext:\n#{tbl.text}"
464
+ tbl.rows.each do |row|
465
+ row_cnt += 1
466
+ cell_cnt = 0
467
+ msg <<"\n=================\ntable: #{tbl_cnt} row: #{row_cnt}\n#{row.inspect}\n#{row}\ntext:'#{row.text}'"
468
+ row.each do |cell|
469
+ cell_cnt += 1
470
+ msg <<"\ncell: #{cell_cnt}\n#{cell.inspect}\n#{row}\ntext: '#{cell.text}'"
471
+ end
472
+ end
473
+ end
474
+ if to_report
475
+ debug_to_report(msg)
476
+ else
477
+ debug_to_log(msg)
478
+ end
479
+ end
480
+
481
+ def dump_table_and_rows(table, to_report = false)
482
+ msg = "\n=================\ntable\n=================\nn#{table}\n#{table.to_yaml}\nrows:"
483
+ cnt = 0
484
+ table.rows.each do |r|
485
+ cnt += 1
486
+ msg << "\n#{cnt}: #{r.text}"
487
+ end
488
+ msg << "\n=================\n================="
489
+ if to_report
490
+ debug_to_report(msg)
491
+ else
492
+ debug_to_log(msg)
493
+ end
494
+ end
495
+
496
+ def dump_table_rows_and_cells(tbl)
497
+ msg = ''
498
+ row_cnt = 0
499
+ msg <<"\n=================\ntable: #{tbl.inspect}\n=================\n#{tbl}\ntext:\n#{tbl.text}"
500
+ tbl.rows.each do |row|
501
+ row_cnt += 1
502
+ cell_cnt = 0
503
+ msg <<"\n=================\nrow: #{row_cnt}\n#{row.inspect}\n#{row}\ntext:'#{row.text}'"
504
+ row.each do |cell|
505
+ cell_cnt += 1
506
+ msg <<"\ncell: #{cell_cnt}\n#{cell.inspect}\n#{row}\ntext: '#{cell.text}'"
507
+ end
508
+ end
509
+ debug_to_log(msg)
510
+ end
511
+
512
+ alias dump_table_rows dump_table_rows_and_cells
513
+
514
+ def dump_row_cells(row)
515
+ msg = ''
516
+ cell_cnt = 0
517
+ msg <<"\n=================\nrow: #{row.inspect}\n#{row}\ntext:'#{row.text}'"
518
+ row.each do |cell|
519
+ cell_cnt += 1
520
+ msg <<"\ncell: #{cell_cnt}\n#{cell.inspect}\n#{row}\ntext: '#{cell.text}'"
521
+ end
522
+ debug_to_log(msg)
523
+ end
524
+
525
+ def parse_cookies(browser)
526
+ cookies = Hash.new
527
+ strg = browser.document.cookie
528
+ ary = strg.split(';')
529
+ ary.each do |c|
530
+ key, value = c.split('=')
531
+ cookies[key.lstrip] = value
532
+ end
533
+ cookies
534
+ end
535
+
536
+ def capture_screen(browser, ts)
537
+ browser.maximize
538
+ browser.bring_to_front
539
+ caller = get_caller
540
+ caller.match(/:(\d+):/)
541
+ lnbr = $1
542
+ path = "#{@myRoot}/screenshot/"
543
+ screenfile = "#{@myName}_#{@myRun.id}_#{lnbr.to_s}_#{ts.to_f.to_s}.scrsht.jpg"
544
+ info_to_log("path:#{path} screenfile:#{screenfile}")
545
+ screenSpec = '"' + path + screenfile + '"'
546
+ screenSpec.gsub!('/', '\\')
547
+ screen_capture(screenSpec)
548
+ screenfile
549
+ end
550
+
551
+ def pdf_to_text(file, noblank = true)
552
+ spec = file.sub(/\.pdf$/, '')
553
+ `pdftotext #{spec}.pdf`
554
+ file = File.new("#{spec}.txt")
555
+ text = []
556
+ file.readlines.each do |l|
557
+ l.chomp! if noblank
558
+ if l.length > 0
559
+ text << l
560
+ end
561
+ end
562
+ file.close
563
+ text
564
+ end
565
+
566
+ def flash_id(browser, strg, count)
567
+ msg = "Flash link id='#{strg}' #{count} times."
568
+ msg << " #{desc}" if desc.length > 0
569
+ browser.link(:id, strg).flash(count)
570
+ if validate(browser, @myName, __LINE__)
571
+ passed_to_log(msg)
572
+ true
573
+ end
574
+ rescue
575
+ failed_to_log("Unable to #{msg} '#{$!}'")
576
+ end
577
+
578
+ def flash(element, count = 4)
579
+ element.flash(count)
580
+ debug_to_log("'#{element.inspect}' flashed #{count} times.")
581
+ true
582
+ rescue
583
+ debug_to_log("Flash '#{element.inspect}' failed: '#{$!}' (#{__LINE__})")
584
+ end
585
+
586
+ def get_save_file_path(root, filename)
587
+ filespec = "#{root}/file/#{filename}"
588
+ filespec.gsub!('/', '\\')
589
+ end
590
+
591
+ def save_file_orig(filepath, desc = '', wait = WAIT)
592
+ # title = translate_popup_title(title)
593
+ @ai.WinWait("File Download", "", wait)
594
+ @ai.ControlFocus("File Download", "", "&Save")
595
+ sleep 1
596
+ @ai.ControlClick("File Download", "", "&Save", "left")
597
+ @ai.WinWait("Save As", "", wait)
598
+ sleep 1
599
+ @ai.ControlSend("Save As", "", "Edit1", filepath)
600
+ @ai.ControlClick("Save As", "", "&Save", "left")
601
+ sleep 1
602
+ @ai.WinWait("Download complete", "", wait)
603
+ @ai.ControlClick("Download complete", "", "Close")
604
+ end
605
+
606
+ #TODO This and save_file2 have to be combined somehow.
607
+ def save_file1(filepath, title = "File Download", desc = '', wait = WAIT)
608
+ title = translate_popup_title(title)
609
+ @ai.WinWait(title, '', wait)
610
+ @ai.WinActivate(title, '')
611
+ sleep 1
612
+ @ai.ControlFocus(title, "", "&Save")
613
+ sleep 3
614
+ @ai.ControlClick(title, "", "&Save", "primary")
615
+ sleep 2
616
+ @ai.ControlClick(title, "", "Save", "primary")
617
+
618
+ @ai.WinWait("Save As", "", wait)
619
+ sleep 1
620
+ @ai.ControlSend("Save As", "", "Edit1", filepath)
621
+ @ai.ControlFocus("Save As", "", "&Save")
622
+ @ai.ControlClick("Save As", "", "&Save", "primary")
623
+ @ai.ControlClick("Save As", "", "Save", "primary")
624
+
625
+ @ai.WinWait("Download complete", "", wait)
626
+ passed_to_log("Save file '#{filepath}' succeeded. #{desc}")
627
+ @ai.ControlClick("Download complete", "", "Close")
628
+ rescue
629
+ failed_to_log("Save file failed: #{desc} '#{$!}'. (#{__LINE__})")
630
+ end
631
+
632
+ def save_file2(filepath, title = "File Download - Security Warning", desc = '', wait = WAIT)
633
+ title = translate_popup_title(title)
634
+ sleep(1)
635
+ @ai.WinWait(title, '', wait)
636
+ dl_hndl = @ai.WinGetHandle(title, '')
637
+ dl_sv_hndl = @ai.ControlGetHandle(title, '', "&Save")
638
+ @ai.WinActivate(title, '')
639
+ sleep 1
640
+ @ai.ControlFocus(title, "", "&Save")
641
+ sleep 1
642
+ @ai.ControlFocus(title, "", "Save")
643
+ sleep 1
644
+ @ai.ControlClick(title, "", "&Save", "primary")
645
+ sleep 1
646
+ @ai.ControlClick(title, "", "Save", "primary")
647
+ sleep 1
648
+ w = WinClicker.new
649
+ w.clickButtonWithHandle(dl_sv_hndl)
650
+ sleep 1
651
+ w.clickWindowsButton_hwnd(dl_hndl, "Save")
652
+ sleep 1
653
+ w.clickWindowsButton_hwnd(dl_hndl, "&Save")
654
+
655
+ @ai.WinWait("Save As", "", wait)
656
+ sleep 1
657
+ @ai.ControlSend("Save As", "", "Edit1", filepath)
658
+ @ai.ControlFocus("Save As", "", "&Save")
659
+ @ai.ControlClick("Save As", "", "&Save", "primary")
660
+
661
+ @ai.WinWait("Download complete", "", wait)
662
+ passed_to_log("Save file '#{filepath}' succeeded. #{desc}")
663
+ @ai.ControlClick("Download complete", "", "Close")
664
+ rescue
665
+ failed_to_log("Save file failed: #{desc} '#{$!}'. (#{__LINE__})")
666
+ end
667
+
668
+ #method for handling save dialog
669
+ #use click_no_wait on the action that triggers the save dialog
670
+ def save_file(filepath, download_title = "File Download - Security Warning")
671
+ # TODO need version for Firefox
672
+ # TODO need to handle first character underline, e.g. 'Cancel' and '&Cancel'
673
+ download_title = translate_popup_title(download_title)
674
+ download_text = ''
675
+ download_control = "&Save"
676
+ saveas_title = 'Save As'
677
+ saveas_text = ''
678
+ saveas_control = "Edit1"
679
+ dnld_cmplt_title = "Download Complete"
680
+ dnld_cmplt_title = translate_popup_title(dnld_cmplt_title)
681
+ dnld_cmplt_text = ""
682
+ # save_title = ""
683
+ side = 'primary'
684
+ msgdl = "Window '#{download_title}':"
685
+ msgsa = "Window '#{saveas_title}':"
686
+ msgdc = "Window '#{dnld_cmplt_title}':"
687
+ begin
688
+ if @ai.WinWait(download_title, download_text, WAIT)
689
+ @ai.WinActivate(download_title, download_text)
690
+ if @ai.WinActive(download_title, download_text)
691
+ dl_title = @ai.WinGetTitle(download_title, download_text)
692
+ # dl_hndl = @ai.WinGetHandle(download_title, download_text)
693
+ # dl_text = @ai.WinGetText(download_title, download_text)
694
+ # dl_sv_hndl = @ai.ControlGetHandle(dl_title, '', download_control)
695
+ # dl_op_hndl = @ai.ControlGetHandle(dl_title, '', '&Open')
696
+ # dl_cn_hndl = @ai.ControlGetHandle(dl_title, '', 'Cancel')
697
+ debug_to_log("#{msgdl} activated. (#{__LINE__})")
698
+
699
+ if @ai.ControlFocus(dl_title, download_text, download_control)
700
+ debug_to_log("#{msgdl} focus gained. (#{__LINE__})")
701
+
702
+ @ai.Send("S")
703
+ # @ai.ControlSend(dl_Stitle, download_text, download_control, "{ENTER}")
704
+ sleep_for 1
705
+
706
+ if @ai.ControlClick(dl_title, download_text, download_control, side)
707
+ debug_to_log("#{msgdl} click succeeded on '#{download_control}'. (#{__LINE__})")
708
+
709
+ if @ai.WinWait(saveas_title, saveas_text, WAIT)
710
+ debug_to_log("#{msgsa} appeared. (#{__LINE__})")
711
+ sleep_for 1
712
+ if @ai.ControlSend(saveas_title, saveas_text, saveas_control, filepath)
713
+ debug_to_log("#{msgsa} controlsend of '#{saveas_control}' succeeded. (#{__LINE__})")
714
+
715
+ @ai.Send("S")
716
+ @ai.ControlSend(saveas_title, saveas_text, saveas_control, "{ENTER}")
717
+ sleep_for 1
718
+
719
+ if @ai.ControlClick(saveas_title, saveas_text, saveas_control, side)
720
+ passed_to_log("#{msgsa} click succeeded on '#{saveas_control}'. (#{__LINE__})")
721
+ if @ai.WinWait(dnld_cmplt_title, dnld_cmplt_text, WAIT)
722
+ debug_to_log("#{msgdc} appeared. (#{__LINE__})")
723
+ sleep_for 1
724
+ if @ai.ControlClick(dnld_cmplt_title, dnld_cmplt_text, "Close", side)
725
+ passed_to_log("Save file for #{filepath} succeeded.")
726
+ else
727
+ failed_to_log("#{msgdc} click failed on 'Close'. (#{__LINE__})")
728
+ end
729
+ else
730
+ failed_to_log("#{msgdc} did not appear after #{WAIT} seconds. (#{__LINE__})")
731
+ end
732
+ else
733
+ failed_to_log("#{msgsa} click failed on '#{saveas_control}'. (#{__LINE__})")
734
+ end
735
+ else
736
+ failed_to_log("#{msgsa} controlsend of '#{saveas_control}' failed. (#{__LINE__})")
737
+ end
738
+ else
739
+ failed_to_log("#{msgsa} did not appear after #{WAIT} seconds. (#{__LINE__})")
740
+ end
741
+ else
742
+ failed_to_log("#{msgdl} click failed on '#{download_control}'. (#{__LINE__})")
743
+ end
744
+ else
745
+ failed_to_log("#{msgdl} Unable to gain focus on control '#{dl_title}'. (#{__LINE__})")
746
+ end
747
+ else
748
+ failed_to_log("#{msgdl} Unable to activate. (#{__LINE__})")
749
+ end
750
+ else
751
+ failed_to_log("#{msgdl} did not appear after #{WAIT} seconds. (#{__LINE__})")
752
+ end
753
+ rescue
754
+ failed_to_log("Save file failed: '#{$!}'. (#{__LINE__})")
755
+ end
756
+ end
757
+
758
+ #method for cancelling Print window
759
+ # TODO need to handle 'Cancel' and '&Cancel' (first character underlined)
760
+ def close_print(title = 'Print', text = '', button = '&Cancel', side = 'left')
761
+ msg = "Popup: title=#{title} button='#{button}' text='#{text}' side='#{side}':"
762
+ if @ai.WinWait(title, text, WAIT)
763
+ passed_to_log("#{msg} found.")
764
+ @ai.WinActivate(title)
765
+ if @ai.WinActive(title, text)
766
+ passed_to_log("#{msg} activated.")
767
+ if @ai.ControlFocus(title, text, button)
768
+ passed_to_log("#{msg} focus attained.")
769
+ if @ai.ControlClick(title, text, button, side)
770
+ passed_to_log("#{msg} closed successfully.")
771
+ else
772
+ failed_to_log("#{msg} click failed on button (#{__LINE__})")
773
+ end
774
+ else
775
+ failed_to_log("#{msg} Unable to gain focus on button (#{__LINE__})")
776
+ end
777
+ else
778
+ failed_to_log("#{msg} Unable to activate (#{__LINE__})")
779
+ end
780
+ else
781
+ failed_to_log("#{msg} did not appear after #{WAIT} seconds. (#{__LINE__})")
782
+ end
783
+ rescue
784
+ failed_to_log("Close #{msg}: '#{$!}'. (#{__LINE__})")
785
+ end
786
+
787
+ #method for handling file download dialog
788
+ #use click_no_wait on the action that triggers the save dialog
789
+ # TODO need version for Firefox
790
+ # TODO need to handle 'Cancel' and '&Cancel' (first character underlined)
791
+ # TODO replace call to close_modal_ie with actual file download
792
+ def file_download(browser = nil)
793
+ title = 'File Download'
794
+ title = translate_popup_title(title)
795
+ text = ''
796
+ button = 'Cancel'
797
+ if @browserAbbrev == 'IE'
798
+ close_popup(title, button, text)
799
+ else
800
+
801
+ end
802
+ end
803
+
804
+ #method for handling file upload dialog
805
+ #use click_no_wait on the action that triggers the save dialog
806
+ # TODO need version for Firefox
807
+ def file_upload(filepath)
808
+ title = 'Choose File'
809
+ title = translate_popup_title(title)
810
+ text = ''
811
+ button = "&Open"
812
+ control = "Edit1"
813
+ side = 'primary'
814
+ msg = "Window title=#{title} button='#{button}' text='#{text}' side='#{side}':"
815
+ begin
816
+ if @ai.WinWait(title, text, WAIT)
817
+ passed_to_log("#{msg} found.")
818
+ @ai.WinActivate(title, text)
819
+ if @ai.WinActive(title, text)
820
+ passed_to_log("#{msg} activated.")
821
+ if @ai.ControlSend(title, text, control, filepath)
822
+ passed_to_log("#{msg} #{control} command sent.")
823
+ sleep_for 1
824
+ if @ai.ControlClick(title, text, button, "primary")
825
+ passed_to_log("#{msg} Upload of #{filepath} succeeded.")
826
+ else
827
+ failed_to_log("#{msg} Upload of #{filepath} failed. (#{__LINE__})")
828
+ end
829
+ else
830
+ failed_to_log("#{msg} Unable to select #{filepath}. (#{__LINE__})")
831
+ end
832
+ else
833
+ failed_to_log("#{msg} Unable to activate. (#{__LINE__})")
834
+ end
835
+ else
836
+ failed_to_log("#{msg} did not appear after #{WAIT} seconds. (#{__LINE__})")
837
+ end
838
+ rescue
839
+ failed_to_log("#{msg} Unable to upload: '#{$!}'. (#{__LINE__})")
840
+ end
841
+
842
+ end
843
+
844
+ def upload_file(data_path)
845
+ limit = 180 # .seconds
846
+ Timeout::timeout(limit) {
847
+ wait = 20
848
+ @ai.WinWait("Choose File to Upload", "", wait)
849
+ sleep 1
850
+ @ai.ControlSend("Choose File to Upload", "", "Edit1", data_path)
851
+ @ai.ControlClick("Choose File to Upload", "", "[CLASS:Button; INSTANCE:2]", "left")
852
+ sleep 4
853
+ #sleep 1
854
+ }
855
+ failed_to_log("Choose File to Upload not found after #{limit} '#{$!}'")
856
+ rescue Timeout::Error
857
+ failed_to_log("File Upload timeout after #{limit} '#{$!}'")
858
+ end
859
+
860
+ def focus_on_textfield_by_id(browser, strg, desc = '')
861
+ msg = "Set focus on textfield name='#{strg}' "
862
+ msg << " #{desc}" if desc.length > 0
863
+ tf = browser.text_field(:id, strg)
864
+ if validate(browser, @myName, __LINE__)
865
+ tf.focus
866
+ if validate(browser, @myName, __LINE__)
867
+ passed_to_log(msg)
868
+ true
869
+ end
870
+ end
871
+ rescue
872
+ failed_to_log("Unable to #{msg} '#{$!}'")
873
+ end
874
+
875
+ def flash_text(browser, strg, count, desc = '')
876
+ msg = "Flash link text='#{strg}' #{count} times."
877
+ msg << " #{desc}" if desc.length > 0
878
+ strgCnt = string_count_in_string(browser.text, strg)
879
+ if strgCnt > 0
880
+ browser.link(:text, strg).flash(count)
881
+ if validate(browser, @myName, __LINE__)
882
+ passed_to_log(msg)
883
+ true
884
+ end
885
+ else
886
+ failed_to_log("#{msg} Link not found.")
887
+ end
888
+ rescue
889
+ failed_to_log("Unable to #{msg} '#{$!}'")
890
+ end
891
+
892
+
893
+ end
894
+ end
895
+ end