awetestlib 0.0.3-x86-mingw32 → 0.1.0-x86-mingw32

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