awetestlib 0.1.28 → 0.1.29pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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