awetestlib 0.1.2 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/README.md +55 -0
  2. data/awetestlib.windows.gemspec +1 -1
  3. data/awetestlib_osx.gemspec +1 -0
  4. data/bin/AutoItX3.dll +0 -0
  5. data/bin/awetestlib +23 -3
  6. data/bin/awetestlib-helpers.rb +39 -0
  7. data/bin/awetestlib-netbeans-setup.rb +39 -0
  8. data/bin/awetestlib-regression-setup.rb +16 -0
  9. data/bin/awetestlib-rubymine-setup.rb +33 -0
  10. data/images/logo.png +0 -0
  11. data/lib/awetestlib.rb +4 -4
  12. data/lib/awetestlib/html_report.rb +171 -0
  13. data/lib/{regression → awetestlib}/logging.rb +13 -46
  14. data/lib/awetestlib/regression/browser.rb +1233 -0
  15. data/lib/awetestlib/regression/drag_and_drop.rb +379 -0
  16. data/lib/awetestlib/regression/find.rb +431 -0
  17. data/lib/awetestlib/regression/legacy.rb +45 -0
  18. data/lib/awetestlib/regression/page_data.rb +190 -0
  19. data/lib/awetestlib/regression/runner.rb +307 -0
  20. data/lib/awetestlib/regression/tables.rb +491 -0
  21. data/lib/awetestlib/regression/user_input.rb +1256 -0
  22. data/lib/awetestlib/regression/utilities.rb +895 -0
  23. data/lib/awetestlib/regression/validations.rb +1184 -0
  24. data/lib/awetestlib/regression/waits.rb +391 -0
  25. data/lib/awetestlib/runner.rb +16 -0
  26. data/lib/version.rb +2 -2
  27. data/setup_samples/sample_netbeans/demo.rb +86 -0
  28. data/setup_samples/sample_netbeans/nbproject/configs/Demo.properties +2 -0
  29. data/setup_samples/sample_netbeans/nbproject/private/config.properties +1 -0
  30. data/setup_samples/sample_netbeans/nbproject/private/configs/Demo.properties +1 -0
  31. data/setup_samples/sample_netbeans/nbproject/private/private.properties +2 -0
  32. data/setup_samples/sample_netbeans/nbproject/project.properties +5 -0
  33. data/setup_samples/sample_netbeans/nbproject/project.xml +13 -0
  34. data/setup_samples/sample_rubymine/.idea/.name +1 -0
  35. data/setup_samples/sample_rubymine/.idea/encodings.xml +5 -0
  36. data/setup_samples/sample_rubymine/.idea/misc.xml +5 -0
  37. data/setup_samples/sample_rubymine/.idea/modules.xml +9 -0
  38. data/setup_samples/sample_rubymine/.idea/sample_rubymine.iml +9 -0
  39. data/setup_samples/sample_rubymine/.idea/scopes/scope_settings.xml +5 -0
  40. data/setup_samples/sample_rubymine/.idea/vcs.xml +7 -0
  41. data/setup_samples/sample_rubymine/.idea/workspace.xml +213 -0
  42. data/setup_samples/sample_rubymine/demo.rb +86 -0
  43. metadata +64 -17
  44. data/lib/regression/browser.rb +0 -1259
  45. data/lib/regression/drag_and_drop.rb +0 -374
  46. data/lib/regression/find.rb +0 -426
  47. data/lib/regression/legacy.rb +0 -40
  48. data/lib/regression/page_data.rb +0 -185
  49. data/lib/regression/runner.rb +0 -278
  50. data/lib/regression/tables.rb +0 -486
  51. data/lib/regression/user_input.rb +0 -1255
  52. data/lib/regression/utilities.rb +0 -891
  53. data/lib/regression/validations.rb +0 -1179
  54. 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