awetestlib 0.1.28 → 0.1.29pre1

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