awetestlib 0.1.30-x86-mingw32 → 1.2.4-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +101 -41
  3. data/awetestlib.gemspec +36 -47
  4. data/awetestlib_osx.gemspec +24 -18
  5. data/awetestlib_windows.gemspec +46 -0
  6. data/bin/awetestlib +130 -111
  7. data/bin/awetestlib-driver-setup.rb +0 -2
  8. data/bin/awetestlib-helpers.rb +43 -30
  9. data/lib/awetestlib.rb +196 -20
  10. data/lib/awetestlib/command_line.rb +44 -0
  11. data/lib/awetestlib/html_report.rb +57 -50
  12. data/lib/awetestlib/logging.rb +242 -171
  13. data/lib/awetestlib/regression/awetest_dsl.rb +4240 -0
  14. data/lib/awetestlib/regression/browser.rb +514 -397
  15. data/lib/awetestlib/regression/date_and_time.rb +280 -0
  16. data/lib/awetestlib/regression/drag_and_drop.rb +24 -0
  17. data/lib/awetestlib/regression/find.rb +70 -43
  18. data/lib/awetestlib/regression/legacy.rb +1 -1
  19. data/lib/awetestlib/regression/mobile.rb +293 -0
  20. data/lib/awetestlib/regression/reporting.rb +298 -0
  21. data/lib/awetestlib/regression/runner.rb +156 -200
  22. data/lib/awetestlib/regression/tables.rb +117 -7
  23. data/lib/awetestlib/regression/test_data.rb +354 -0
  24. data/lib/awetestlib/regression/user_input.rb +179 -93
  25. data/lib/awetestlib/regression/utilities.rb +755 -286
  26. data/lib/awetestlib/regression/validations.rb +325 -115
  27. data/lib/awetestlib/regression/waits.rb +60 -133
  28. data/lib/awetestlib/runner.rb +5 -2
  29. data/lib/version.rb +11 -2
  30. data/setup_samples/sample_cucumber/features/step_definitions/predefined_steps.rb +109 -49
  31. data/setup_samples/sample_mobile_app/features/support/env.rb +1 -1
  32. data/test/google_search2.rb +7 -6
  33. data/test/popup_child_0.rb +13 -0
  34. data/test/popup_child_1.rb +33 -0
  35. data/test/watir_no_require.rb +13 -0
  36. data/test/watir_with_require.rb +16 -0
  37. data/test/zoho_exercise.rb +8 -8
  38. metadata +216 -303
  39. data/AwetestLib Instructions.rtf +0 -0
  40. data/awetestlib.windows.gemspec +0 -42
  41. data/lib/patches/README +0 -2
  42. data/lib/patches/firewatir.rb +0 -106
  43. data/lib/patches/watir.rb +0 -175
@@ -0,0 +1,4240 @@
1
+ module Awetestlib
2
+
3
+ module Logging
4
+
5
+ def where_am_i?(index = 2)
6
+ index = index ? index : 2
7
+ calls = get_call_list_new
8
+ log_message(DEBUG, "=== #{__LINE__}\n#{calls.to_yaml}\n===") if $debug
9
+ if calls[index]
10
+ where = calls[index].dup.to_s
11
+ here = where.gsub(/^\[/, '').gsub(/\]\s*$/, '')
12
+ else
13
+ here = 'unknown'
14
+ end
15
+ here
16
+ rescue
17
+ failed_to_log(unable_to)
18
+ end
19
+
20
+ end
21
+
22
+ module Regression
23
+
24
+ module Runner
25
+
26
+ def start
27
+ before_run
28
+ run
29
+ rescue Exception => e
30
+ failed_to_log(e.to_s, 3, e)
31
+ ensure
32
+ after_run
33
+ end
34
+
35
+ end
36
+
37
+ module TestData
38
+
39
+ def instantiate_style_list
40
+ @style_list =
41
+ ['-webkit-app-region', '-webkit-appearance', '-webkit-background-composite',
42
+ '-webkit-border-horizontal-spacing', '-webkit-border-vertical-spacing',
43
+ '-webkit-box-align', '-webkit-box-decoration-break', '-webkit-box-direction',
44
+ '-webkit-box-flex', '-webkit-box-flex-group', '-webkit-box-lines',
45
+ '-webkit-box-ordinal-group', '-webkit-box-orient', '-webkit-box-pack',
46
+ '-webkit-box-reflect', '-webkit-column-break-after', '-webkit-column-break-before',
47
+ '-webkit-column-break-inside', '-webkit-column-count', '-webkit-column-gap',
48
+ '-webkit-column-rule-color', '-webkit-column-rule-style', '-webkit-column-rule-width',
49
+ '-webkit-column-span', '-webkit-column-width', '-webkit-font-smoothing', '-webkit-highlight',
50
+ '-webkit-hyphenate-character', '-webkit-line-box-contain', '-webkit-line-break',
51
+ '-webkit-line-clamp', '-webkit-locale', '-webkit-margin-after-collapse',
52
+ '-webkit-margin-before-collapse', '-webkit-mask-box-image', '-webkit-mask-box-image-outset',
53
+ '-webkit-mask-box-image-repeat', '-webkit-mask-box-image-slice', '-webkit-mask-box-image-source',
54
+ '-webkit-mask-box-image-width', '-webkit-mask-clip', '-webkit-mask-composite',
55
+ '-webkit-mask-image', '-webkit-mask-origin', '-webkit-mask-position', '-webkit-mask-repeat',
56
+ '-webkit-mask-size', '-webkit-print-color-adjust', '-webkit-rtl-ordering',
57
+ '-webkit-tap-highlight-color', '-webkit-text-combine', '-webkit-text-decorations-in-effect',
58
+ '-webkit-text-emphasis-color', '-webkit-text-emphasis-position', '-webkit-text-emphasis-style',
59
+ '-webkit-text-fill-color', '-webkit-text-orientation', '-webkit-text-security',
60
+ '-webkit-text-stroke-color', '-webkit-text-stroke-width', '-webkit-user-drag',
61
+ '-webkit-user-modify', '-webkit-user-select', 'align-content', 'align-items', 'align-self',
62
+ 'alignment-baseline', 'animation-delay', 'animation-direction', 'animation-duration',
63
+ 'animation-fill-mode', 'animation-iteration-count', 'animation-name', 'animation-play-state',
64
+ 'animation-timing-function', 'backface-visibility', 'background-attachment', 'background-blend-mode',
65
+ 'background-clip', 'background-color', 'background-image', 'background-origin',
66
+ 'background-position', 'background-repeat', 'background-size', 'baseline-shift', 'border-bottom-color',
67
+ 'border-bottom-left-radius', 'border-bottom-right-radius', 'border-bottom-style', 'border-bottom-width',
68
+ 'border-collapse', '-webkit-border-image', 'border-image-outset', 'border-image-repeat',
69
+ 'border-image-slice', 'border-image-source', 'border-image-width', 'border-left-color',
70
+ 'border-left-style', 'border-left-width', 'border-right-color', 'border-right-style',
71
+ 'border-right-width', 'border-top-color', 'border-top-left-radius', 'border-top-right-radius',
72
+ 'border-top-style', 'border-top-width', 'bottom', 'box-shadow', 'box-sizing', 'buffered-rendering',
73
+ 'caption-side', 'clear', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation',
74
+ 'color-interpolation-filters', 'color-rendering', 'cursor', 'cx', 'cy', 'direction', 'display',
75
+ 'dominant-baseline', 'empty-cells', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flex-basis',
76
+ 'flex-direction', 'flex-grow', 'flex-shrink', 'flex-wrap', 'float', 'flood-color', 'flood-opacity',
77
+ 'font-family', 'font-kerning', 'font-size', 'font-stretch', 'font-style', 'font-variant',
78
+ 'font-variant-ligatures', 'font-weight', 'glyph-orientation-horizontal', 'glyph-orientation-vertical',
79
+ 'height', 'image-rendering', 'isolation', 'justify-content', 'left', 'letter-spacing', 'lighting-color',
80
+ 'line-height', 'list-style-image', 'list-style-position', 'list-style-type', 'margin-bottom', 'margin-left',
81
+ 'margin-right', 'margin-top', 'marker-end', 'marker-mid', 'marker-start', 'mask', 'mask-type', 'max-height',
82
+ 'max-width', 'min-height', 'min-width', 'mix-blend-mode', 'object-fit', 'object-position', 'opacity', 'order',
83
+ 'orphans', 'outline-color', 'outline-offset', 'outline-style', 'outline-width', 'overflow-wrap', 'overflow-x',
84
+ 'overflow-y', 'padding-bottom', 'padding-left', 'padding-right', 'padding-top', 'page-break-after',
85
+ 'page-break-before', 'page-break-inside', 'paint-order', 'perspective', 'perspective-origin', 'pointer-events',
86
+ 'position', 'r', 'resize', 'right', 'rx', 'ry', 'shape-image-threshold', 'shape-margin', 'shape-outside',
87
+ 'shape-rendering', 'speak', 'stop-color', 'stop-opacity', 'stroke', 'stroke-dasharray', 'stroke-dashoffset',
88
+ 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke-width', 'tab-size',
89
+ 'table-layout', 'text-align', 'text-anchor', 'text-decoration', 'text-indent', 'text-overflow', 'text-rendering',
90
+ 'text-shadow', 'text-transform', 'top', 'touch-action', 'transform', 'transform-origin', 'transform-style',
91
+ 'transition-delay', 'transition-duration', 'transition-property', 'transition-timing-function', 'unicode-bidi',
92
+ 'vector-effect', 'vertical-align', 'visibility', 'white-space', 'widows', 'width', 'will-change', 'word-break',
93
+ 'word-spacing', 'word-wrap', 'writing-mode', '-webkit-writing-mode', 'x', 'y', 'z-index', 'zoom']
94
+ end
95
+
96
+ def load_variables(file, key_type = :role, enabled_only = true, dbg = true, scripts = nil)
97
+ mark_test_level(build_message(file, "key:'#{key_type}'"))
98
+
99
+ # ok = true
100
+
101
+ debug_to_log("#{__method__}: file = #{file}")
102
+ debug_to_log("#{__method__}: key = #{key_type}")
103
+
104
+ workbook = file =~ /\.xlsx$/ ? Roo::Excelx.new(file) : Roo::Excel.new(file)
105
+
106
+ if @myName =~ /appium/i
107
+ ok = script_found_in_data = script_found_in_login = true
108
+ else
109
+ script_found_in_data = load_data_variables(workbook, dbg)
110
+ ok, script_found_in_login = load_login_variables(workbook, enabled_only, file, key_type, scripts, dbg)
111
+ end
112
+
113
+ unless @env_name =~ /^gen/
114
+ unless ok and script_found_in_login and script_found_in_data
115
+ ok = false
116
+ failed_to_log("Script found: in Login = #{script_found_in_login}; in Data = #{script_found_in_data}")
117
+ end
118
+ end
119
+
120
+ workbook.close
121
+
122
+ [ok, script_found_in_login, script_found_in_data]
123
+ rescue
124
+ failed_to_log(unable_to)
125
+ end
126
+
127
+ end
128
+
129
+ module Utilities
130
+
131
+ def element_action_message(element, action, how = nil, what = nil, value = nil, desc = '', refs = '')
132
+ if element.respond_to?(:tag_name)
133
+ begin
134
+ name = element.tag_name #.upcase
135
+ rescue
136
+ name = element.to_s
137
+ end
138
+ else
139
+ name = element.to_s
140
+ end
141
+ how, what = extract_locator(element, how)[1, 2] unless how and what
142
+ build_message(desc, action, "#{name}",
143
+ (what ? "with #{how}=>'#{what}'" : nil),
144
+ (value ? "and value=>'#{value}'" : nil), refs)
145
+ rescue
146
+ failed_to_log(unable_to)
147
+ end
148
+
149
+ def extract_locator(element, how = nil)
150
+ # html_to_log(element)
151
+ if element.respond_to?(:tag_name)
152
+ tag = element.tag_name.to_sym
153
+ else
154
+ element = element.body.elements[0]
155
+ tag = element.tag_name.to_sym
156
+ end
157
+ what = nil
158
+ case how
159
+ when nil
160
+ [:id, :name, :title, :class, :value].each do |attr|
161
+ what = element.attribute_value(attr.to_s)
162
+ if what and what.length > 0 and what != 'undefined'
163
+ how = attr
164
+ break
165
+ end
166
+ end
167
+ else
168
+ what = element.attribute_value(how.to_s)
169
+ end
170
+ # debug_to_log(with_caller("#{tag}:#{how}:#{what}"))
171
+ [tag, how, what]
172
+ rescue
173
+ failed_to_log(unable_to(build_message(":#{tag}, :#{how}='#{what}'")))
174
+ end
175
+
176
+ alias nbr2wd number_to_word
177
+
178
+ def get_project_git(proj_name, proj_dir = Dir.pwd)
179
+ debug_to_log(with_caller(proj_dir))
180
+ sha = nil
181
+ branch = nil
182
+ date = nil
183
+
184
+ curr_dir = Dir.pwd
185
+ version_file = "#{proj_name.downcase.gsub(' ', '_')}_version"
186
+
187
+ if Dir.exists?(proj_dir)
188
+
189
+ Dir.chdir(proj_dir) unless proj_dir == curr_dir
190
+
191
+ if Dir.exists?('.git')
192
+ require 'git'
193
+ git = Git.open(Dir.pwd)
194
+ branch = git.current_branch
195
+ commit = git.gblob(branch).log(5).first
196
+ sha = commit.sha
197
+ date = commit.date
198
+
199
+ version_file = File.join(curr_dir, version_file)
200
+ file = File.open(version_file, 'w')
201
+ file.puts "#{proj_name}: #{branch}, #{date}, #{sha}"
202
+ file.close
203
+
204
+ end
205
+
206
+ Dir.chdir(curr_dir) unless proj_dir == curr_dir
207
+
208
+ end
209
+
210
+ unless branch
211
+ version_file = File.join(Dir.pwd, version_file)
212
+ if File.exists?(version_file)
213
+ vers = File.open(version_file).read
214
+ branch, date, sha = parse_list(vers.chomp)
215
+ end
216
+ end
217
+
218
+ [branch, date, sha]
219
+ end
220
+
221
+ def normalize_border_style(value, rgba = true)
222
+ weight, style, color = parse_list(value, ' ', 3)
223
+ norm_color = normalize_color_value(color, rgba)
224
+ "#{weight} #{style} #{norm_color}"
225
+ end
226
+
227
+ def rescue_me(e, me = nil, what = nil, where = nil, who = nil)
228
+ #TODO: these are rescues from exceptions raised in Watir or Watir-webdriver
229
+ debug_to_log("#{__method__}: Begin rescue")
230
+ ok = false
231
+ begin
232
+ gaak = who.inspect
233
+ located = gaak =~ /located=true/i
234
+ rescue
235
+ debug_to_log("#{__method__}: gaak: '#{gaak}'")
236
+ end
237
+ msg = e.message
238
+ debug_to_log("#{__method__}: msg = #{msg}")
239
+ if msg =~ /undefined method\s+.join.\s+for/i # firewatir to_s implementation error
240
+ ok = true
241
+ elsif msg =~ /the server refused the connection/i
242
+ ok = true
243
+ elsif msg =~ /undefined method\s+.match.\s+for.+WIN32OLERuntimeError/i # watir and firewatir
244
+ ok = true
245
+ elsif msg =~ /undefined method\s+.match.\s+for.+UnknownObjectException/i # watir
246
+ ok = true
247
+ elsif msg =~ /window\.getBrowser is not a function/i # firewatir
248
+ ok = true
249
+ elsif msg =~ /WIN32OLERuntimeError/i # watir
250
+ ok = true
251
+ elsif msg =~ /undefined method\s+.match.\s+for/i # watir
252
+ ok = true
253
+ elsif msg =~ /wrong number of arguments \(1 for 0\)/i
254
+ ok = true
255
+ elsif msg =~ /unable to locate element/i
256
+ if located
257
+ ok = true
258
+ elsif where == 'Watir::Div'
259
+ ok = true
260
+ end
261
+ elsif msg =~ /(The SafariDriver does not interact with modal dialogs)/i
262
+ to_report = $1
263
+ ok = true
264
+ elsif msg =~ /HRESULT error code:0x80070005/
265
+ ok = true
266
+ #elsif msg =~ /missing\s+\;\s+before statement/
267
+ # ok = true
268
+ end
269
+ call_list = get_call_list(6, true)
270
+ if ok
271
+ debug_to_log("#{__method__}: RESCUED: \n#{who.to_yaml}=> #{what} in #{me}()\n=> '#{$!}'")
272
+ debug_to_log("#{__method__}: #{who.inspect}") if who
273
+ debug_to_log("#{__method__}: #{where.inspect}")
274
+ debug_to_log("#{__method__}: #{call_list}")
275
+ failed_to_log("#{to_report} #{call_list}")
276
+ else
277
+ debug_to_log("#{__method__}: NO RESCUE: #{e.message}")
278
+ debug_to_log("#{__method__}: NO RESCUE: \n#{call_list}")
279
+ end
280
+ debug_to_log("#{__method__}: Exit")
281
+ ok
282
+ end
283
+
284
+ def get_element_properties(element, list = [])
285
+ hash = {}
286
+ list.each do |prop|
287
+ style = nil
288
+ attr = nil
289
+ begin
290
+ style = element.style(prop)
291
+ rescue
292
+ debug_to_log(with_caller("Can't find style '#{prop}"))
293
+ end
294
+ begin
295
+ attr = element.attribute_value(prop)
296
+ rescue
297
+ debug_to_log(with_caller("Can't find attribute '#{prop}"))
298
+ end
299
+
300
+ hash[prop] = style ? style : attr
301
+ end
302
+
303
+ hash
304
+ rescue
305
+ failed_to_log(unable_to)
306
+ end
307
+
308
+ def escape_stuff(strg)
309
+ if strg.nil?
310
+ rslt = strg
311
+ else
312
+ if strg.respond_to?(:dup)
313
+ rslt = strg.dup
314
+ unless rslt.is_a?(Regexp)
315
+ if rslt.match(/[\/\(\)]/)
316
+ rslt.gsub!('/', '\/')
317
+ rslt.gsub!('(', '\(')
318
+ rslt.gsub!(')', '\)')
319
+ rslt = Regexp.new(rslt)
320
+ end
321
+ end
322
+ else
323
+ rslt = strg
324
+ end
325
+ end
326
+ rslt
327
+ rescue
328
+ failed_to_log(unable_to("#{rslt}"))
329
+ end
330
+
331
+ def element_query_message(element, query, how = nil, what = nil, value = nil, desc = '', refs = '', tag = '')
332
+ if element.exists?
333
+ name = element.respond_to?(:tag_name) ? element.tag_name.upcase : element.to_s
334
+ else
335
+ if tag and tag.length > 0
336
+ name = tag.upcase
337
+ else
338
+ name = '(unknown)'
339
+ end
340
+ end
341
+ build_message(desc, "#{name}",
342
+ (what ? "with #{how}=>' #{what}'" : nil),
343
+ (value ? "and value=>'#{value}'" : nil),
344
+ query, refs)
345
+ rescue
346
+ failed_to_log(unable_to)
347
+ end
348
+
349
+ end
350
+
351
+
352
+ module Find
353
+
354
+ def get_attribute_value(container, element, how, what, attribute, desc = '', refs = '')
355
+ msg = build_message(desc, "'#{attribute}' in :#{element.to_s.upcase} :#{how}='#{what}'.")
356
+ code = build_webdriver_fetch(element, how, what)
357
+ value = eval("#{code}.attribute_value('#{attribute}')")
358
+ if value
359
+ passed_to_log(with_caller(msg, desc, refs))
360
+ value
361
+ else
362
+ failed_to_log(with_caller(msg, desc, refs))
363
+ end
364
+ rescue
365
+ failed_to_log(unable_to(msg))
366
+ end
367
+
368
+ def get_element_colors(element, colors = [], desc = '', refs = '')
369
+ msg = build_message(desc, "Get colors for #{element.tag_name.upcase}.", refs)
370
+
371
+ colors = [
372
+ 'color', 'background-color', 'border-bottom-color', 'border-left-color', 'border-right-color',
373
+ 'border-top-color', 'border-color'
374
+ ] unless colors.size > 0
375
+
376
+ hash = {}
377
+ colors.each do |color|
378
+ hash[color] = normalize_color_value(element.style(color))
379
+ end
380
+
381
+ hash
382
+ rescue
383
+ failed_to_log(unable_to(msg))
384
+ end
385
+
386
+ def get_element_attribute(element, attribute, desc = '', refs = '', how = '', what = nil)
387
+ msg = build_message(desc, "Get '#{attribute}' for #{element.tag_name.upcase}", (":#{how}=>'#{what}'" if what), refs)
388
+ value = element.attribute_value(attribute)
389
+ if value
390
+ passed_to_log(with_caller(msg))
391
+ else
392
+ failed_to_log(with_caller(msg))
393
+ end
394
+ value
395
+ rescue
396
+ failed_to_log(unable_to(msg))
397
+ end
398
+
399
+ def get_selected_options(browser, how, what, desc = '', refs = '')
400
+ msg = build_message(desc, with_caller("in Select list #:#{how}=>#'#{what}'"), refs)
401
+ selected = nil
402
+ begin
403
+ list = browser.select_list(how, what)
404
+ rescue => e
405
+ unless rescue_me(e, __method__, rescue_me_command(:select_list, how, what), "#{browser.class}")
406
+ raise e
407
+ end
408
+ end
409
+ if list
410
+ selected = list.selected_options
411
+ if selected and selected.length > 0
412
+ passed_to_log(msg + " Found #{selected.length} selected options:" + " (first: value/text: #{selected[0].value}/#{selected[0].text})")
413
+ selected
414
+ else
415
+ failed_to_log(msg + ' Found no selected options.')
416
+ end
417
+ else
418
+ failed_to_log(with_caller(desc, "Select List #{how}=#{what} not found.", refs))
419
+ end
420
+ selected
421
+ rescue
422
+ failed_to_log(unable_to(msg))
423
+ end
424
+
425
+ def get_style(container, element, how, what, style, desc = '', refs = '')
426
+ msg = build_message(desc, "Get '#{style}' in :#{element.to_s.upcase} :#{how}='#{what}'.")
427
+ code = build_webdriver_fetch(element, how, what)
428
+ value = eval("#{code}.style('#{style}')")
429
+ if value
430
+ passed_to_log(with_caller(msg, "value=>'#{value}'", desc, refs))
431
+ value
432
+ else
433
+ failed_to_log(with_caller(msg, desc, refs))
434
+ end
435
+ rescue
436
+ failed_to_log(unable_to(msg))
437
+ end
438
+
439
+ alias get_style_value get_style
440
+
441
+ def get_directory(path)
442
+ if File.directory?(path)
443
+ debug_to_log("Directory already exists, '#{path}'.")
444
+ else
445
+ Dir::mkdir(path)
446
+ debug_to_log("Directory was created, '#{path}'.")
447
+ end
448
+ path
449
+ end
450
+
451
+ def get_element(container, element, how, what, value = nil, desc = '', refs = '', options = {})
452
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
453
+ msg = build_message(desc, "Return #{element.to_s.upcase} with :#{how}='#{what}'", value, refs)
454
+ timeout = options[:timeout] ? options[:timeout] : 30
455
+ code = build_webdriver_fetch(element, how, what, options)
456
+ code = "#{code}.when_present(#{timeout})" unless options[:exists_only] or container.to_s =~ /noko/i
457
+ debug_to_log(with_caller("{#{code}")) if $mobile
458
+ target = eval(code)
459
+ if target and target.exists?
460
+ if options[:flash] and target.respond_to?(:flash)
461
+ target.wd.location_once_scrolled_into_view
462
+ target.flash
463
+ end
464
+ if target.class =~ /element/i
465
+ target = target.to_subtype
466
+ msg.sub!(element.tag_name, target.tag_name)
467
+ end
468
+ passed_to_log(msg)
469
+ target
470
+ else
471
+ failed_to_log(msg)
472
+ nil
473
+ end
474
+ rescue => e
475
+ unless rescue_me(e, __method__, rescue_me_command(target, how, what), "#{container.class}", target)
476
+ failed_to_log(unable_to(msg))
477
+ raise e
478
+ end
479
+ end
480
+
481
+ def capture_value_desc(value, desc, refs, options = nil)
482
+ opt = options.dup if options
483
+ unless opt.kind_of?(Hash)
484
+ opt = Hash.new
485
+ end
486
+
487
+ if value
488
+ vlu = value.dup
489
+ elsif opt[:value]
490
+ vlu = opt[:value]
491
+ end
492
+
493
+ if desc
494
+ dsc = desc.dup
495
+ elsif opt[:desc]
496
+ dsc = opt[:desc]
497
+ end
498
+
499
+ if refs
500
+ rfs = refs.dup
501
+ elsif opt[:refs]
502
+ rfs = opt[:refs]
503
+ end
504
+
505
+ [vlu, dsc, rfs, opt]
506
+ rescue
507
+ failed_to_log(unable_to)
508
+ end
509
+
510
+ def ancestor_is_a?(descendant, tag_name, generation = 1, desc = '', refs = '')
511
+ tag_name = 'a' if tag_name == 'link'
512
+ msg = build_message(desc, "#{descendant.tag_name.upcase} with id '#{descendant.attribute_value('id')}' has", "tag: '#{tag_name}'", "#{generation} level above")
513
+ ancestor = descendant.dup
514
+ count = 0
515
+ while count < generation
516
+ ancestor = ancestor.parent
517
+ count += 1
518
+ end
519
+ if ancestor.respond_to?(:tag_name) and ancestor.tag_name.downcase == tag_name.downcase
520
+ passed_to_log(with_caller(msg, desc, refs))
521
+ true
522
+ else
523
+ failed_to_log(with_caller(msg, desc, refs))
524
+ end
525
+ rescue
526
+ failed_to_log(unable_to, false, true)
527
+ end
528
+
529
+ def get_ancestor(descendant, element, how, what, desc = '', refs = '', dbg = $debug)
530
+ found = false
531
+ how = 'class_name' if how.to_s == 'class'
532
+ tag = element.to_s.downcase
533
+ debug_to_log("target: #{descendant.to_s.upcase} :id=>#{descendant.attribute_value('id')}") if dbg
534
+ debug_to_log("goal: #{tag.upcase} :#{how}='#{what}' #{desc}") if dbg
535
+ ancestor = descendant.parent
536
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}' #{refs}") if dbg
537
+ code = "ancestor.#{how}"
538
+ what.is_a?(Regexp) ? code << " =~ /#{what.source}/" : code << " == '#{what}'"
539
+ debug_to_log("#{code}") if dbg
540
+ until found do
541
+ break unless ancestor
542
+ break if ancestor.tag_name =~ /html/i
543
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}' :id=>'#{ancestor.attribute_value('id')}' #{refs}") if dbg
544
+ if ancestor.tag_name == tag
545
+ if eval(code)
546
+ found = true
547
+ break
548
+ end
549
+ end
550
+ ancestor = ancestor.parent
551
+ end
552
+ msg = build_message(
553
+ with_caller(desc),
554
+ "- Descendant is #{descendant.tag_name.upcase} :id=>#{descendant.attribute_value('id')}.",
555
+ "Find ancestor #{tag.upcase} :#{how}='#{what}'?"
556
+ )
557
+ if found
558
+ passed_to_log(msg)
559
+ ancestor
560
+ else
561
+ failed_to_log(msg)
562
+ nil
563
+ end
564
+
565
+ rescue
566
+ failed_to_log(unable_to)
567
+ end
568
+
569
+ def get_ancestor2(descendant, element, how, what, desc = '', dbg = $DEBUG)
570
+ elements = Array.new
571
+ if element.is_a?(Array)
572
+ element.each do |e|
573
+ elements << e.to_s.downcase
574
+ end
575
+ else
576
+ elements[0] = element.tag_name.downcase
577
+ end
578
+ found = false
579
+ how = 'class_name' if how.to_s == 'class'
580
+ debug_to_log("target: #{descendant.tag_name} :id=>'#{descendant.attribute_value('id')}'") if dbg
581
+ debug_to_log("goal: #{nice_array(elements)} :#{how}='#{what}' #{desc}") if dbg
582
+ ancestor = descendant.parent
583
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}'") if dbg
584
+ code = "ancestor.#{how}"
585
+ what.is_a?(Regexp) ? code << " =~ /#{what.source}/" : code << " == '#{what}'"
586
+ debug_to_log("#{code}") if dbg
587
+
588
+ until found do
589
+ break unless ancestor
590
+ if ancestor.tag_name =~ /html/i
591
+ ancestor = nil
592
+ break
593
+ end
594
+
595
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}' :id=>'#{ancestor.attribute_value('id')}'") if dbg
596
+ if elements.include?(ancestor.tag_name.downcase)
597
+ if eval(code)
598
+ found = true
599
+ break
600
+ end
601
+ end
602
+
603
+ ancestor = ancestor.parent
604
+ end
605
+
606
+ [ancestor, (ancestor.tag_name.downcase if ancestor)]
607
+ rescue
608
+ failed_to_log(unable_to)
609
+ end
610
+
611
+ def get_ancestor3(descendant, elements = [:any], hows = [], whats = [], desc = '', dbg = $DEBUG)
612
+ fail 'Parameter \'elements\' must be an array.' unless elements.is_a?(Array)
613
+ fail 'Parameter \'hows\' must be an array.' unless hows.is_a?(Array)
614
+ fail 'Parameter \'whats\' must be an array.' unless whats.is_a?(Array)
615
+ fail 'Parameters \'hows\' and \'whats\' must be the same length.' unless hows.length == whats.length
616
+
617
+ found = false
618
+
619
+ debug_to_log("target: #{descendant.tag_name} :id=>'#{descendant.attribute_value('id')}'") if dbg
620
+ debug_to_log("goal: #{element.tag_name.upcase} :#{how}='#{what}' #{desc}") if dbg
621
+ ancestor = descendant.parent
622
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}'") if dbg
623
+ code == ''
624
+ (0..hows.length).each do |idx|
625
+ hows[idx] = 'class_name' if hows[idx].to_s == 'class'
626
+ code = "ancestor.#{how}"
627
+ whats[idx].is_a?(Regexp) ? code << " =~ /#{whats[idx].source}/" : code << " == '#{whats[idx]}'"
628
+ code << ' and ' if idx < hows.length
629
+ debug_to_log("#{code}") if dbg
630
+ end
631
+ until found do
632
+ break unless ancestor
633
+ break if ancestor.tag_name =~ /html/i
634
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}' :id=>'#{descendant.attribute_value('id')}'") if dbg
635
+ if elements.include?(ancestor.tag_name.downcase.to_sym)
636
+ if eval(code)
637
+ found = true
638
+ break
639
+ end
640
+ end
641
+ ancestor = ancestor.parent
642
+ end
643
+ [ancestor, ancestor.tag_name.downcase]
644
+ rescue
645
+ failed_to_log(unable_to)
646
+ end
647
+
648
+ def get_ancestor4(descendant, args = {})
649
+ desc = args[:desc] if args[:desc]
650
+ errors = Array.new
651
+ [:elements, :hows, :whats].each do |key|
652
+ if args.keys.include?(key)
653
+ unless args[key].is_a?(Array)
654
+ args[key] = [args[key]]
655
+ end
656
+ eval("#{key.to_s} = args[#{key}]")
657
+ else
658
+ errors << "Parameter '#{key}' is required. "
659
+ end
660
+ end
661
+ if hows and whats
662
+ unless hows.length == whats.length
663
+ errors << "Parameters 'hows' and 'whats' must be the same length. "
664
+ end
665
+ end
666
+ if errors.length > 0
667
+ failed_to_log("#{method_to_title(__method__)}: #{nice_array(errors)} #{desc}")
668
+ else
669
+ found = false
670
+ ancestor = descendant.parent
671
+ code == ''
672
+ (0..hows.length).each do |idx|
673
+ hows[idx] = 'class_name' if hows[idx].to_s == 'class'
674
+ code = "ancestor.#{how}"
675
+ whats[idx].is_a?(Regexp) ? code << " =~ /#{whats[idx].source}/" : code << " == '#{whats[idx]}'"
676
+ code << ' and ' if idx < hows.length
677
+ debug_to_log("#{code}") if dbg
678
+ end
679
+ until found do
680
+ break unless ancestor
681
+ debug_to_log("#{ancestor.tag_name}: :class=>'#{ancestor.class_name}' :id=>'#{descendant.attribute_value('id')}'") if dbg
682
+ if elements.include?(ancestor.tag_name.downcase.to_sym)
683
+ if eval(code)
684
+ found = true
685
+ break
686
+ end
687
+ end
688
+ ancestor = ancestor.parent
689
+ end
690
+ [ancestor, ancestor.tag_name.downcase]
691
+ end
692
+ rescue
693
+ failed_to_log(unable_to)
694
+ end
695
+
696
+ # def find_element_with_focus(container)
697
+ # container.driver.browser.switch_to.active_element
698
+ # end
699
+
700
+ def get_active_element(container)
701
+ container.execute_script("return document.activeElement")
702
+ end
703
+
704
+ alias find_element_with_focus get_active_element
705
+
706
+ def identify_active_element(container, desc = '', parent = false)
707
+ element = get_active_element(container)
708
+ element = element.parent if parent
709
+ tag = element.respond_to?(:tag_name) ? element.tag_name : 'no tag name'
710
+ id = element.respond_to?(:id) ? element.id : 'no id'
711
+ cls = element.respond_to?(:class_name) ? element.class_name : 'no class'
712
+ text = element.respond_to?(:text) ? element.text : 'no text'
713
+ debug_to_report(with_caller(desc, ":tag_name=>#{tag}", ":id=>#{id}", ":text=>'#{text}'", "is parent?=>#{parent}"))
714
+ [element, tag.to_sym, :id, cls]
715
+ rescue
716
+ failed_to_log(unable_to)
717
+ end
718
+
719
+ def highlight_element(element)
720
+ # not really different than .flash unless the two js scripts are separated by a sleep.
721
+ # probably needs to make sure that original color and border can be restored.
722
+ #public void highlightElement(WebDriver driver, WebElement element)
723
+ # { for (int i = 0; i < 2; i++)
724
+ # { JavascriptExecutor js = (JavascriptExecutor) driver;
725
+ # js.executeScript("arguments[0].setAttribute('style', arguments[1]);", element, "color: yellow; border: 2px solid yellow;");
726
+ # js.executeScript("arguments[0].setAttribute('style', arguments[1]);", element, "");
727
+ # }
728
+ # }
729
+ # - See more at: http://selenium.polteq.com/en/highlight-elements-with-selenium-webdriver/#sthash.JShjPbsj.dpuf
730
+ end
731
+
732
+ end
733
+
734
+ module Validations
735
+
736
+ include W3CValidators
737
+
738
+ def is_true?(actual, message, desc = '', refs = '')
739
+ msg = build_message(desc, "Is '#{message}' true?", refs)
740
+ if actual
741
+ passed_to_log(msg)
742
+ true
743
+ else
744
+ failed_to_log(msg)
745
+ end
746
+ end
747
+
748
+ def is_false?(actual, message, desc = '', refs = '')
749
+ msg = build_message(desc, "Is '#{message}' false?", refs)
750
+ if actual
751
+ failed_to_log(msg)
752
+ else
753
+ passed_to_log(msg)
754
+ true
755
+ end
756
+ end
757
+
758
+ def verify_months(list, language = 'English', abbrev = 0, desc = '', refs = '')
759
+ msg = build_message(desc, "List of xxxx months in #{language} is correct and in order?")
760
+ list = [nil].concat(list)
761
+ month_names = get_months(language, abbrev)
762
+ if abbrev > 0
763
+ msg.gsub!('xxxx', "#{nbr2wd(abbrev)} character")
764
+ else
765
+ msg.gsub!('xxxx', 'fully spelled')
766
+ end
767
+ if list == month_names
768
+ passed_to_log(with_caller(msg, refs))
769
+ true
770
+ else
771
+ failed_to_log(with_caller(msg, refs))
772
+ end
773
+ rescue
774
+ failed_to_log(unable_to(msg))
775
+ end
776
+
777
+ def verify_days(list, language = 'English', abbrev = 0, offset = 0, desc = '', refs = '')
778
+ #TODO: Handle different starting day: rotate_array(arr, target, index = 0, stop = 0)
779
+ msg = build_message(desc, "List of xxxx weekdays in #{language} is correct and in order?")
780
+ day_names = get_days(language, abbrev)
781
+ day_names = rotate_array(day_names, offset) if offset > 0
782
+ if abbrev > 0
783
+ msg.gsub!('xxxx', "#{nbr2wd(abbrev)} character")
784
+ else
785
+ msg.gsub!('xxxx', 'fully spelled')
786
+ end
787
+ if list == day_names
788
+ passed_to_log(with_caller(msg, refs))
789
+ true
790
+ else
791
+ failed_to_log(with_caller(msg, refs))
792
+ end
793
+ rescue
794
+ failed_to_log(unable_to(msg))
795
+ end
796
+
797
+ def greater_than?(actual, expected, desc = '', refs = '')
798
+ msg = build_message(desc, "Actual '#{actual}' greater than expected '#{expected}'?", refs)
799
+ if actual > expected
800
+ passed_to_log("#{msg}")
801
+ true
802
+ else
803
+ failed_to_log("#{msg}")
804
+ end
805
+ rescue
806
+ rescue_msg_for_validation(msg)
807
+ end
808
+
809
+ def greater_than_or_equal_to?(actual, expected, desc = '', refs = '')
810
+ msg = build_message(desc, "Actual '#{actual}' greater than or equal to expected '#{expected}'?", refs)
811
+ if actual >= expected
812
+ passed_to_log("#{msg}")
813
+ true
814
+ else
815
+ failed_to_log("#{msg}")
816
+ end
817
+ rescue
818
+ rescue_msg_for_validation(msg)
819
+ end
820
+
821
+ alias greater_than_or_equal? greater_than_or_equal_to?
822
+ alias greater_or_equal? greater_than_or_equal_to?
823
+ alias count_greater_or_equal? greater_than_or_equal_to?
824
+
825
+ def less_than?(actual, expected, desc = '', refs = '')
826
+ msg = build_message(desc, "Actual '#{actual}' less than expected '#{expected}'?", refs)
827
+ if actual < expected
828
+ passed_to_log("#{msg}")
829
+ true
830
+ else
831
+ failed_to_log("#{msg}")
832
+ end
833
+ rescue
834
+ rescue_msg_for_validation(msg)
835
+ end
836
+
837
+ def less_than_or_equal_to?(actual, expected, desc = '', refs = '')
838
+ msg = build_message(desc, "Actual '#{actual}' less than or equal to expected '#{expected}'?", refs)
839
+ if actual <= expected
840
+ passed_to_log("#{msg}")
841
+ true
842
+ else
843
+ failed_to_log("#{msg}")
844
+ end
845
+ rescue
846
+ rescue_msg_for_validation(msg)
847
+ end
848
+
849
+ alias count_less_or_equal? less_than_or_equal_to?
850
+ alias less_than_or_equal? less_than_or_equal_to?
851
+ alias less_or_equal? less_than_or_equal_to?
852
+
853
+ def number_equals?(actual, expected, desc = '', refs = '')
854
+ msg = build_message(desc, "Actual '#{actual}' equals expected '#{expected}'?", refs)
855
+ if actual == expected
856
+ passed_to_log("#{msg}")
857
+ true
858
+ else
859
+ failed_to_log("#{msg}")
860
+ end
861
+ rescue
862
+ rescue_msg_for_validation(msg)
863
+ end
864
+
865
+ alias count_equals? number_equals?
866
+
867
+ def number_does_not_equal?(actual, expected, desc = '', refs = '')
868
+ msg = build_message(desc, "Actual '#{actual}' does not equal expected '#{expected}'?", refs)
869
+ if actual == expected
870
+ failed_to_log("#{msg}")
871
+ else
872
+ passed_to_log("#{msg}")
873
+ true
874
+ end
875
+ rescue
876
+ rescue_msg_for_validation(msg)
877
+ end
878
+
879
+ alias count_does_not_equal? number_does_not_equal?
880
+
881
+ def within_range?(actual, target, min, max = nil)
882
+ if max
883
+ (min..max).include?(actual)
884
+ else
885
+ ((target - min)..(target + min)).include?(actual)
886
+ end
887
+ rescue
888
+ failed_to_log(unable_to, false, true)
889
+ end
890
+
891
+ def within_tolerance?(actual, expected, tolerance, desc = '', refs = '')
892
+ min = expected - tolerance
893
+ max = expected + tolerance
894
+ msg = build_message(desc, "#{actual} is between #{min} and #{max}?", refs)
895
+ if within_range?(actual, expected, tolerance)
896
+ passed_to_log("#{msg}")
897
+ true
898
+ else
899
+ failed_to_log("#{msg}")
900
+ end
901
+ rescue
902
+ rescue_msg_for_validation(msg)
903
+ end
904
+
905
+ alias number_within_tolerance? within_tolerance?
906
+ alias count_within_tolerance? within_tolerance?
907
+
908
+ def dimensions_equal?(first_name, first_value, second_name, second_value, desc = '', refs = '')
909
+ msg = build_message(desc, "#{first_name}: #{first_value} equals #{second_name}: #{second_value}?", refs)
910
+ if first_value == second_value
911
+ passed_to_log("#{msg}")
912
+ true
913
+ else
914
+ failed_to_log("#{msg}")
915
+ end
916
+ rescue
917
+ rescue_msg_for_validation(msg)
918
+ end
919
+
920
+ def dimensions_not_equal?(first_name, first_value, second_name, second_value, desc = '', refs = '')
921
+ msg = build_message(desc, "#{first_name}: #{first_value} does not equal #{second_name}: #{second_value}?", refs)
922
+ if first_value == second_value
923
+ failed_to_log("#{msg}")
924
+ else
925
+ passed_to_log("#{msg}")
926
+ true
927
+ end
928
+ rescue
929
+ rescue_msg_for_validation(msg)
930
+ end
931
+
932
+ def dimension_within_tolerance?(name, actual, expected, tolerance, desc = '', refs = '')
933
+ within_tolerance?(actual, expected, tolerance, with_caller("#{desc}, Dimension", name), refs = '')
934
+ end
935
+
936
+ # def centered?(container, element, desc = '', refs = '')
937
+ # name = element.respond_to?(:tag_name) ? element.tag_name.upcase : 'DOM'
938
+ # msg = build_message(desc, "is centered @@@?", refs)
939
+ #
940
+ # element_x, element_y = element.dimensions
941
+ # element_left, element_top = element.client_offset
942
+ #
943
+ # horizontally = (((element_left * 2) + element_x.floor).to_i) == viewport_x
944
+ # h_msg = msg.sub('@@@', 'horizontally')
945
+ # if horizontally
946
+ # passed_to_log(h_msg)
947
+ # else
948
+ # failed_to_log(h_msg)
949
+ # end
950
+ #
951
+ # # At <= 600BP, should be full size of viewport
952
+ # vertically = true
953
+ # unless element_top <= 1 || element_x <= 601
954
+ # vertically = ((element_top * 2) + element_y) == viewport_y
955
+ # v_msg = msg.sub('@@@', 'vertically')
956
+ #
957
+ # if vertically
958
+ # passed_to_log(v_msg)
959
+ # else
960
+ # failed_to_log(v_msg)
961
+ # end
962
+ # end
963
+ #
964
+ # if horizontally and vertically
965
+ # true
966
+ # else
967
+ # false
968
+ # end
969
+ #
970
+ # rescue
971
+ # failed_to_log(unable_to(msg.sub('@@@ ', ''), false, true))
972
+ # end
973
+ #
974
+ def class_equals?(container, element, how, what, expected, desc = '', refs = '')
975
+ code = build_webdriver_fetch(element, how, what)
976
+ target = eval("#{code}")
977
+ element_class_equals?(target, expected, desc, refs, how, what)
978
+ rescue
979
+ failed_to_log(unable_to(build_msg(element, how, what), false, true))
980
+ end
981
+
982
+ def element_class_equals?(container, element, expected, desc = '', refs = '', how = nil, what = nil)
983
+ msg = element_query_message(element, ":class equals '#{expected}'?", how, what, nil, desc, refs)
984
+ element_wait(element)
985
+ if element.class_name == expected
986
+ passed_to_log(msg)
987
+ true
988
+ else
989
+ failed_to_log("#{msg}. Found '#{element.class_name}'")
990
+ end
991
+ rescue
992
+ rescue_msg_for_validation(msg)
993
+ end
994
+
995
+ def class_does_not_contain?(container, element, how, what, expected, desc = '', refs = '')
996
+ code = build_webdriver_fetch(element, how, what)
997
+ target = eval("#{code}")
998
+ element_class_does_not_contain?(target, expected, desc, refs, how, what)
999
+ rescue
1000
+ failed_to_log(unable_to(build_msg(element, how, what), false, true))
1001
+ end
1002
+
1003
+ def element_class_does_not_contain?(element, expected, desc = '', refs = '', how = nil, what = nil)
1004
+ msg = element_query_message(element, ":class does not contain '#{expected}'?", how, what, nil, desc, refs)
1005
+ element_wait(element)
1006
+ if element.class_name.match(expected)
1007
+ failed_to_log(msg)
1008
+ else
1009
+ passed_to_log(msg)
1010
+ true
1011
+ end
1012
+ rescue
1013
+ rescue_msg_for_validation(msg)
1014
+ end
1015
+
1016
+ def class_contains?(container, element, how, what, expected, desc = '', refs = '')
1017
+ code = build_webdriver_fetch(element, how, what)
1018
+ target = eval("#{code}")
1019
+ element_class_contains?(target, expected, desc, refs, how, what)
1020
+ rescue
1021
+ failed_to_log(unable_to(build_msg(element, how, what), false, true))
1022
+ end
1023
+
1024
+ alias verify_class class_contains?
1025
+
1026
+ def element_class_contains?(element, expected, desc = '', refs = '', how = nil, what = nil)
1027
+ msg = element_query_message(element, ":class contains '#{expected}'?", how, what, nil, desc, refs)
1028
+ class_name = element.class_name
1029
+ if class_name.match(expected)
1030
+ passed_to_log(msg)
1031
+ true
1032
+ else
1033
+ failed_to_log("#{msg}. Found '#{class_name}'")
1034
+ end
1035
+ rescue
1036
+ rescue_msg_for_validation(msg)
1037
+ end
1038
+
1039
+ alias verify_class class_contains?
1040
+
1041
+ def columns_match?(exp, act, dir, col, org = nil, desc = '', refs = '')
1042
+ msg = build_message(desc, "Click on #{dir} column '#{col}' produces expected sorted list?", refs)
1043
+ ok = arrays_match?(exp, act, msg)
1044
+ unless ok
1045
+ debug_to_log("Original order ['#{org.join("', '")}']") if org
1046
+ debug_to_log("Expected order ['#{exp.join("', '")}']")
1047
+ debug_to_log(" Actual order ['#{act.join("', '")}']")
1048
+ end
1049
+ ok
1050
+ rescue
1051
+ rescue_msg_for_validation(desc, refs)
1052
+ end
1053
+
1054
+ def hashes_match?(exp, act, desc = '', refs = '')
1055
+ msg = build_message(desc, 'Hashes match?', refs)
1056
+ if exp == act
1057
+ passed_to_log(msg)
1058
+ true
1059
+ else
1060
+ failed_to_log(msg)
1061
+ end
1062
+ rescue
1063
+ rescue_msg_for_validation(desc, refs)
1064
+ end
1065
+
1066
+ def array_includes?(array, expected, desc = '', refs = '')
1067
+ msg = build_message(desc, "Array includes '#{expected}'?", refs)
1068
+ if array.include?(expected)
1069
+ passed_to_log(msg)
1070
+ true
1071
+ else
1072
+ failed_to_log(msg)
1073
+ end
1074
+ rescue
1075
+ rescue_msg_for_validation(desc, refs)
1076
+ end
1077
+
1078
+ def array_does_not_include?(array, expected, desc = '', refs = '')
1079
+ msg = build_message(desc, "Array does not include '#{expected}'?", refs)
1080
+ if array.include?(expected)
1081
+ failed_to_log(msg)
1082
+ else
1083
+ passed_to_log(msg)
1084
+ true
1085
+ end
1086
+ rescue
1087
+ rescue_msg_for_validation(desc, refs)
1088
+ end
1089
+
1090
+ def arrays_match?(exp, act, desc = '', refs = '')
1091
+ msg = build_message(desc, 'Arrays match?', refs)
1092
+ exp = exp.is_a?(Array) ? exp.dup : [exp]
1093
+ act = act.is_a?(Array) ? act.dup : [act]
1094
+ if exp == act
1095
+ passed_to_log(msg)
1096
+ true
1097
+ else
1098
+ failed_to_log(msg)
1099
+ end
1100
+ rescue
1101
+ rescue_msg_for_validation(desc, refs)
1102
+ end
1103
+
1104
+ alias arrays_match arrays_match?
1105
+
1106
+ def attribute_contains?(container, element, how, what, attribute, expected, desc = '', refs = '')
1107
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}'", ";#{attribute}", "contains '#{expected}'?", refs)
1108
+ actual = container.element(how, what).attribute_value(attribute)
1109
+ if actual
1110
+ if actual.match(expected)
1111
+ passed_to_log(msg)
1112
+ true
1113
+ else
1114
+ failed_to_log(msg)
1115
+ end
1116
+ else
1117
+ failed_to_log("#{msg} '#{attribute}' not found.")
1118
+ end
1119
+ rescue
1120
+ rescue_msg_for_validation(desc, refs)
1121
+ end
1122
+
1123
+ def attribute_does_not_contain?(container, element, how, what, attribute, expected, desc = '', refs = '')
1124
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}'", "attribute '#{attribute}", "does not contain '#{expected}'?", refs)
1125
+ actual = container.element(how, what).attribute_value(attribute)
1126
+ if actual
1127
+ if actual.match(expected)
1128
+ failed_to_log(msg)
1129
+ else
1130
+ passed_to_log(msg)
1131
+ true
1132
+ end
1133
+ else
1134
+ failed_to_log("#{msg} '#{attribute}' not found.")
1135
+ end
1136
+ rescue
1137
+ rescue_msg_for_validation(desc, refs)
1138
+ end
1139
+
1140
+ def attribute_equals?(container, element, how, what, attribute, expected, desc = '', refs = '')
1141
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}'", "attribute '#{attribute}", "equals '#{expected}'?", refs)
1142
+ actual = container.element(how, what).attribute_value(attribute)
1143
+ if actual
1144
+ if actual == expected
1145
+ passed_to_log(msg)
1146
+ true
1147
+ else
1148
+ failed_to_log("#{msg} Found '#{actual}'")
1149
+ end
1150
+ else
1151
+ failed_to_log("#{msg} '#{attribute}' not found.")
1152
+ end
1153
+ rescue
1154
+ rescue_msg_for_validation(desc, refs)
1155
+ end
1156
+
1157
+ def attribute_does_not_equal?(container, element, how, what, attribute, expected, desc = '', refs = '')
1158
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}'", "attribute '#{attribute}", "does not equal '#{expected}?", refs)
1159
+ actual = container.element(how, what).attribute_value(attribute)
1160
+ if actual
1161
+ if actual == expected
1162
+ failed_to_log(msg)
1163
+ else
1164
+ passed_to_log("#{msg} Found '#{actual}'")
1165
+ true
1166
+ end
1167
+ else
1168
+ failed_to_log("#{msg} '#{attribute}' not found.")
1169
+ end
1170
+ rescue
1171
+ rescue_msg_for_validation(desc, refs)
1172
+ end
1173
+
1174
+ def checked?(container, element, how, what, value = nil, desc = '', refs = '')
1175
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
1176
+ code = build_webdriver_fetch(element, how, what, options)
1177
+ target = eval(code)
1178
+ element_checked?(target, desc, refs, how, what, value)
1179
+ rescue
1180
+ rescue_msg_for_validation(desc, refs)
1181
+ end
1182
+
1183
+ alias checkbox_checked? checked?
1184
+ alias checkbox_set? checked?
1185
+
1186
+ def element_checked?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
1187
+ msg = element_query_message(element, "is checked?", how, what, value, desc, refs)
1188
+ if element.checked?
1189
+ passed_to_log(msg)
1190
+ true
1191
+ else
1192
+ failed_to_log(msg)
1193
+ end
1194
+ rescue
1195
+ rescue_msg_for_validation(msg)
1196
+ end
1197
+
1198
+ def not_checked?(container, how, what, value = nil, desc = '', refs = '')
1199
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
1200
+ code = build_webdriver_fetch(element, how, what, options)
1201
+ target = eval(code)
1202
+ element_not_checked?(target, desc, refs, how, what, value)
1203
+ rescue
1204
+ rescue_msg_for_validation(desc, refs)
1205
+ end
1206
+
1207
+ alias checkbox_not_checked? not_checked?
1208
+ alias checkbox_not_set? not_checked?
1209
+
1210
+ def element_not_checked?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
1211
+ msg = element_query_message(element, "is not checked?", how, what, value, desc, refs)
1212
+ if element.checked?
1213
+ failed_to_log(msg)
1214
+ else
1215
+ passed_to_log(msg)
1216
+ true
1217
+ end
1218
+ rescue
1219
+ rescue_msg_for_validation(msg)
1220
+ end
1221
+
1222
+ def checkbox_has_checked?(checkbox, desc = '', refs = '')
1223
+ msg = element_query_message(checkbox, "has 'checked' attribute", nil, nil, nil, desc, refs)
1224
+ html = checkbox.html
1225
+ if html =~ /checked/ and not html =~ /checked=""/
1226
+ passed_to_log(msg)
1227
+ true
1228
+ else
1229
+ failed_to_log(msg)
1230
+ end
1231
+ rescue
1232
+ rescue_msg_for_validation(desc, refs)
1233
+ end
1234
+
1235
+ def checkbox_does_not_have_checked?(checkbox, desc = '', refs = '')
1236
+ msg = element_query_message(checkbox, "does not have 'checked' attribute", nil, nil, nil, desc, refs)
1237
+ html = checkbox.html
1238
+ if html =~ /checked=""/ or not html =~ /checked/
1239
+ passed_to_log(msg)
1240
+ true
1241
+ else
1242
+ failed_to_log(msg)
1243
+ end
1244
+ rescue
1245
+ rescue_msg_for_validation(desc, refs)
1246
+ end
1247
+
1248
+ def attribute_in_html?(container, how, what, attribute, desc = '', refs = '')
1249
+ target = container.element(how, what)
1250
+ element_attribute_in_html?(target, attribute, desc, refs, how, what)
1251
+ rescue
1252
+ rescue_msg_for_validation(desc, refs)
1253
+ end
1254
+
1255
+ def element_attribute_in_html?(element, attribute, desc = '', refs = '', how = nil, what = nil)
1256
+ msg = element_query_message(element, "attribute '#{attribute}' exists in html?", how, what, nil, desc, refs)
1257
+ # element_wait(element)
1258
+ ptrn = /#{attribute}(?:\s|>|=|$)/
1259
+ # debug_to_log(with_caller("[#{element.html}]::", "[#{ptrn}"))
1260
+ if element.html =~ ptrn
1261
+ attr_vlu = element.attribute_value(attribute)
1262
+ passed_to_log("#{msg} Value = '#{attr_vlu}'")
1263
+ true
1264
+ else
1265
+ failed_to_log(msg)
1266
+ end
1267
+ rescue
1268
+ rescue_msg_for_validation(desc, refs)
1269
+ end
1270
+
1271
+ def attribute_not_in_html?(container, how, what, attribute, desc = '', refs = '')
1272
+ target = container.element(how, what)
1273
+ element_attribute_not_in_html?(target, attribute, desc, refs, how, what)
1274
+ rescue
1275
+ rescue_msg_for_validation(desc, refs)
1276
+ end
1277
+
1278
+ def element_attribute_not_in_html?(element, attribute, desc = '', refs = '', how = nil, what = nil)
1279
+ msg = element_query_message(element, "attribute '#{attribute}' does not exist in html?", how, what, nil, desc, refs)
1280
+ ptrn = /#{attribute}(?:\s|>|=|$)/
1281
+ # debug_to_log(with_caller("[#{element.html}]::", "[#{ptrn}"))
1282
+ if element.html =~ ptrn
1283
+ attr_vlu = element.attribute_value(attribute)
1284
+ failed_to_log("#{msg} Value = '#{attr_vlu}'")
1285
+ else
1286
+ passed_to_log(msg)
1287
+ true
1288
+ end
1289
+ rescue
1290
+ rescue_msg_for_validation(desc, refs)
1291
+ end
1292
+
1293
+ def attribute_exists?(container, how, what, attribute, desc = '', refs = '')
1294
+ target = container.element(how, what)
1295
+ element_attribute_exists?(target, attribute, desc, refs, how, what)
1296
+ rescue
1297
+ rescue_msg_for_validation(desc, refs)
1298
+ end
1299
+
1300
+ def element_attribute_exists?(element, attribute, desc = '', refs = '', how = nil, what = nil)
1301
+ msg = element_query_message(element, "attribute '#{attribute}' exists?", how, what, nil, desc, refs)
1302
+ # element_wait(element)
1303
+ ptrn = /(?:<|\s)#{attribute}(?:\s|>|=|$)/
1304
+ if element.html =~ ptrn
1305
+ value = element.attribute_value(attribute)
1306
+ passed_to_log("#{msg} '#{attribute}' found with value '#{value}'.")
1307
+ true
1308
+ else
1309
+ failed_to_log(msg)
1310
+ end
1311
+ rescue
1312
+ rescue_msg_for_validation(desc, refs)
1313
+ end
1314
+
1315
+ def attribute_does_not_exist?(container, how, what, attribute, desc = '', refs = '')
1316
+ target = container.element(how, what)
1317
+ element_attribute_does_not_exist?(target, attribute, desc, refs, how, what)
1318
+ rescue
1319
+ rescue_msg_for_validation(desc, refs)
1320
+ end
1321
+
1322
+ def element_attribute_does_not_exist?(element, attribute, desc = '', refs = '', how = nil, what = nil)
1323
+ msg = element_query_message(element, "attribute '#{attribute}' does not exist?", how, what, nil, desc, refs)
1324
+ # element_wait(element)
1325
+ ptrn = /(?:<|\s)#{attribute}(?:\s|>|=|$)/
1326
+ if element.html =~ ptrn
1327
+ value = element.attribute_value(attribute)
1328
+ failed_to_log("#{msg} '#{attribute}' found with value '#{value}'.")
1329
+ else
1330
+ passed_to_log("#{msg}")
1331
+ true
1332
+ end
1333
+ rescue
1334
+ rescue_msg_for_validation(desc, refs)
1335
+ end
1336
+
1337
+ def element_inline_attribute_contains?(element, attribute, expected, desc = '', refs = '', how = nil, what = nil)
1338
+ msg = element_query_message(element, "Inline attribute '#{attribute}' contains '#{force_string(expected)}'?", how, what, nil, desc, refs)
1339
+ element_html = element.html
1340
+ if element_html.include? attribute
1341
+ inline_attr = "#{attribute}" + '=' + '"' + "#{expected}" + '"'
1342
+ puts inline_attr
1343
+ if element_html.include? inline_attr
1344
+ pass_to_log(msg)
1345
+ else
1346
+ fail_to_log(msg)
1347
+ end
1348
+ end
1349
+ end
1350
+
1351
+ # def element_inline_attribute_equals?(element, attribute, expected, desc = '', refs = '')
1352
+ # element_html = element.html
1353
+ # if element_html.include? attribute
1354
+ # inline_attr = "#{attribute}" + '=' + '"' + "#{value}" + '"'
1355
+ # puts inline_attr
1356
+ # if element_html.include? inline_attr
1357
+ # pass_to_log("#{attribute} has the expected value of #{value}")
1358
+ # else
1359
+ # fail_to_log("#{attribute} missing the expected value of #{value} ")
1360
+ # end
1361
+ # end
1362
+ # end
1363
+
1364
+ def element_attribute_equals?(element, attribute, expected, desc = '', refs = '', how = nil, what = nil)
1365
+ msg = element_query_message(element, "attribute '#{attribute}' equals '#{force_string(expected)}'?", how, what, nil, desc, refs)
1366
+ actual = element.attribute_value(attribute)
1367
+ if actual
1368
+ if actual == expected
1369
+ passed_to_log(msg)
1370
+ true
1371
+ else
1372
+ failed_to_log("#{msg} Found '#{actual}'")
1373
+ end
1374
+ else
1375
+ failed_to_log("#{msg} '#{attribute}' not found.")
1376
+ end
1377
+ rescue
1378
+ rescue_msg_for_validation(desc, refs)
1379
+ end
1380
+
1381
+ def element_attribute_does_not_equal?(element, attribute, expected, desc = '', refs = '', how = nil, what = nil)
1382
+ msg = element_query_message(element, "attribute '#{attribute}' does not equal '#{force_string(expected)}'?", how, what, nil, desc, refs)
1383
+ actual = element.attribute_value(attribute)
1384
+ if actual
1385
+ if actual == expected
1386
+ failed_to_log(msg)
1387
+ else
1388
+ passed_to_log(msg)
1389
+ true
1390
+ end
1391
+ else
1392
+ failed_to_log("#{msg} '#{attribute}' not found.")
1393
+ end
1394
+ rescue
1395
+ rescue_msg_for_validation(desc, refs)
1396
+ end
1397
+
1398
+ alias element_attribute_not_equal? element_attribute_does_not_equal?
1399
+
1400
+ def element_attribute_contains?(element, attribute, expected, desc = '', refs = '', how = nil, what = nil)
1401
+ msg = element_query_message(element, "attribute '#{attribute}' contains '#{force_string(expected)}'?", how, what, nil, desc, refs)
1402
+ actual = element.attribute_value(attribute)
1403
+ if actual
1404
+ if actual.match(expected)
1405
+ passed_to_log(msg)
1406
+ true
1407
+ else
1408
+ failed_to_log("#{msg} Found '#{actual}'")
1409
+ end
1410
+ else
1411
+ failed_to_log("#{msg} '#{attribute}' not found.")
1412
+ end
1413
+ rescue
1414
+ rescue_msg_for_validation(msg)
1415
+ end
1416
+
1417
+ def element_attribute_does_not_contain?(element, attribute, expected, desc = '', refs = '')
1418
+ msg = element_query_message(element, "attribute '#{attribute}' does not contain '#{force_string(expected)}'?", nil, nil, nil, desc, refs)
1419
+ actual = element.attribute_value(attribute)
1420
+ if actual
1421
+ if actual.match(expected)
1422
+ msg << " Found '#{actual.match(expected)[1]}'"
1423
+ failed_to_log(msg)
1424
+ else
1425
+ passed_to_log(msg)
1426
+ true
1427
+ end
1428
+ else
1429
+ failed_to_log("#{msg} '#{attribute}' not found.")
1430
+ end
1431
+ rescue
1432
+ rescue_msg_for_validation(msg)
1433
+ end
1434
+
1435
+ def element_attribute_greater?(element, attr_name, expected, desc = '', refs = '')
1436
+ msg = element_query_message(element, "attribute '#{attr_name}' greater than '#{expected}'?", nil, nil, nil, desc, refs)
1437
+ actual = element.attribute_value(attr_name)
1438
+ if actual
1439
+ if actual.to_i > expected.to_i
1440
+ passed_to_log(msg)
1441
+ true
1442
+ else
1443
+ failed_to_log("#{msg} Found '#{actual}'")
1444
+ end
1445
+ else
1446
+ failed_to_log("#{msg} '#{attribute}' not found.")
1447
+ end
1448
+ rescue
1449
+ rescue_msg_for_validation(desc, refs)
1450
+ end
1451
+
1452
+ def element_attribute_less?(element, attr_name, expected, desc = '', refs = '')
1453
+ msg = element_query_message(element, "attribute '#{attr_name}' less than '#{expected}'?", nil, nil, nil, desc, refs)
1454
+ actual = element.attribute_value(attr_name)
1455
+ if actual
1456
+ if actual.to_i < expected.to_i
1457
+ passed_to_log(msg)
1458
+ true
1459
+ else
1460
+ failed_to_log("#{msg} Found '#{actual}'")
1461
+ end
1462
+ else
1463
+ failed_to_log("#{msg} '#{attribute}' not found.")
1464
+ end
1465
+ rescue
1466
+ rescue_msg_for_validation(desc, refs)
1467
+ end
1468
+
1469
+ def element_attribute_greater_or_equal?(element, attr_name, expected, desc = '', refs = '')
1470
+ msg = element_query_message(element, "attribute '#{attr_name}' greater than or equal to '#{expected}'?", nil, nil, nil, desc, refs)
1471
+ actual = element.attribute_value(attr_name)
1472
+ if actual
1473
+ if actual.to_i >= expected.to_i
1474
+ passed_to_log(msg)
1475
+ true
1476
+ else
1477
+ failed_to_log("#{msg} Found '#{actual}'")
1478
+ end
1479
+ else
1480
+ failed_to_log("#{msg} '#{attribute}' not found.")
1481
+ end
1482
+ rescue
1483
+ rescue_msg_for_validation(desc, refs)
1484
+ end
1485
+
1486
+ def element_attribute_less_or_equal?(element, attr_name, expected, desc = '', refs = '')
1487
+ msg = element_query_message(element, "attribute '#{attr_name}' less than or equal to '#{expected}'?", nil, nil, nil, desc, refs)
1488
+ actual = element.attribute_value(attr_name)
1489
+ if actual
1490
+ if actual.to_i <= expected.to_i
1491
+ passed_to_log(msg)
1492
+ true
1493
+ else
1494
+ failed_to_log("#{msg} Found '#{actual}'")
1495
+ end
1496
+ else
1497
+ failed_to_log("#{msg} '#{attribute}' not found.")
1498
+ end
1499
+ rescue
1500
+ rescue_msg_for_validation(desc, refs)
1501
+ end
1502
+
1503
+ def element_value_equals?(element, expected, desc = '', refs = '')
1504
+ msg = element_query_message(element, "value equals '#{expected}'?", nil, nil, nil, desc, refs)
1505
+
1506
+ if element.responds_to?('value')
1507
+ actual = element.value
1508
+ if actual
1509
+ if actual == expected
1510
+ passed_to_log(msg)
1511
+ true
1512
+ else
1513
+ failed_to_log(msg)
1514
+ end
1515
+ else
1516
+ failed_to_log("#{msg} 'value' not found.")
1517
+ end
1518
+ else
1519
+ failed_to_log("#{msg} Element does not respond to 'value'")
1520
+ end
1521
+
1522
+ rescue
1523
+ rescue_msg_for_validation(desc, refs)
1524
+ end
1525
+
1526
+ def element_text_equals?(element, expected, desc = '', refs = '')
1527
+ msg = element_query_message(element, "text equals '#{expected}'?", nil, nil, nil, desc, refs)
1528
+ actual = element.text
1529
+ if actual
1530
+ if actual == expected
1531
+ passed_to_log(msg)
1532
+ true
1533
+ else
1534
+ failed_to_log(msg)
1535
+ end
1536
+ else
1537
+ failed_to_log("#{msg} 'text' not found.")
1538
+ end
1539
+ rescue
1540
+ rescue_msg_for_validation(desc, refs)
1541
+ end
1542
+
1543
+ def element_text_does_not_equal?(element, expected, desc = '', refs = '')
1544
+ msg = element_query_message(element, "text does not '#{expected}'?", nil, nil, nil, desc, refs)
1545
+ actual = element.text
1546
+ if actual
1547
+ if actual == expected
1548
+ failed_to_log(msg)
1549
+ else
1550
+ passed_to_log(msg)
1551
+ true
1552
+ end
1553
+ else
1554
+ failed_to_log("#{msg} 'text' not found.")
1555
+ end
1556
+ rescue
1557
+ rescue_msg_for_validation(desc, refs)
1558
+ end
1559
+
1560
+ def element_text_includes?(element, expected, desc = '', refs = '')
1561
+ msg = element_query_message(element, "text includes '#{expected}'?", nil, nil, nil, desc, refs)
1562
+ actual = element.text
1563
+ if actual
1564
+ if actual.include?(expected)
1565
+ passed_to_log(msg)
1566
+ true
1567
+ else
1568
+ failed_to_log(msg)
1569
+ end
1570
+ else
1571
+ failed_to_log("#{msg} 'text' not found.")
1572
+ end
1573
+ rescue
1574
+ rescue_msg_for_validation(desc, refs)
1575
+ end
1576
+
1577
+ alias element_includes_text? element_text_includes?
1578
+
1579
+ def element_text_does_not_include?(element, expected, desc = '', refs = '')
1580
+ msg = element_query_message(element, "text does not include '#{expected}'?", nil, nil, nil, desc, refs)
1581
+ actual = element.text
1582
+ if actual
1583
+ if actual.include?(expected)
1584
+ failed_to_log(msg)
1585
+ else
1586
+ passed_to_log(msg)
1587
+ true
1588
+ end
1589
+ else
1590
+ failed_to_log("#{msg} '#{attribute}' not found.")
1591
+ end
1592
+ rescue
1593
+ rescue_msg_for_validation(desc, refs)
1594
+ end
1595
+
1596
+ alias element_does_not_include_text? element_text_does_not_include?
1597
+
1598
+ def element_wait(element, sleep = 0.25)
1599
+ if element.respond_to?(:wait)
1600
+ element.wait
1601
+ elsif element.respond_to?(:wait_until_present)
1602
+ element.wait_until_present
1603
+ else
1604
+ sleep(sleep)
1605
+ end
1606
+ end
1607
+
1608
+ def contains_text?(container, element, how, what, expected, desc = '', refs = '')
1609
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}' contains '#{expected}'?", refs)
1610
+ code = build_webdriver_fetch(element, how, what)
1611
+ target = eval(code)
1612
+ if target
1613
+ element_wait(target)
1614
+ if target.text.match(expected)
1615
+ passed_to_log(msg)
1616
+ true
1617
+ else
1618
+ failed_to_log("#{msg} Found '#{text}'. #{desc}")
1619
+ end
1620
+ end
1621
+ rescue
1622
+ rescue_msg_for_validation(msg)
1623
+ end
1624
+
1625
+ def does_not_contain_text?(container, element, how, what, expected, desc = '', refs = '')
1626
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}' does not contain '#{expected}'?", refs)
1627
+ code = build_webdriver_fetch(element, how, what)
1628
+ target = eval(code)
1629
+ if target
1630
+ element_wait(target)
1631
+ if target.text.match(expected)
1632
+ failed_to_log("#{msg} Found '#{text}'. #{desc}")
1633
+ else
1634
+ passed_to_log(msg)
1635
+ true
1636
+ end
1637
+ end
1638
+ rescue
1639
+ rescue_msg_for_validation(msg)
1640
+ end
1641
+
1642
+ def element_contains_text?(element, expected, desc = '', refs = '', how = '', what = '', skip_fail = false)
1643
+ msg = element_query_message(element, "text contains '#{expected}'?", how, what, nil, desc, refs)
1644
+ element_wait(element)
1645
+ if element.text.match(expected)
1646
+ passed_to_log(msg)
1647
+ true
1648
+ else
1649
+ if skip_fail
1650
+ debug_to_log(build_msg(msg, "(Fail suppressed)"))
1651
+ else
1652
+ failed_to_log("#{msg} Found '#{element.text}'")
1653
+ end
1654
+ end
1655
+ rescue
1656
+ rescue_msg_for_validation(msg)
1657
+ end
1658
+
1659
+ alias element_text_contains? element_contains_text?
1660
+
1661
+ def element_does_not_contain_text?(element, expected, desc = '', refs = '', how = '', what = '')
1662
+ msg = element_query_message(element, "text does not contain '#{expected}'?", how, what, nil, desc, refs)
1663
+ element_wait(element)
1664
+ if element.text.match(expected)
1665
+ failed_to_log(msg)
1666
+ else
1667
+ passed_to_log(msg)
1668
+ true
1669
+ end
1670
+ rescue
1671
+ rescue_msg_for_validation(msg)
1672
+ end
1673
+
1674
+ alias element_text_does_not_contain? element_does_not_contain_text?
1675
+
1676
+ def directory_exists?(directory)
1677
+ File.directory?(directory)
1678
+ end
1679
+
1680
+ def string_contains?(strg, target, desc = '', refs = '')
1681
+ msg = build_message(desc, "String '#{strg}' contains '#{target}'?", refs)
1682
+ if strg.match(target)
1683
+ passed_to_log(msg)
1684
+ true
1685
+ else
1686
+ failed_to_log(msg)
1687
+ end
1688
+ end
1689
+
1690
+ alias validate_string string_contains?
1691
+ alias validate_string_contains string_contains?
1692
+
1693
+ def string_does_not_contain?(strg, target, desc = '', refs = '')
1694
+ msg = build_message(desc, "String '#{strg}' does not contain '#{target}'?", refs)
1695
+ if strg.match(target)
1696
+ failed_to_log(msg)
1697
+ true
1698
+ else
1699
+ passed_to_log(msg)
1700
+ end
1701
+ end
1702
+
1703
+ def boolean_equals?(actual, expected, desc = '', refs = '')
1704
+ msg = build_message(desc, "Boolean '#{actual}' equals expected '#{expected}'?", refs)
1705
+ if actual == expected
1706
+ passed_to_log(msg)
1707
+ true
1708
+ else
1709
+ failed_to_log(msg)
1710
+ end
1711
+ rescue
1712
+ rescue_msg_for_validation(msg)
1713
+ end
1714
+
1715
+ # def string_contains?(strg, target, desc = '', refs = '')
1716
+ # msg = build_message("String '#{strg}' contains '#{target}'.", desc, refs)
1717
+ # if strg.match(target)
1718
+ # passed_to_log(msg)
1719
+ # true
1720
+ # else
1721
+ # failed_to_log(msg)
1722
+ # end
1723
+ # end
1724
+
1725
+ def string_equals?(actual, expected, desc = '', refs = '')
1726
+ msg = build_message(desc, "String '#{actual}' equals expected '#{expected}'?", refs)
1727
+ if actual == expected
1728
+ passed_to_log(msg)
1729
+ true
1730
+ else
1731
+ failed_to_log(msg)
1732
+ end
1733
+ rescue
1734
+ rescue_msg_for_validation(msg)
1735
+ end
1736
+
1737
+ def string_does_not_equal?(actual, expected, desc = '', refs = '')
1738
+ msg = build_message(desc, "String '#{actual}' does not equal expected '#{expected}'?", refs)
1739
+ if actual == expected
1740
+ failed_to_log(msg)
1741
+ else
1742
+ passed_to_log(msg)
1743
+ true
1744
+ end
1745
+ rescue
1746
+ rescue_msg_for_validation(msg)
1747
+ end
1748
+
1749
+ alias string_not_equal? string_does_not_equal?
1750
+
1751
+ def text_does_not_contain?(container, ptrn, desc = '', refs = '')
1752
+ name = container.respond_to?(:tag_name) ? container.tag_name.titleize : 'DOM'
1753
+ msg = build_message(desc, "#{name} text does not contain '#{ptrn}'?", refs)
1754
+
1755
+ if ptrn.is_a?(Regexp)
1756
+ target = ptrn
1757
+ else
1758
+ target = Regexp.new(Regexp.escape(ptrn))
1759
+ end
1760
+
1761
+ if container.text.match(target)
1762
+ failed_to_log(msg)
1763
+ else
1764
+ passed_to_log(msg)
1765
+ true
1766
+ end
1767
+
1768
+ rescue
1769
+ rescue_msg_for_validation(msg)
1770
+ end
1771
+
1772
+ def text_contains?(container, ptrn, desc = '', refs = '', skip_fail = false, skip_sleep = false)
1773
+ name = container.respond_to?(:tag_name) ? container.tag_name.titleize : 'DOM'
1774
+ msg = build_message(desc, "#{name} text contains '#{ptrn}'?", refs)
1775
+ if ptrn.is_a?(Regexp)
1776
+ target = ptrn
1777
+ else
1778
+ target = Regexp.new(Regexp.escape(ptrn))
1779
+ end
1780
+ # debug_to_log(with_caller(__LINE__))
1781
+ # if container.respond_to?(:wait)
1782
+ # container.wait
1783
+ # elsif container.respond_to?(:wait_until_present)
1784
+ # container.wait_until_present
1785
+ # else
1786
+ # sleep(3)
1787
+ # end
1788
+
1789
+ # sleep_for(10)
1790
+ if container.text.match(target)
1791
+ passed_to_log("#{msg}")
1792
+ true
1793
+ else
1794
+ if skip_fail
1795
+ debug_to_log("#{name} text does not contain the text: '#{ptrn}'. #{desc} (Fail suppressed)")
1796
+ else
1797
+ failed_to_log(msg)
1798
+ end
1799
+ end
1800
+ rescue
1801
+ rescue_msg_for_validation(msg)
1802
+ end
1803
+
1804
+ alias text_equals? text_contains?
1805
+ alias validate_text text_contains?
1806
+ alias element_text_equals? text_contains?
1807
+
1808
+ def validate_html(container, page, force_browser = false, filter = true)
1809
+ mark_testlevel(": #{page}")
1810
+ # require 'nokogiri-pretty'
1811
+ # require 'iconv'
1812
+ require 'diff/lcs'
1813
+
1814
+ if force_browser
1815
+ html = container.browser.html
1816
+ else
1817
+ html = container.html
1818
+ end
1819
+
1820
+ url = container.browser.url
1821
+
1822
+ html_with_line_feeds = html.gsub("\n", '').gsub('>', ">\n")
1823
+ html_with_line_feeds = "<!DOCTYPE html>\n" + html_with_line_feeds unless html_with_line_feeds =~ /^\s*\<\!DOCTYPE/
1824
+
1825
+ pretty_html, html_array = validate_encoding(html_with_line_feeds)
1826
+
1827
+ html_context = html_line_context(html_array, container)
1828
+
1829
+ file_name = page.gsub(' ', '_').gsub('-', '_').gsub('__', '_').gsub(':', '')
1830
+ file_name << "_#{get_timestamp('condensed_seconds')}_pretty.html"
1831
+ spec = File.join(@myRoot, 'log', file_name)
1832
+ file = File.new(spec, 'w')
1833
+ file.puts(pretty_html)
1834
+ file.close
1835
+
1836
+ exceptions = Hash.new
1837
+
1838
+ validate_with_nokogiri(pretty_html, exceptions)
1839
+ validate_with_tidy(url, pretty_html, exceptions)
1840
+ # validate_with_w3c_markup_file(spec, exceptions)
1841
+ validate_with_w3c_markup(pretty_html, exceptions)
1842
+
1843
+ report_html_exceptions(container, exceptions, html_array, html_context, page, filter)
1844
+
1845
+ rescue
1846
+ failed_to_log(unable_to, 2)
1847
+ end
1848
+
1849
+ def validate_encoding(html, encoding = 'UTF-8')
1850
+ # ic = Iconv.new("#{encoding}//IGNORE", encoding)
1851
+ encoded = ''
1852
+
1853
+ html_array = html.split(/\n/)
1854
+ line_number = 1
1855
+
1856
+ html_array.each do |line|
1857
+ # valid_string = ic.iconv(line + ' ')[0..-2]
1858
+ valid_string = line.encode('UTF-16', :invalid => :replace, :replace => '').encode('UTF-8')
1859
+ unless line == valid_string
1860
+ diffs = Diff::LCS.diff(valid_string, line)
1861
+ diffs_arr = diffs[0]
1862
+ debug_to_log("#{diffs_arr}")
1863
+ #TODO make message more meaningful by interpretting the nested array.
1864
+ debug_to_report("line #{line_number}: '#{diffs.to_s}' removed from '#{line}' to avoid W3C invalid UTF-8 characters error")
1865
+ end
1866
+
1867
+ encoded << valid_string << "\n"
1868
+
1869
+ line_number += 1
1870
+ end
1871
+
1872
+ [encoded, html_array]
1873
+
1874
+ rescue
1875
+ failed_to_log(unable_to)
1876
+ end
1877
+
1878
+ def validate_with_nokogiri(html, exceptions)
1879
+ # mark_test_level
1880
+ nokogiri_levels = { '0' => 'None', '1' => 'Warning', '2' => 'Error', '3' => 'Fatal' }
1881
+
1882
+ errors = Nokogiri::HTML(html).errors
1883
+ debug_to_log("Nokogiri: error count: #{errors.length}")
1884
+
1885
+ instance = 1
1886
+ errors.each do |excp|
1887
+ debug_to_log("#{instance.to_s.ljust(4, ' ')}: #{excp}", 4)
1888
+ line = excp.line.to_i
1889
+ column = excp.column.to_i
1890
+ exceptions['nokogiri'] = Hash.new unless exceptions['nokogiri']
1891
+ exceptions['nokogiri'][:excps] = Hash.new unless exceptions['nokogiri'][:excps]
1892
+ exceptions['nokogiri'][:excps][line] = Hash.new unless exceptions['nokogiri'][:excps][line]
1893
+ exceptions['nokogiri'][:excps][line][column] = Hash.new unless exceptions['nokogiri'][:excps][line][column]
1894
+ exceptions['nokogiri'][:excps][line][column][instance] = "line #{line} column #{column} - #{nokogiri_levels[excp.level.to_s]}: #{excp.message} (nokogiri)"
1895
+ instance += 1
1896
+ end
1897
+
1898
+ rescue
1899
+ failed_to_log(unable_to)
1900
+ end
1901
+
1902
+ def validate_with_w3c_markup_file(html, exceptions)
1903
+ # mark_test_level
1904
+ @w3c_markup_validator = MarkupValidator.new(
1905
+ :validator_uri => 'http://wnl-svr017c.wellsfargo.com/w3c-validator/check'
1906
+ ) unless @w3c_markup_validator
1907
+ result = @w3c_markup_validator.validate_file(html)
1908
+ parse_w3c_result(result, exceptions)
1909
+ end
1910
+
1911
+ def validate_with_w3c_markup(html, exceptions)
1912
+ # mark_test_level
1913
+ @w3c_markup_validator = MarkupValidator.new(
1914
+ :validator_uri => 'http://wnl-svr017c.wellsfargo.com/w3c-validator/check'
1915
+ ) unless @w3c_markup_validator
1916
+ result = @w3c_markup_validator.validate_text(html)
1917
+ parse_w3c_result(result, exceptions)
1918
+ end
1919
+
1920
+ def parse_w3c_result(result, exceptions)
1921
+
1922
+ debug_to_log("W3c Markup: #{result.debug_messages}")
1923
+ debug_to_log("W3c Markup: error count: #{result.errors.length}")
1924
+
1925
+ instance = 1
1926
+ result.errors.each do |excp|
1927
+ begin
1928
+ debug_to_log("#{instance.to_s.ljust(4, ' ')}: #{excp}", 4)
1929
+ if excp =~ /not allowed on element/
1930
+ debug_to_log("[#{excp.explanation}]")
1931
+ end
1932
+
1933
+ if excp.line
1934
+ line = excp.line.to_i
1935
+ column = excp.col.to_i
1936
+ exceptions['w3c_markup'] = Hash.new unless exceptions['w3c_markup']
1937
+ exceptions['w3c_markup'][:excps] = Hash.new unless exceptions['w3c_markup'][:excps]
1938
+ exceptions['w3c_markup'][:excps][line] = Hash.new unless exceptions['w3c_markup'][:excps][line]
1939
+ exceptions['w3c_markup'][:excps][line][column] = Hash.new unless exceptions['w3c_markup'][:excps][line][column]
1940
+ exceptions['w3c_markup'][:excps][line][column][instance] = "line #{line} column #{column} - (#{excp.message_id}) #{excp.message} (w3c_markup)"
1941
+ end
1942
+ instance += 1
1943
+ rescue
1944
+ debug_to_log(unable_to("#{instance}"))
1945
+ end
1946
+ end
1947
+
1948
+ rescue
1949
+ failed_to_log(unable_to)
1950
+ end
1951
+
1952
+ def validate_with_tidy(url, html, exceptions)
1953
+ # mark_test_level
1954
+ @html_validator = ::PageValidations::HTMLValidation.new(
1955
+ File.join(@myRoot, 'log'),
1956
+ [
1957
+ #'-access 2'
1958
+ ],
1959
+ {
1960
+ # :ignore_proprietary => true
1961
+ #:gnu_emacs => true
1962
+ }
1963
+ ) unless @html_validator
1964
+
1965
+ validation = @html_validator.validation(html, url)
1966
+ results = validation.exceptions.split(/\n/)
1967
+
1968
+ debug_to_log("HTML Tidy: error count: #{results.length}")
1969
+
1970
+ instance = 1
1971
+ results.each do |excp|
1972
+ debug_to_log("#{instance.to_s.ljust(4, ' ')}: #{excp}", 4)
1973
+ begin
1974
+ mtch = excp.match(/line\s*(\d+)\s*column\s*(\d+)\s*-\s*(.+)$/)
1975
+ if mtch
1976
+ line = mtch[1].to_i
1977
+ column = mtch[2].to_i
1978
+ excp.chomp!
1979
+ exceptions['tidy'] = Hash.new unless exceptions['tidy']
1980
+ exceptions['tidy'][:excps] = Hash.new unless exceptions['tidy'][:excps]
1981
+ exceptions['tidy'][:excps][line] = Hash.new unless exceptions['tidy'][:excps][line]
1982
+ exceptions['tidy'][:excps][line][column] = Hash.new unless exceptions['tidy'][:excps][line][column]
1983
+ exceptions['tidy'][:excps][line][column][instance] = excp + ' (tidy)'
1984
+ end
1985
+ instance += 1
1986
+ rescue
1987
+ debug_to_log(unable_to("#{instance}"))
1988
+ end
1989
+ end
1990
+
1991
+ rescue
1992
+ failed_to_log(unable_to)
1993
+ end
1994
+
1995
+ def report_html_exceptions(container, exceptions, html_array, html_location, page, filter = true, pre_length = 25, post_length = 50)
1996
+ mark_test_level(page)
1997
+ message_to_report(build_message('(Filtering disabled)')) unless filter
1998
+
1999
+ exception_count = 0
2000
+ error_count = 0
2001
+ log_count = 0
2002
+ warn_count = 0
2003
+ ignored_count = 0
2004
+ unknown_count = 0
2005
+ no_filtering = 0
2006
+
2007
+
2008
+ exceptions.keys.sort.each do |validator|
2009
+ mark_test_level("Validator: #{validator.titleize}", 5)
2010
+ exceptions[validator][:tallies] = Hash.new
2011
+ exceptions[validator][:tallies][:ignore] = 0
2012
+ exceptions[validator][:tallies][:log] = 0
2013
+ exceptions[validator][:tallies][:warn] = 0
2014
+ exceptions[validator][:tallies][:fail] = 0
2015
+ exceptions[validator][:tallies][:unknown] = 0
2016
+
2017
+ # debug_to_log("[#{validator}]")
2018
+ exceptions[validator][:excps].keys.sort.each do |line|
2019
+ # debug_to_log("[#{line}]")
2020
+ next unless line.is_a?(Fixnum)
2021
+ exceptions[validator][:excps][line].keys.sort.each do |column|
2022
+ # debug_to_log("[#{column}]")
2023
+ exceptions[validator][:excps][line][column].keys.sort.each do |instance|
2024
+
2025
+ excp = exceptions[validator][:excps][line][column][instance]
2026
+ exception_count += 1
2027
+
2028
+ mtch = excp.match(/line\s*(\d+)\s*column\s*(\d+)\s*-\s*(.+)$/)
2029
+ arr_line = (mtch[1].to_i - 1)
2030
+ int_column = (mtch[2].to_i - 1)
2031
+ desc = mtch[3]
2032
+
2033
+ tag = "#{validator}/#{line}/#{column}/#{instance} "
2034
+ # debug_to_log(tag, 4)
2035
+
2036
+ excerpt = format_html_excerpt(html_array[arr_line], int_column, pre_length, post_length, tag)
2037
+ out = "#{desc}: line #{line} col #{column} #{excerpt}"
2038
+
2039
+ annotate_html_message(out, html_location[arr_line], line, column)
2040
+
2041
+ if filter
2042
+
2043
+ filter_id, action, alt_value = filter_html_exception?(desc, out, html_array[arr_line], validator, html_location[arr_line])
2044
+ alt_value_msg = alt_value ? "'#{alt_value}'" : nil
2045
+
2046
+ if filter_id
2047
+ case action
2048
+ when 'log'
2049
+ log_count += 1
2050
+ exceptions[validator][:tallies][:log] += 1
2051
+ debug_to_log(build_message("LOGGED [#{filter_id}]: #{out}", alt_value_msg), 5)
2052
+ when 'warn'
2053
+ warn_count += 1
2054
+ exceptions[validator][:tallies][:warn] += 1
2055
+ message_to_report(build_message("WARN [#{filter_id}]: #{out}", alt_value_msg), 4)
2056
+ when 'ignore'
2057
+ ignored_count += 1
2058
+ exceptions[validator][:tallies][:ignore] += 1
2059
+ debug_to_log(build_message("IGNORED [#{filter_id}]: #{out}", alt_value_msg), 5)
2060
+ else
2061
+ unknown_count += 1
2062
+ exceptions[validator][:tallies][:unknown] += 1
2063
+ debug_to_log("unknown action '#{action}' [#{filter_id}]: #{out}", 4)
2064
+ end
2065
+ else
2066
+ out.sub!(/Warning:|\(html5\)/i, 'ERROR:')
2067
+ ref, desc, tag, id = fetch_html_err_ref(out)
2068
+ ref = ref.size > 0 ? format_reference(ref) : nil
2069
+ if id
2070
+ elem = container.element(:id, id)
2071
+ debug_to_log(with_caller(build_message(elem.to_subtype, "class=#{elem.class_name}")), 5)
2072
+ end
2073
+ failed_to_log(build_message(out, desc, ref), 6)
2074
+ error_count += 1
2075
+ exceptions[validator][:tallies][:fail] += 1
2076
+ end
2077
+ else
2078
+ debug_to_report(out)
2079
+ no_filtering += 1
2080
+ end
2081
+
2082
+ end
2083
+ end
2084
+ end
2085
+ end
2086
+
2087
+ if error_count > 0
2088
+ message_to_report(with_caller("#{error_count} HTML validation errors reported"))
2089
+ else
2090
+ message_to_report(with_caller('No HTML validation errors reported'))
2091
+ end
2092
+ message_to_report(with_caller("#{warn_count} HTML validation warnings reported")) if warn_count > 0
2093
+ debug_to_log(with_caller("total #{exception_count},", "filtering turned off? #{no_filtering},", " errors #{error_count},",
2094
+ " warn #{warn_count},", " log #{log_count},", " ignored #{ignored_count}",
2095
+ " unknown #{unknown_count}"))
2096
+
2097
+ report_results(error_count, with_caller(page))
2098
+
2099
+ rescue
2100
+ failed_to_log(unable_to)
2101
+ end
2102
+
2103
+ def annotate_html_message(out, location, line, column)
2104
+ if location[:script]
2105
+ out << " (in script #{line}/#{column})"
2106
+ else
2107
+ if location[:head]
2108
+ out << " (in head)"
2109
+ if location[:meta]
2110
+ out << " (in meta)"
2111
+ end
2112
+ end
2113
+ end
2114
+ if location[:in_frame]
2115
+ out << " (in frame)"
2116
+ end
2117
+ # out << " (in meta)" if in_meta
2118
+ # out << " (in body)" if in_body
2119
+ if location[:fragment]
2120
+ out << " (in fragment)"
2121
+ end
2122
+ end
2123
+
2124
+ def fetch_html_err_ref(strg)
2125
+ ref = ''
2126
+ desc = nil
2127
+ tag = nil
2128
+ anchor = nil
2129
+ @html_error_references.each_key do |ptrn|
2130
+ begin
2131
+ mtch = strg.match(ptrn)
2132
+ rescue
2133
+ debug_to_report(with_caller("'#{$!}'"))
2134
+ end
2135
+ if mtch
2136
+ ref = @html_error_references[ptrn][:reference]
2137
+ desc = @html_error_references[ptrn][:description]
2138
+ tag = mtch[1] if mtch[1]
2139
+ case strg
2140
+ when /\s*anchor\s*/
2141
+ anchor = mtch[2] if mtch[2]
2142
+ end
2143
+ break
2144
+ end
2145
+ end
2146
+ [ref, desc, tag, anchor]
2147
+ rescue
2148
+ failed_to_log(unable_to)
2149
+ end
2150
+
2151
+ def format_html_excerpt(line, column, pre_length, post_length, tag)
2152
+ # debug_to_log(with_caller(tag))
2153
+ if line
2154
+ column = 0 if line.size < post_length
2155
+ pre_length = column if column < pre_length
2156
+ pre_excerpt = line.slice(column - pre_length, pre_length)
2157
+ pre_excerpt.gsub!(/^\s+/, '')
2158
+ post_excerpt = line.slice(column, post_length)
2159
+ excerpt = '['
2160
+ excerpt << '...' if (column - pre_length) > 1
2161
+ excerpt << pre_excerpt if pre_excerpt
2162
+ excerpt << '^'
2163
+ excerpt << post_excerpt if post_excerpt
2164
+ excerpt << '...' if line.size >= (pre_length + post_length)
2165
+ excerpt << ']'
2166
+ excerpt.ljust(excerpt.size + 1, ' ')
2167
+ else
2168
+ debug_to_log("Line for #{tag} is nil")
2169
+ end
2170
+ rescue
2171
+ failed_to_log(unable_to)
2172
+ end
2173
+
2174
+ def filter_html_exception?(excp, out, line, validator, location)
2175
+ filter = nil
2176
+ action = nil
2177
+ alt_value = nil
2178
+
2179
+ if @html_filters[validator]
2180
+ @html_filters[validator].each_key do |key|
2181
+ pattern = @html_filters[validator][key][:pattern]
2182
+ if excp.match(pattern)
2183
+ # msg = build_message('(filtered):', "[id:#{key}]", out, @html_filters[validator][key][:description])
2184
+
2185
+ action = @html_filters[validator][key][:action]
2186
+
2187
+ filter, action, alt_value = html_alt_filter(validator, key, action, line, location)
2188
+
2189
+ case action
2190
+ when /ignore|log|warn/i
2191
+ filter = key
2192
+ when /fail/i
2193
+ filter = nil
2194
+ else
2195
+ debug_to_log(with_caller("Unknown action '#{action}'"))
2196
+ filter = nil
2197
+ end
2198
+ break
2199
+ end
2200
+ end
2201
+ end
2202
+ [filter, action, alt_value]
2203
+ rescue
2204
+ failed_to_log(unable_to)
2205
+ end
2206
+
2207
+ def html_alt_filter(validator, key, action, line, location)
2208
+ filter = key
2209
+ alt_action = action
2210
+ mtch_value = nil
2211
+
2212
+ if @html_filters[validator][key][:alt_pattern]
2213
+
2214
+ alt_pattern = @html_filters[validator][key][:alt_pattern]
2215
+ mtch = line.match(alt_pattern)
2216
+ if mtch
2217
+ mtch_value = mtch[1] if mtch[1]
2218
+ alt_action = @html_filters[validator][key][:alt_action]
2219
+ case alt_action
2220
+ when ''
2221
+ filter = nil
2222
+ when /fail/i
2223
+ filter = nil
2224
+ when /ignore/i, /warn/i, /log/i
2225
+ filter = key
2226
+ else
2227
+ debug_to_log(with_caller("Unknown alt_action '#{alt_action}'"))
2228
+ alt_action = 'warn'
2229
+ end
2230
+
2231
+ else
2232
+ alt_action = action
2233
+ filter = nil if action =~ /fail/i
2234
+ end
2235
+
2236
+ else
2237
+ # TODO This hierarchy is over simple.
2238
+ # NOTE: Current assumption is that first found wins
2239
+ # NOTE: and only one will be set with an action for a given filter
2240
+ [:script, :meta, :head, :body, :fragment, :frame].each do |loc|
2241
+ if location[loc] and @html_filters[validator][key][loc]
2242
+ alt_action = @html_filters[validator][key][loc]
2243
+ filter = nil if alt_action =~ /fail/i
2244
+ break
2245
+ end
2246
+ end
2247
+ end
2248
+
2249
+ [filter, alt_action, mtch_value]
2250
+ rescue
2251
+ failed_to_log(unable_to, 2)
2252
+ end
2253
+
2254
+ def html_line_context(html, container)
2255
+ in_script = false
2256
+ in_head = false
2257
+ in_meta = false
2258
+ in_body = false
2259
+ in_frame = false
2260
+ in_fragment = false
2261
+
2262
+ line = 0
2263
+ hash = {}
2264
+ container_class = container.class.to_s
2265
+ debug_to_log("container class='#{container_class}'")
2266
+
2267
+ case container_class
2268
+ when /frame/i
2269
+ in_frame = true
2270
+ when /browser/i
2271
+ in_frame = false
2272
+ else
2273
+ in_fragment = true
2274
+ end
2275
+ html.each do |l|
2276
+ target = l.dup.strip
2277
+
2278
+ hash[line] = Hash.new
2279
+
2280
+ hash[line][:frame] = in_frame
2281
+ hash[line][:fragment] = in_fragment
2282
+
2283
+ in_script = true if target.match(/^\s*<script/)
2284
+ in_head = true if target.match(/^\s*<head>/)
2285
+ in_meta = true if target.match(/^\s*<meta/)
2286
+ in_body = true if target.match(/^\s*<body/)
2287
+
2288
+ hash[line][:script] = in_script
2289
+ hash[line][:head] = in_head
2290
+ hash[line][:meta] = in_meta
2291
+ hash[line][:body] = in_body
2292
+
2293
+ in_script = false if target.match(/^\s*<script.*\/>$/)
2294
+ in_script = false if target.match(/<\/script>$/)
2295
+ in_head = false if target.match(/<\/head>/)
2296
+ in_meta = false if target.match(/<\/meta.*\/>$/)
2297
+ in_script = false if target.match(/<\/meta>$/)
2298
+ in_body = false if target.match(/<\/body/)
2299
+
2300
+ line += 1
2301
+ end
2302
+
2303
+ hash
2304
+ end
2305
+
2306
+ def text_does_not_equal?(container, ptrn, desc = '', refs = '')
2307
+ name = container.respond_to?(:tag_name) ? container.tag_name.titleize : 'DOM'
2308
+ msg = build_message(desc, "#{name} text contains '#{ptrn}'?", refs)
2309
+ if ptrn.is_a?(Regexp)
2310
+ target = ptrn
2311
+ else
2312
+ target = Regexp.new(Regexp.escape(ptrn))
2313
+ end
2314
+ if container.respond_to?(:wait)
2315
+ container.wait
2316
+ elsif container.respond_to?(:wait_until_present)
2317
+ container.wait_until_present
2318
+ else
2319
+ sleep(3)
2320
+ end
2321
+ if container.text.match(target)
2322
+ failed_to_log(msg)
2323
+ else
2324
+ passed_to_log("#{msg}")
2325
+ true
2326
+ end
2327
+ rescue
2328
+ failed_to_log(unable_to)
2329
+ end
2330
+
2331
+ alias validate_no_text text_does_not_equal?
2332
+ alias element_text_does_not_equal? text_does_not_equal?
2333
+
2334
+ def textfield_equals?(browser, how, what, expected, desc = '', refs = '')
2335
+ msg = build_message(desc, "Expected value to equal '#{expected}' in textfield #{how}='#{what}'?", refs)
2336
+ actual = browser.text_field(how, what).value
2337
+ if actual.is_a?(Array)
2338
+ actual = actual[0].to_s
2339
+ end
2340
+ if actual == expected
2341
+ passed_to_log(msg)
2342
+ true
2343
+ else
2344
+ act_s = actual.strip
2345
+ exp_s = expected.strip
2346
+ if act_s == exp_s
2347
+ passed_to_log("#{msg} (stripped)")
2348
+ true
2349
+ else
2350
+ debug_to_report(
2351
+ "#{__method__} (spaces underscored):\n "+
2352
+ "expected:[#{expected.gsub(' ', '_')}] (#{expected.length})\n "+
2353
+ "actual:[#{actual.gsub(' ', '_')}] (#{actual.length}) (spaces underscored)"
2354
+ )
2355
+ failed_to_log("#{msg}. Found: '#{actual}'")
2356
+ end
2357
+ end
2358
+ rescue
2359
+ failed_to_log(unable_to("#{how}='#{what}'", false, true))
2360
+ end
2361
+
2362
+ alias validate_textfield_value textfield_equals?
2363
+ alias text_field_equals? textfield_equals?
2364
+
2365
+ def textfield_contains?(container, how, what, expected, desc = '', refs = '')
2366
+ msg = build_message(desc, "Does text field #{how}='#{what}' contains '#{expected}'?", refs)
2367
+ contents = container.text_field(how, what).when_present.value
2368
+ if contents =~ /#{expected}/
2369
+ passed_to_log(msg)
2370
+ true
2371
+ else
2372
+ failed_to_log("#{msg} Contents: '#{contents}'")
2373
+ end
2374
+ rescue
2375
+ rescue_msg_for_validation(msg)
2376
+ end
2377
+
2378
+ alias text_field_contains? textfield_contains?
2379
+
2380
+ def textfield_empty?(browser, how, what, desc = '', refs = '')
2381
+ msg = build_message(desc, "Text field #{how}='#{what}' is empty?", refs)
2382
+ contents = browser.text_field(how, what).value
2383
+ if contents.to_s.length == 0
2384
+ passed_to_log(msg)
2385
+ true
2386
+ else
2387
+ failed_to_log("#{msg} Contents: '#{contents}'")
2388
+ end
2389
+ rescue
2390
+ rescue_msg_for_validation(msg)
2391
+ end
2392
+
2393
+ alias validate_textfield_empty textfield_empty?
2394
+ alias text_field_empty? textfield_empty?
2395
+
2396
+ def existence(container, should_be, element, how, what, value = nil, desc = '', refs = '', options = {})
2397
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2398
+ code = build_webdriver_fetch(element, how, what, options)
2399
+ target = eval(code)
2400
+ if should_be
2401
+ element_exists?(target, desc, refs, how, what, value)
2402
+ else
2403
+ element_does_not_exist?(target, desc, refs, how, what, value)
2404
+ end
2405
+ rescue
2406
+ failed_to_log(unable_to(desc, false, true))
2407
+ end
2408
+
2409
+ def element_existence(element, should_be, desc = '', refs = '', how = '', what = '')
2410
+ should_be = force_boolean(should_be)
2411
+ if should_be
2412
+ element_exists?(element, desc, refs, how, what, nil)
2413
+ else
2414
+ element_does_not_exist?(element, desc, refs, how, what, nil)
2415
+ end
2416
+ rescue
2417
+ rescue_msg_for_validation(desc, refs)
2418
+ end
2419
+
2420
+ def exists?(container, element, how, what, value = nil, desc = '', refs = '', options = {})
2421
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2422
+ code = build_webdriver_fetch(element, how, what, options)
2423
+ target = eval(code)
2424
+ element_exists?(target, desc, refs, how, what, value)
2425
+ rescue
2426
+ rescue_msg_for_validation(desc, refs)
2427
+ end
2428
+
2429
+ def element_exists?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
2430
+ msg = element_query_message(element, 'exists?', how, what, value, desc, refs)
2431
+ if element.exists?
2432
+ passed_to_log(msg)
2433
+ true
2434
+ else
2435
+ failed_to_log(msg)
2436
+ end
2437
+ rescue
2438
+ rescue_msg_for_validation(msg)
2439
+ end
2440
+
2441
+ def does_not_exist?(container, element, how, what, value = nil, desc = '', refs = '', options = {})
2442
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2443
+ code = build_webdriver_fetch(element, how, what, options)
2444
+ target = eval(code)
2445
+ element_does_not_exist?(target, value, desc, refs, how, what, element)
2446
+ rescue
2447
+ rescue_msg_for_validation(desc, refs)
2448
+ end
2449
+
2450
+ def element_does_not_exist?(element, value = nil, desc = '', refs = '', how = nil, what = nil, tag = nil)
2451
+ msg = element_query_message(element, 'does not exist?', how, what, value, desc, refs, tag)
2452
+ if element.exists?
2453
+ failed_to_log(msg)
2454
+ else
2455
+ passed_to_log(msg)
2456
+ true
2457
+ end
2458
+ rescue
2459
+ rescue_msg_for_validation(msg)
2460
+ end
2461
+
2462
+ def presence(container, should_be, element, how, what, value = nil, desc = '', refs = '')
2463
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2464
+ code = build_webdriver_fetch(element, how, what, options)
2465
+ target = eval(code)
2466
+ if should_be
2467
+ element_is_present?(target, desc, refs, how, what, value)
2468
+ else
2469
+ element_not_present?(target, desc, refs, how, what, value)
2470
+ end
2471
+ rescue
2472
+ failed_to_log(unable_to(desc, false, true))
2473
+ end
2474
+
2475
+ def element_presence(element, should_be, desc = '', refs = '', how = '', what = '')
2476
+ should_be = force_boolean(should_be)
2477
+ if should_be
2478
+ element_is_present?(element, desc, refs, how, what, nil)
2479
+ else
2480
+ element_not_present?(element, desc, refs, how, what, nil)
2481
+ end
2482
+ rescue
2483
+ rescue_msg_for_validation(desc, refs)
2484
+ end
2485
+
2486
+ def is_present?(container, element, how, what, value = nil, desc = '', refs = '', options = {})
2487
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2488
+ code = build_webdriver_fetch(element, how, what, options)
2489
+ target = eval(code)
2490
+ element_is_present?(target, desc, refs, how, what, value)
2491
+ rescue
2492
+ failed_to_log(unable_to(build_msg(element, how, what, value), false, true))
2493
+ end
2494
+
2495
+ def element_is_present?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
2496
+ msg = element_query_message(element, 'is_present?', how, what, value, desc, refs)
2497
+ if element.present?
2498
+ passed_to_log(msg)
2499
+ true
2500
+ else
2501
+ failed_to_log(msg)
2502
+ end
2503
+ rescue
2504
+ rescue_msg_for_validation(msg)
2505
+ end
2506
+
2507
+ alias element_present? element_is_present?
2508
+
2509
+ def not_present?(container, element, how, what, value = nil, desc = '', refs = '', options = {})
2510
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2511
+ code = build_webdriver_fetch(element, how, what, options)
2512
+ target = eval(code)
2513
+ element_not_present?(target, desc, refs, how, what, value)
2514
+ rescue
2515
+ failed_to_log(unable_to(build_msg(element, how, what, value), false, true))
2516
+ end
2517
+
2518
+ def element_not_present?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
2519
+ msg = element_query_message(element, 'is not present?', how, what, value, desc, refs)
2520
+ if element.present?
2521
+ failed_to_log(msg)
2522
+ else
2523
+ passed_to_log(msg)
2524
+ true
2525
+ end
2526
+ rescue
2527
+ rescue_msg_for_validation(msg)
2528
+ end
2529
+
2530
+ alias element_is_not_present? element_not_present?
2531
+
2532
+ def force_boolean(boolean)
2533
+ case boolean
2534
+ when true, false
2535
+ should_be = boolean
2536
+ when /yes/i, /true/i
2537
+ should_be = true
2538
+ else
2539
+ should_be = false
2540
+ end
2541
+ should_be
2542
+ end
2543
+
2544
+ def expected_url?(container, expected, desc = '', refs = '')
2545
+ msg = build_message(desc, "Is browser at url #{expected}?", refs)
2546
+ if container.url == expected
2547
+ passed_to_log(msg)
2548
+ true
2549
+ else
2550
+ failed_to_log("#{msg} Found #{container.url}")
2551
+ end
2552
+ rescue
2553
+ rescue_msg_for_validation(msg)
2554
+ end
2555
+
2556
+ def not_focused?(container, element, how, what, value = nil, desc = '', refs = '', options = {})
2557
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2558
+ code = build_webdriver_fetch(element, how, what, options)
2559
+ target = eval(code)
2560
+ element_not_focused?(target, how, what, value, desc, refs)
2561
+ rescue
2562
+ rescue_msg_for_validation(build_msg(element, how, what), refs)
2563
+ end
2564
+
2565
+ alias is_not_focused? not_focused?
2566
+
2567
+ def element_not_focused?(element, how, what, value = nil, desc = '', refs = '')
2568
+ msg = element_query_message(element, 'does not have focus?', how, what, value, desc, refs)
2569
+ current = element.browser.execute_script("return document.activeElement")
2570
+ if element == current
2571
+ failed_to_log(msg)
2572
+ else
2573
+ passed_to_log(msg)
2574
+ true
2575
+ end
2576
+ rescue
2577
+ rescue_msg_for_validation(msg)
2578
+ end
2579
+
2580
+ alias element_is_not_focused? element_not_focused?
2581
+
2582
+ def is_focused?(container, element, how, what, value = nil, desc = '', refs = '', options = {})
2583
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2584
+ code = build_webdriver_fetch(element, how, what, options)
2585
+ target = eval(code)
2586
+ element_focused?(target, how, what, value, desc, refs)
2587
+ rescue
2588
+ rescue_msg_for_validation(build_msg(element, how, what), refs)
2589
+ end
2590
+
2591
+ def element_focused?(element, how, what, value = nil, desc = '', refs = '')
2592
+ msg = element_query_message(element, 'has focus?', how, what, value, desc, refs)
2593
+ current = element.browser.execute_script("return document.activeElement")
2594
+ if element == current
2595
+ passed_to_log(msg)
2596
+ true
2597
+ else
2598
+ failed_to_log(msg)
2599
+ end
2600
+ rescue
2601
+ rescue_msg_for_validation(msg)
2602
+ end
2603
+
2604
+ alias element_is_focused? element_focused?
2605
+
2606
+ def visibility(container, boolean, element, how, what, desc = '', refs = '')
2607
+ should_be = force_boolean(boolean)
2608
+ if should_be
2609
+ visible?(container, element, how, what, desc, refs)
2610
+ else
2611
+ not_visible?(container, element, how, what, desc, refs)
2612
+ end
2613
+ rescue
2614
+ rescue_msg_for_validation(build_msg(element, how, what), refs)
2615
+ end
2616
+
2617
+ def visible?(container, element, how, what, desc = '', refs = '')
2618
+ code = build_webdriver_fetch(element, how, what)
2619
+ target = eval(code)
2620
+ element_visible?(target, desc, refs, how, what)
2621
+ rescue
2622
+ rescue_msg_for_validation(build_msg(element, how, what), refs)
2623
+ end
2624
+
2625
+ def element_visible?(element, desc = '', refs = '', how = nil, what = nil)
2626
+ msg = element_query_message(element, 'is visible?', how, what, nil, desc, refs)
2627
+ if element.visible?
2628
+ passed_to_log(msg)
2629
+ true
2630
+ else
2631
+ failed_to_log(msg)
2632
+ end
2633
+ rescue
2634
+ rescue_msg_for_validation(msg)
2635
+ end
2636
+
2637
+ def not_visible?(container, element, how, what, desc = '', refs = '')
2638
+ code = build_webdriver_fetch(element, how, what)
2639
+ target = eval(code)
2640
+ element_not_visible?(target, desc, refs, how, what)
2641
+ rescue
2642
+ failed_to_log(unable_to(build_msg(element, how, what), false, true))
2643
+ end
2644
+
2645
+ def element_not_visible?(element, desc = '', refs = '', how = nil, what = nil)
2646
+ msg = element_query_message(element, 'is not visible?', how, what, nil, desc, refs)
2647
+ if element.visible?
2648
+ failed_to_log(msg)
2649
+ else
2650
+ passed_to_log(msg)
2651
+ true
2652
+ end
2653
+ rescue
2654
+ rescue_msg_for_validation(msg)
2655
+ end
2656
+
2657
+ def disablement(container, boolean, element, how, what, desc = '', refs = '')
2658
+ should_be = force_boolean(boolean)
2659
+ if should_be
2660
+ disabled?(container, element, how, what, desc, nil, refs)
2661
+ else
2662
+ enabled?(container, element, how, what, desc, nil, refs)
2663
+ end
2664
+ rescue
2665
+ failed_to_log(unable_to(desc, false, true))
2666
+ end
2667
+
2668
+ def disabled?(container, element, how, what, desc = '', value = nil, refs = '', options = {})
2669
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2670
+ code = build_webdriver_fetch(element, how, what, options)
2671
+ target = eval(code)
2672
+ element_disabled?(target, desc, refs, how, what, value)
2673
+ rescue
2674
+ failed_to_log(unable_to(build_msg(element, how, what, value), false, true))
2675
+ end
2676
+
2677
+ def element_disabled?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
2678
+ msg = element_query_message(element, 'is disabled?', how, what, value, desc, refs)
2679
+ element_wait(element)
2680
+ if element.respond_to?(:disabled?)
2681
+ if element.disabled?
2682
+ passed_to_log(msg)
2683
+ true
2684
+ else
2685
+ failed_to_log(msg)
2686
+ end
2687
+ else
2688
+ failed_to_log(build_message("#{element} does not respond to .disabled?"), msg)
2689
+ end
2690
+ rescue
2691
+ rescue_msg_for_validation(msg)
2692
+ end
2693
+
2694
+ def not_disabled?(container, element, how, what, desc = '', value = nil, refs = '', options = {})
2695
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
2696
+ code = build_webdriver_fetch(element, how, what, options)
2697
+ target = eval(code)
2698
+ element_not_disabled?(target, desc, refs, how, what, value)
2699
+ rescue
2700
+ failed_to_log(unable_to(build_msg(element, how, what, value), false, true))
2701
+ end
2702
+
2703
+ alias enabled? not_disabled?
2704
+
2705
+ def element_not_disabled?(element, desc = '', refs = '', how = nil, what = nil, value = nil)
2706
+ msg = element_query_message(element, 'is enabled?', how, what, value, desc, refs)
2707
+ element_wait(element)
2708
+ if element.disabled?
2709
+ failed_to_log(msg)
2710
+ else
2711
+ passed_to_log(msg)
2712
+ true
2713
+ end
2714
+ rescue
2715
+ rescue_msg_for_validation(msg)
2716
+ end
2717
+
2718
+ alias element_enabled? element_not_disabled?
2719
+
2720
+ def element_disablement(target, disabled, desc = '', refs = '')
2721
+ #TODO: Is this really necessary?
2722
+ is_disabled = target.disabled?
2723
+ disablement = false
2724
+ should_be = disabled ? true : false
2725
+ msg = build_message(desc, "(in #{method_to_title(__method__)})", "should be #{should_be}", "is #{is_disabled}", refs)
2726
+ if should_be == is_disabled
2727
+ passed_to_log(msg)
2728
+ disablement = true
2729
+ else
2730
+ failed_to_log(msg)
2731
+ end
2732
+ [is_disabled, disablement]
2733
+ rescue
2734
+ rescue_msg_for_validation(msg)
2735
+ end
2736
+
2737
+ def pixels_do_not_equal?(container, element, how, what, style, expected, desc = '', refs = '', rounding = 'up')
2738
+ code = build_webdriver_fetch(element, how, what)
2739
+ actual = eval("#{code}.style('#{style}')")
2740
+
2741
+ if actual =~ /px$/
2742
+ expected = expected.to_s + 'px'
2743
+ else
2744
+ case rounding
2745
+ when 'ceil', 'up'
2746
+ actual = actual.to_f.ceil
2747
+ when 'down', 'floor'
2748
+ actual = actual.to_f.floor
2749
+ else
2750
+ actual = actual.to_f.round
2751
+ end
2752
+ end
2753
+
2754
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}'", "pixel size '#{style}",
2755
+ "equals '#{expected}' (with rounding #{rounding})?", refs)
2756
+
2757
+ if actual == expected
2758
+ failed_to_log("#{msg} Found '#{actual}'")
2759
+ else
2760
+ passed_to_log(msg)
2761
+ true
2762
+ end
2763
+ rescue
2764
+ rescue_msg_for_validation(desc, refs)
2765
+ end
2766
+
2767
+ alias pixels_not_equal? pixels_do_not_equal?
2768
+
2769
+ def pixels_equal?(container, element, how, what, style, expected, desc = '', refs = '', rounding = 'up')
2770
+ code = build_webdriver_fetch(element, how, what)
2771
+ actual = eval("#{code}.style('#{style}')")
2772
+
2773
+ if actual =~ /px$/
2774
+ expected = expected.to_s + 'px'
2775
+ else
2776
+ case rounding
2777
+ when 'ceil', 'up'
2778
+ actual = actual.to_f.ceil
2779
+ when 'down', 'floor'
2780
+ actual = actual.to_f.floor
2781
+ else
2782
+ actual = actual.to_f.round
2783
+ end
2784
+ end
2785
+
2786
+ msg = build_message(desc, "Element #{element.to_s.upcase} :#{how}='#{what}'", "attribute '#{style}",
2787
+ "equals '#{expected}' (with rounding #{rounding})?", refs)
2788
+
2789
+ if actual == expected
2790
+ passed_to_log(msg)
2791
+ true
2792
+ else
2793
+ failed_to_log("#{msg} Found '#{actual}'")
2794
+ end
2795
+ rescue
2796
+ rescue_msg_for_validation(desc, refs)
2797
+ end
2798
+
2799
+ def style_does_not_contain?(container, element, how, what, style, expected, desc = '', refs = '')
2800
+ code = build_webdriver_fetch(element, how, what)
2801
+ target = eval("#{code}")
2802
+ element_style_does_not_contain?(target, style, expected, desc, refs, how, what)
2803
+ rescue
2804
+ failed_to_log(unable_to(build_msg(element, how, what, style), false, true))
2805
+ end
2806
+
2807
+ def element_style_does_not_contain?(element, style, expected, desc = '', refs = '', how = nil, what = nil)
2808
+ msg = element_query_message(element, "style '#{style}' does not contain '#{expected}'?", how, what, nil, desc, refs)
2809
+ element_wait(element)
2810
+ if element.style(style).match(expected)
2811
+ failed_to_log(msg)
2812
+ else
2813
+ passed_to_log(msg)
2814
+ true
2815
+ end
2816
+ rescue
2817
+ rescue_msg_for_validation(msg)
2818
+ end
2819
+
2820
+ def style_contains?(container, element, how, what, style, expected, desc = '', refs = '')
2821
+ code = build_webdriver_fetch(element, how, what)
2822
+ target = eval("#{code}")
2823
+ element_style_contains?(target, style, expected, desc, refs, how, what)
2824
+ rescue
2825
+ failed_to_log(unable_to(build_msg(element, how, what, style), false, true))
2826
+ end
2827
+
2828
+ def element_style_contains?(element, style, expected, desc = '', refs = '', how = nil, what = nil)
2829
+ msg = element_query_message(element, "style '#{style}' contains '#{expected}'?", how, what, nil, desc, refs)
2830
+ element_wait(element)
2831
+ if element.style(style).match(expected)
2832
+ passed_to_log(msg)
2833
+ true
2834
+ else
2835
+ failed_to_log("#{msg}. Found '#{element.class_name}'")
2836
+ end
2837
+ rescue
2838
+ rescue_msg_for_validation(msg)
2839
+ end
2840
+
2841
+ def style_does_not_equal?(container, element, how, what, style, expected, desc = '', refs = '')
2842
+ code = build_webdriver_fetch(element, how, what)
2843
+ target = eval("#{code}")
2844
+
2845
+ element_style_does_not_equal?(target, style, expected, desc, refs, how, what)
2846
+ rescue
2847
+ rescue_msg_for_validation(desc, refs)
2848
+ end
2849
+
2850
+ alias color_not_equal? style_does_not_equal?
2851
+ alias style_not_equal? style_does_not_equal?
2852
+ alias color_does_not_equal? style_does_not_equal?
2853
+
2854
+ def element_style_does_not_equal?(element, style, expected, desc = '', refs = '', how = nil, what = nil)
2855
+ msg = element_query_message(element, "style '#{style}' does not equal '#{expected}'?", how, what, nil, desc, refs)
2856
+ actual = element.style(style)
2857
+ actual_norm = style =~ /color/ ? normalize_color_value(actual) : actual
2858
+ expected_norm = style =~ /color/ ? normalize_color_value(expected) : expected
2859
+
2860
+ if actual
2861
+ if actual_norm == expected_norm
2862
+ failed_to_log(msg)
2863
+ else
2864
+ found = style =~ /color/ ? "#{rgb_to_html(actual).upcase} (#{actual_norm})" : "#{actual}"
2865
+ passed_to_log("#{msg}. Found #{found}")
2866
+ true
2867
+ end
2868
+ else
2869
+ failed_to_log("#{msg} '#{attribute}' not found.")
2870
+ end
2871
+
2872
+ rescue
2873
+ rescue_msg_for_validation(msg)
2874
+ end
2875
+
2876
+ alias element_color_does_not_equal? element_style_does_not_equal?
2877
+ alias element_color_not_equal? element_style_does_not_equal?
2878
+ alias element_style_not_equal? element_style_does_not_equal?
2879
+
2880
+ def style_equals?(container, element, how, what, style, expected, desc = '', refs = '')
2881
+ code = build_webdriver_fetch(element, how, what)
2882
+ target = eval("#{code}")
2883
+ element_style_equals?(target, style, expected, desc, refs, how, what)
2884
+ rescue
2885
+ rescue_msg_for_validation(desc, refs)
2886
+ end
2887
+
2888
+ alias color_equals? style_equals?
2889
+
2890
+ def element_style_equals?(element, style, expected, desc = '', refs = '', how = nil, what = nil)
2891
+ msg = element_query_message(element, "style '#{style}' equals '#{expected}'?", how, what, nil, desc, refs)
2892
+ actual = element.style(style)
2893
+ actual = element.attribute_value(style) unless actual and actual.length > 0
2894
+ case style
2895
+ when /color/
2896
+ actual_norm = normalize_color_value(actual)
2897
+ expected_norm = normalize_color_value(expected)
2898
+ when /opacity/
2899
+ actual_norm = actual.to_f
2900
+ expected_norm = expected.to_f
2901
+ when /border/
2902
+ actual_norm = normalize_border_style(actual)
2903
+ expected_norm = normalize_border_style(expected)
2904
+ else
2905
+ actual_norm = actual
2906
+ expected_norm = expected
2907
+ end
2908
+
2909
+ # if style =~ /color/
2910
+ # debug_to_log(with_caller("'#{style}'", "actual: raw: '" + actual + "' normalized: '" + actual_norm + "'"))
2911
+ # debug_to_log(with_caller("'#{style}'", "expected: raw: '" + expected + "' normalized: '" + expected_norm + "'"))
2912
+ # end
2913
+
2914
+ if actual and actual.length > 0
2915
+ if actual_norm == expected_norm
2916
+ passed_to_log(msg)
2917
+ true
2918
+ else
2919
+ found = style =~ /color/ ? "#{rgb_to_html(actual)} (#{actual_norm})" : "#{actual}"
2920
+ failed_to_log("#{msg}. Found #{found}")
2921
+ end
2922
+ else
2923
+ failed_to_log("#{msg} '#{style}' not found.")
2924
+ end
2925
+
2926
+ rescue
2927
+ rescue_msg_for_validation(msg)
2928
+ end
2929
+
2930
+ alias element_color_equals? element_style_equals?
2931
+
2932
+ def border_colors_equal?(container, element, how, what, desc, refs, *colors)
2933
+ code = build_webdriver_fetch(element, how, what)
2934
+ target = eval(code)
2935
+ element_border_colors_equal?(target, how, what, desc, refs, *colors)
2936
+ rescue
2937
+ rescue_msg_for_validation(desc, refs)
2938
+ end
2939
+
2940
+ def element_border_colors_equal?(element, how, what, desc, refs, *colors)
2941
+ msg = element_query_message(element, "Border colors are '#{colors}'?", how, what, nil, desc, refs)
2942
+ errors = 0
2943
+ errs = []
2944
+
2945
+ sides = ['top', 'bottom', 'left', 'right']
2946
+ sides.each do |side|
2947
+ idx = sides.index(side)
2948
+ color = colors[idx] ? colors[idx] : colors[0]
2949
+ expected = normalize_color_value(color)
2950
+ debug_to_log(with_caller(desc, side, 'expected normalized:', expected))
2951
+ actual = normalize_color_value(element.style("border-#{side}-color"))
2952
+ unless actual == expected
2953
+ errors += 1
2954
+ errs << "#{side}:#{actual}"
2955
+ end
2956
+ end
2957
+
2958
+ if errors == 0
2959
+ passed_to_log(with_caller(msg))
2960
+ true
2961
+ else
2962
+ failed_to_log(with_caller(msg, "Found #{nice_array(errs)}"))
2963
+ end
2964
+
2965
+ rescue
2966
+ rescue_msg_for_validation(msg)
2967
+ end
2968
+
2969
+ def border_sizes_equal?(container, element, how, what, attribute, desc, refs, *pixels)
2970
+ code = build_webdriver_fetch(element, how, what)
2971
+ target = eval(code)
2972
+ element_border_sizes_equal?(target, how, what, attribute, desc, refs, *pixels)
2973
+ rescue
2974
+ rescue_msg_for_validation(desc, refs)
2975
+ end
2976
+
2977
+ def element_border_sizes_equal?(element, how, what, attribute, desc, refs, *pixels)
2978
+ attribute = attribute.downcase.gsub(/s$/, '')
2979
+ errors = 0
2980
+
2981
+ sides = ['top', 'bottom', 'left', 'right']
2982
+
2983
+ sides.each do |side|
2984
+ msg = element_query_message(element, "#{attribute}-#{side} equals '#{pixels}'?", how, what, nil, desc, refs)
2985
+ idx = sides.index(side)
2986
+ value = pixels[idx] ? pixels[idx] : pixels[0]
2987
+ expected = value =~ /px$/ ? value.to_s : "#{value}px"
2988
+ actual = element.style("#{attribute}-#{side}")
2989
+ if actual == expected
2990
+ passed_to_log(msg)
2991
+ else
2992
+ failed_to_log(msg)
2993
+ errors += 1
2994
+ end
2995
+ end
2996
+
2997
+ errors == 0
2998
+
2999
+ rescue
3000
+ rescue_msg_for_validation(desc, refs)
3001
+ end
3002
+
3003
+ def margins_equal?(container, element, how, what, desc, refs, *pixels)
3004
+ border_sizes_equal?(container, element, how, what, 'margins', desc, refs, *pixels)
3005
+ end
3006
+
3007
+ def borders_equal?(container, element, how, what, desc, refs, *pixels)
3008
+ border_sizes_equal?(container, element, how, what, 'borders', desc, refs, *pixels)
3009
+ end
3010
+
3011
+ def padding_equal?(container, element, how, what, desc, refs, *pixels)
3012
+ border_sizes_equal?(container, element, how, what, 'padding', desc, refs, *pixels)
3013
+ end
3014
+
3015
+ def select_list_includes?(browser, how, what, which, option, desc = '', refs = '')
3016
+ msg = build_message(desc, "Select list #{how}='#{what}' includes option with #{which}='#{option}'?", refs)
3017
+ select_list = browser.select_list(how, what)
3018
+ options = select_list.options
3019
+ case which
3020
+ when :text
3021
+ found = false
3022
+ options.each do |opt|
3023
+ if opt.text == option
3024
+ found = true
3025
+ break
3026
+ end
3027
+ end
3028
+ if found
3029
+ passed_to_log(msg)
3030
+ true
3031
+ else
3032
+ failed_to_log(msg)
3033
+ end
3034
+ else
3035
+ if options.include?(option)
3036
+ passed_to_log(msg)
3037
+ true
3038
+ else
3039
+ failed_to_log(msg)
3040
+ end
3041
+ end
3042
+ rescue
3043
+ rescue_msg_for_validation(msg)
3044
+ end
3045
+
3046
+ def select_list_does_not_include?(browser, how, what, which, option, desc = '', refs = '')
3047
+ msg = build_message(desc, "Select list #{how}='#{what}' does not include option with #{which}='#{option}'?", refs)
3048
+ select_list = browser.select_list(how, what)
3049
+ options = select_list.options
3050
+ case which
3051
+ when :text
3052
+ found = false
3053
+ options.each do |opt|
3054
+ if opt.text == option
3055
+ found = true
3056
+ break
3057
+ end
3058
+ end
3059
+ if found
3060
+ failed_to_log(msg)
3061
+ else
3062
+ passed_to_log(msg)
3063
+ true
3064
+ end
3065
+ else
3066
+ if options.include?(option)
3067
+ failed_to_log(msg)
3068
+ else
3069
+ passed_to_log(msg)
3070
+ true
3071
+ end
3072
+ end
3073
+ rescue
3074
+ failed_to_log("Unable to verify #{msg}. '#{$!}'")
3075
+ end
3076
+
3077
+ def validate_selected_options(browser, how, what, list, desc = '', refs = '', which = :text)
3078
+ selected_options = browser.select_list(how, what).selected_options.dup
3079
+ selected = extract_selected(selected_options, which)
3080
+ sorted_list = list.dup.sort
3081
+ if list.is_a?(Array)
3082
+ msg = build_message(desc, "Expected options [#{list.sort}] are selected by #{which} [#{selected}]?", refs)
3083
+ if selected == sorted_list
3084
+ passed_to_log(msg)
3085
+ true
3086
+ else
3087
+ failed_to_log(msg)
3088
+ end
3089
+ else
3090
+ if selected.length == 1
3091
+ msg = build_message(desc, "Expected option [#{list}] was selected by #{which}?", refs)
3092
+ esc_list = Regexp.escape(list)
3093
+ if selected[0] =~ /#{esc_list}/
3094
+ passed_to_log(msg)
3095
+ true
3096
+ else
3097
+ failed_to_log("#{msg} Found [#{selected}]. #{desc}")
3098
+ end
3099
+ else
3100
+ msg = build_message(desc, "Expected option [#{list}] was found among multiple selections by #{which} [#{selected}]?", refs)
3101
+ if selected.include?(list)
3102
+ failed_to_log(msg)
3103
+ else
3104
+ failed_to_log(msg)
3105
+ end
3106
+ end
3107
+ end
3108
+
3109
+ rescue
3110
+ failed_to_log(unable_to)
3111
+ end
3112
+
3113
+ def verify_attribute(container, element, how, what, attribute, expected, desc = '', refs = '')
3114
+ msg = element_query_message(element, "#{attribute} equals '#{expected}'?", how, what, nil, desc, refs)
3115
+ actual = get_attribute_value(container, element, how, what, attribute, desc)
3116
+ if actual == expected
3117
+ passed_to_log(msg)
3118
+ else
3119
+ failed_to_log("#{msg} Found '#{actual}'")
3120
+ end
3121
+ rescue
3122
+ failed_to_log(unable_to(msg))
3123
+ end
3124
+
3125
+ alias validate_attribute_value verify_attribute
3126
+ alias verify_attribute_value verify_attribute
3127
+
3128
+ end
3129
+
3130
+ module UserInput
3131
+
3132
+ def focus(container, element, how, what, desc = '', refs = '', wait = 10)
3133
+ code = build_webdriver_fetch(element, how, what)
3134
+ target = eval("#{code}.when_present(#{wait})")
3135
+ focus_element(target, desc, refs, how, what)
3136
+ rescue
3137
+ failed_to_log(unable_to(msg))
3138
+ end
3139
+
3140
+ def focus_element(element, desc = '', refs = '', how = nil, what = nil)
3141
+ msg = element_action_message(element, 'Set focus on', how, what, nil, desc, refs)
3142
+ element.focus
3143
+ if element.focused?
3144
+ passed_to_log(with_caller(msg))
3145
+ true
3146
+ else
3147
+ failed_to_log(with_caller(msg))
3148
+ end
3149
+ rescue
3150
+ failed_to_log(unable_to(msg))
3151
+ end
3152
+
3153
+ def blur_element(element, desc = '', refs = '', how = nil, what = nil)
3154
+ msg = element_action_message(element, "Trigger blur", how, what, nil, desc, refs)
3155
+ element.fire_event('onBlur')
3156
+ if element.focused?
3157
+ passed_to_log(with_caller(msg))
3158
+ true
3159
+ else
3160
+ failed_to_log(with_caller(msg))
3161
+ end
3162
+ rescue
3163
+ failed_to_log(unable_to(msg))
3164
+ end
3165
+
3166
+ def clear(container, element, how, what, value = nil, desc = '', refs = '', options = {})
3167
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
3168
+ msg = element_action_message(element, 'Clear', how, what, value, desc, refs)
3169
+ code = build_webdriver_fetch(element, how, what, options)
3170
+ eval("#{code}.clear")
3171
+ cleared = false
3172
+ case element
3173
+ when :text_field, :textfield
3174
+ cleared = eval("#{code}.value == ''")
3175
+ when :text_area, :textarea
3176
+ cleared = eval("#{code}.value == ''")
3177
+ when :checkbox, :radio
3178
+ cleared != eval("#{code}.set?")
3179
+ end
3180
+ if cleared
3181
+ passed_to_log(msg)
3182
+ true
3183
+ else
3184
+ failed_to_log(msg)
3185
+ end
3186
+ rescue
3187
+ failed_to_log(unable_to(msg))
3188
+ end
3189
+
3190
+ def click(container, element, how, what, desc = '', refs = '', wait = 10)
3191
+ code = build_webdriver_fetch(element, how, what)
3192
+ target = eval("#{code}.when_present(#{wait})")
3193
+ click_element(target, desc, refs, how, what, value = nil)
3194
+ rescue
3195
+ failed_to_log(unable_to(build_message(desc, "#{element.to_s.upcase} :#{how}=>'#{what}'", refs)))
3196
+ end
3197
+
3198
+ alias click_js click
3199
+
3200
+ def click_element(element, desc = '', refs = '', how = '', what = '', value = '')
3201
+ msg = element_action_message(element, 'Click', how, what, value, desc, refs)
3202
+ begin
3203
+ element.click
3204
+ rescue => e
3205
+ unless rescue_me(e, __method__, rescue_me_command(element, how, what, __method__.to_s))
3206
+ raise e
3207
+ end
3208
+ end
3209
+ passed_to_log(msg)
3210
+ true
3211
+ rescue
3212
+ failed_to_log(unable_to(msg))
3213
+ end
3214
+
3215
+ alias element_click click_element
3216
+
3217
+ def click_as_needed(browser, target_container, target_elem, target_how, target_what,
3218
+ confirm_container, confirm_elem, confirm_how, confirm_what,
3219
+ desc = '', neg = false, alternate = false, limit = 6.0, increment = 0.5, interval = 2.0)
3220
+ rtrn = true
3221
+ nope = neg ? 'not ' : ''
3222
+
3223
+ debug_to_log("#{__method__.to_s.titleize}: Target: :#{target_elem} :#{target_how}='#{target_what}' in #{target_container}")
3224
+ debug_to_log("#{__method__.to_s.titleize}: Confirm: :#{confirm_elem} :#{confirm_how}='#{confirm_what}' in #{confirm_container}")
3225
+ windows_to_log(browser)
3226
+ click(target_container, target_elem, target_how, target_what, desc)
3227
+ last_action = 'click'
3228
+
3229
+ if confirm_elem == :window
3230
+ query = 'current?'
3231
+ else
3232
+ query = 'present?'
3233
+ end
3234
+
3235
+ if confirm_what.is_a?(Regexp)
3236
+ code = "#{nope}confirm_container.#{confirm_elem.to_s}(:#{confirm_how}, /#{confirm_what}/).#{query}"
3237
+ else
3238
+ code = "#{nope}confirm_container.#{confirm_elem.to_s}(:#{confirm_how}, '#{confirm_what}').#{query}"
3239
+ end
3240
+ debug_to_log("#{__method__}: code=[#{code}]")
3241
+
3242
+ seconds = 0.0
3243
+ until eval(code) do
3244
+ debug_to_log("#{__method__}: seconds=[#{seconds}] [#{code}]")
3245
+ sleep(increment)
3246
+ seconds += increment
3247
+ if seconds > limit
3248
+ rtrn = false
3249
+ break
3250
+ end
3251
+ if seconds.modulo(interval) == 0.0
3252
+ if alternate
3253
+ if last_action == 'click'
3254
+ fire_event(target_container, target_elem, target_how, target_what, 'onclick', "#{desc} (#{seconds} seconds)")
3255
+ last_action = 'fire'
3256
+ else
3257
+ click(target_container, target_elem, target_how, target_what, "#{desc} (#{seconds} seconds)")
3258
+ last_action = 'click'
3259
+ end
3260
+ else
3261
+ click(target_container, target_elem, target_how, target_what, "#{desc} (#{seconds} seconds)")
3262
+ end
3263
+ end
3264
+ end
3265
+ unless rtrn
3266
+ focus(browser, target_elem, target_how, target_what)
3267
+ sleep(0.1)
3268
+ send_a_key(browser, :enter)
3269
+ sleep(interval)
3270
+ rtrn = eval(code)
3271
+ end
3272
+ rtrn
3273
+ rescue
3274
+ failed_to_log(unable_to)
3275
+ end
3276
+
3277
+ def fire_event(container, element, how, what, event, desc = '', refs = '', wait = 10)
3278
+ code = build_webdriver_fetch(element, how, what)
3279
+ target = eval("#{code}.when_present(#{wait})")
3280
+ element_fire_event(target, event, desc, refs, how, what)
3281
+ rescue
3282
+ failed_to_log(unable_to(build_msg(element, how, what, event)))
3283
+ end
3284
+
3285
+ def element_fire_event(element, event, desc = '', refs = '', how = nil, what = nil)
3286
+ msg = element_action_message(element, "Fire '#{event}' event on", how, what, nil, desc, refs)
3287
+ begin
3288
+ element.fire_event(event)
3289
+ rescue => e
3290
+ unless rescue_me(e, __method__, rescue_me_command(element, how, what, __method__.to_s, event))
3291
+ raise e
3292
+ end
3293
+ end
3294
+ passed_to_log(msg)
3295
+ true
3296
+ rescue
3297
+ failed_to_log(unable_to(msg))
3298
+ end
3299
+
3300
+ def element_hover(element, desc = '', refs = '', how = nil, what = nil)
3301
+ msg = element_action_message(element, "Hover over", how, what, nil, desc, refs)
3302
+ element.hover
3303
+ passed_to_log(msg)
3304
+ true
3305
+ rescue
3306
+ failed_to_log(unable_to(msg))
3307
+ end
3308
+
3309
+ def set(container, element, how, what, value = nil, desc = '', refs = '', options = {})
3310
+ value, desc, refs, options = capture_value_desc(value, desc, refs, options) # for backwards compatibility
3311
+ code = build_webdriver_fetch(element, how, what, options)
3312
+ target = eval("#{code}")
3313
+ #TODO: Fix this!
3314
+ set_element(target, value, desc, refs, how, what)
3315
+ rescue
3316
+ failed_to_log("#{msg} '#{$!}'")
3317
+ end
3318
+
3319
+ def set_element(element, value = nil, desc = '', refs = '', how = '', what = '')
3320
+ msg = element_action_message(element, "Set", how, what, nil, desc, refs)
3321
+ case element.class.to_s
3322
+ when /radio/i, /checkbox/i
3323
+ element.set
3324
+ passed_to_log(msg)
3325
+ true
3326
+ when /text_field|textfield|text_area|textarea/i
3327
+ element_set_text(element, value, desc, refs, how, what)
3328
+ else
3329
+ failed_to_log(with_caller(desc, "#{element} not supported", refs))
3330
+ end
3331
+ rescue
3332
+ failed_to_log(unable_to(msg))
3333
+ end
3334
+
3335
+ def element_set_text(element, value, desc = '', refs = '', how = '', what = '')
3336
+ msg = element_action_message(element, "Set to '#{value}':", how, what, nil, desc, refs)
3337
+ element.when_present.set(value)
3338
+ if element.value == value
3339
+ passed_to_log(msg)
3340
+ true
3341
+ else
3342
+ failed_to_log("#{msg}: Found:'#{element.value}'.")
3343
+ end
3344
+ rescue
3345
+ failed_to_log(unable_to(msg))
3346
+ end
3347
+
3348
+ def set_text_field(browser, how, what, value, desc = '', refs = '', skip_value_check = false)
3349
+ #TODO: fix this to handle Safari password field
3350
+ msg = build_message(desc, with_caller("#{how}='#{what}' to '#{value}'"), refs)
3351
+ msg << ' (Skip value check)' if skip_value_check
3352
+ browser.text_field(how, what).when_present.set(value)
3353
+ if skip_value_check
3354
+ passed_to_log(msg)
3355
+ true
3356
+ else
3357
+ if browser.text_field(how, what).value == value
3358
+ passed_to_log(msg)
3359
+ true
3360
+ else
3361
+ failed_to_log("#{msg}: Found:'#{browser.text_field(how, what).value}'.")
3362
+ end
3363
+ end
3364
+ rescue
3365
+ failed_to_log(unable_to(msg))
3366
+ end
3367
+
3368
+ def select_option(browser, how, what, which, option, desc = '', refs = '', nofail = false)
3369
+ list = browser.select_list(how, what).when_present
3370
+ msg = build_message(desc, with_caller("from list with :#{how}='#{what}"))
3371
+ select_option_from_list(list, which, option, msg, refs, nofail)
3372
+ rescue
3373
+ failed_to_log(unable_to)
3374
+ end
3375
+
3376
+ def select_next_option_from_list(list, desc = '', refs = '')
3377
+ msg = build_message(desc, refs)
3378
+ options = list.options
3379
+ #This doesnt seem to account for the last option already being selected. ex. calendar with dec selected
3380
+ selected_index = list.selected_options[0].index
3381
+ if selected_index == options.length - 1
3382
+ new_index = 0
3383
+ else
3384
+ new_index = options[selected_index + 1] ? selected_index + 1 : 0
3385
+ end
3386
+
3387
+ select_option_from_list(list, :index, new_index, with_caller(desc), refs)
3388
+ rescue
3389
+ failed_to_log(unable_to(msg))
3390
+ end
3391
+
3392
+ def select_previous_option_from_list(list, desc = '', refs = '')
3393
+ msg = build_message(desc, refs)
3394
+ options = list.options
3395
+ #This doesnt seem to account for the last option already being selected. ex. calendar with dec selected
3396
+ selected_index = list.selected_options[0].index
3397
+ if selected_index == options.length - 1
3398
+ new_index = 0
3399
+ else
3400
+ new_index = options[selected_index - 1] ? selected_index - 1 : 0
3401
+ end
3402
+
3403
+ select_option_from_list(list, :index, new_index, with_caller(desc), refs)
3404
+ rescue
3405
+ failed_to_log(unable_to(msg))
3406
+ end
3407
+
3408
+ def select_option_from_list(list, how, what, desc = '', refs = '', nofail = false)
3409
+ msg = build_message(desc, "Select option :#{how}='#{what}'", refs)
3410
+ ok = true
3411
+ if list
3412
+ case how
3413
+ when :text
3414
+ list.select(what) #TODO: regex?
3415
+ when :value
3416
+ list.select_value(what) #TODO: regex?
3417
+ when :index
3418
+ list.option(:index, what.to_i).select
3419
+ else
3420
+ failed_to_log("#{msg} Select by #{how} not supported.")
3421
+ ok = false
3422
+ end
3423
+ if ok
3424
+ passed_to_log(msg)
3425
+ true
3426
+ else
3427
+ if nofail
3428
+ passed_to_log("#{msg} Option not found. No Fail specified.")
3429
+ true
3430
+ else
3431
+ failed_to_log("#{msg} Option not found.")
3432
+ end
3433
+ end
3434
+ else
3435
+ failed_to_log("#{msg} Select list not found.")
3436
+ end
3437
+ rescue
3438
+ failed_to_log(unable_to(msg))
3439
+ end
3440
+
3441
+ def option_selected?(container, how, what, which, option, desc = '', refs = '')
3442
+ list = container.select_list(how, what).when_present
3443
+ msg = build_message(desc, with_caller("from list with :#{how}='#{what}"))
3444
+ option_selected_from_list?(list, which, option, desc, refs)
3445
+ rescue
3446
+ failed_to_log(unable_to(msg))
3447
+ end
3448
+
3449
+ def option_selected_from_list?(list, which, what, desc = '', refs = '')
3450
+ msg = build_message(desc, "Option :#{which}='#{what}' is selected?", refs)
3451
+ if list.option(which, what).selected?
3452
+ passed_to_log(msg)
3453
+ true
3454
+ else
3455
+ failed_to_log(msg)
3456
+ end
3457
+ rescue
3458
+ failed_to_log(unable_to(msg))
3459
+ end
3460
+
3461
+ def resize_browser_window(browser, width, height, move_to_origin = true)
3462
+ msg = "#{__method__.to_s.humanize} to (#{width}, #{height})"
3463
+ #browser = browser.browser if browser.respond_to?(:tag_name)
3464
+ browser.browser.driver.manage.window.resize_to(width, height)
3465
+ sleep(0.5)
3466
+ if move_to_origin
3467
+ browser.browser.driver.manage.window.move_to(0, 0)
3468
+ msg << ' and move to origin (0, 0).'
3469
+ end
3470
+ #scroll_to_top(browser)
3471
+ passed_to_log(msg)
3472
+ true
3473
+ rescue
3474
+ failed_to_log(unable_to(msg))
3475
+ end
3476
+
3477
+ alias resize_window resize_browser_window
3478
+
3479
+ def tab_until_focused(container, element, how, what, class_strg = nil, desc = '', refs = '', limit = 15)
3480
+ ok = nil
3481
+ msg = build_message('Tab to set focus on', "#{element.to_s.upcase}", "#{how}='#{what}'", refs)
3482
+ target = get_element(container, element, how, what, nil, with_caller(desc, "(#{limit})"), refs)
3483
+ count = 0
3484
+ (0..limit).each do |cnt|
3485
+ #debug_to_log("tab #{cnt}")
3486
+ if class_strg
3487
+ if target.class_name.include?(class_strg)
3488
+ passed_to_log(with_caller(msg, "(#{cnt} tabs)"))
3489
+ ok = true
3490
+ break
3491
+ end
3492
+ else
3493
+ if target.focused?
3494
+ passed_to_log(with_caller(msg, "(#{cnt} tabs)"))
3495
+ ok = true
3496
+ break
3497
+ end
3498
+ end
3499
+ container.send_keys(:tab)
3500
+ count = cnt
3501
+ #send_tab(container)
3502
+ end
3503
+ failed_to_log(unable_to(msg, "(#{count} tabs)")) unless ok
3504
+ ok
3505
+ rescue
3506
+ failed_to_log(unable_to)
3507
+ end
3508
+
3509
+ def type_in_text_field(element, strg, desc = '', refs = '')
3510
+ msg = build_message(desc, "Type (send_keys) '#{strg}' into text field :id=>'#{element.attribute_value('id')}'", refs)
3511
+ element.send_keys(strg)
3512
+ if element.value == strg
3513
+ passed_to_log(msg)
3514
+ true
3515
+ else
3516
+ failed_to_log(msg)
3517
+ end
3518
+ rescue
3519
+ failed_to_log(unable_to(msg))
3520
+ end
3521
+
3522
+ def send_a_key(browser, key, modifier = nil, desc = '', refs = '')
3523
+ if modifier
3524
+ msg = build_message(desc, "Sent #{modifier}+#{key}", refs)
3525
+ browser.send_keys [modifier, key]
3526
+ else
3527
+ msg = build_message(desc, "Sent #{key}", refs)
3528
+ browser.send_keys key
3529
+ end
3530
+ message_to_report(msg)
3531
+ end
3532
+
3533
+ def send_page_down(browser, desc = '', refs = '', modifier = nil)
3534
+ send_a_key(browser, :page_down, modifier, desc, refs)
3535
+ end
3536
+
3537
+ alias press_page_down send_page_down
3538
+
3539
+ def sent_page_up(browser, desc = '', refs = '', modifier = nil)
3540
+ send_a_key(browser, :page_up, modifier, desc, refs)
3541
+ end
3542
+
3543
+ alias press_page_up sent_page_up
3544
+
3545
+ def send_spacebar(browser, desc = '', refs = '', modifier = nil)
3546
+ send_a_key(browser, :space, modifier, desc, refs)
3547
+ end
3548
+
3549
+ alias press_spacebar send_spacebar
3550
+ alias press_space send_spacebar
3551
+ alias send_space send_spacebar
3552
+
3553
+ def send_enter(browser, desc = '', refs = '', modifier = nil)
3554
+ send_a_key(browser, :enter, modifier, desc, refs)
3555
+ end
3556
+
3557
+ alias press_enter send_enter
3558
+
3559
+ def send_tab(browser, desc = '', refs = '', modifier = nil)
3560
+ send_a_key(browser, :tab, modifier, desc, refs)
3561
+ end
3562
+
3563
+ alias press_tab send_tab
3564
+
3565
+ def send_up_arrow(browser, desc = '', refs = '', modifier = nil)
3566
+ send_a_key(browser, :arrow_up, modifier, desc, refs)
3567
+ end
3568
+
3569
+ alias press_up_arrow send_up_arrow
3570
+
3571
+ def send_down_arrow(browser, desc = '', refs = '', modifier = nil)
3572
+ send_a_key(browser, :arrow_down, modifier, desc, refs)
3573
+ end
3574
+
3575
+ alias press_down_arrow send_down_arrow
3576
+
3577
+ def send_right_arrow(browser, desc = '', refs = '', modifier = nil)
3578
+ send_a_key(browser, :arrow_right, modifier, desc, refs)
3579
+ end
3580
+
3581
+ alias press_right_arrow send_right_arrow
3582
+
3583
+ def send_left_arrow(browser, desc = '', refs = '', modifier = nil)
3584
+ send_a_key(browser, :arrow_left, modifier, desc, refs)
3585
+ end
3586
+
3587
+ alias press_left_arrow send_left_arrow
3588
+
3589
+ def send_escape(browser, desc = '', refs = '', modifier = nil)
3590
+ send_a_key(browser, :escape, modifier, desc, refs)
3591
+ end
3592
+
3593
+ alias press_escape send_escape
3594
+
3595
+ end
3596
+
3597
+ module DragAndDrop
3598
+
3599
+ def remove_focus(container, element, desc = '', refs = '', tab_twice = false)
3600
+ msg = build_message(desc, refs)
3601
+ ok = true
3602
+ if element.focused?
3603
+ debug_to_log('element has focus')
3604
+ element.fire_event('onblur')
3605
+ debug_to_log("Fired 'onblur' event")
3606
+ which = :blur
3607
+ if element.focused?
3608
+ container.send_keys(:tab)
3609
+ debug_to_log("Sent tab")
3610
+ which = :tab
3611
+ if tab_twice
3612
+ container.send_keys(:tab)
3613
+ debug_to_log("Sent second tab")
3614
+ which = :tab
3615
+ end
3616
+ if element.focused?
3617
+ container.send_keys(:enter)
3618
+ debug_to_log("Sent enter")
3619
+ which = :enter
3620
+ end
3621
+ end
3622
+ if element.focused?
3623
+ failed_to_log(unable_to(msg))
3624
+ which = :fail
3625
+ ok = false
3626
+ else
3627
+ passed_to_log(with_caller("#{element.tag_name}", msg))
3628
+ end
3629
+ else
3630
+ debug_to_log('Element does not have focus to remove.')
3631
+ which = :already
3632
+ end
3633
+ begin
3634
+ if @focus_moves
3635
+ @focus_moves[:remove][which] += 1
3636
+ if which == :tab and tab_twice
3637
+ @focus_moves[:remove][which] += 1
3638
+ end
3639
+ end
3640
+ rescue
3641
+ debug_to_log(with_caller("'#{$!}'", msg))
3642
+ end
3643
+ ok
3644
+ rescue
3645
+ failed_to_log(unable_to(msg))
3646
+ end
3647
+
3648
+ def return_focus(container, element, desc = '', refs = '')
3649
+ msg = build_message(desc, refs)
3650
+ ok = true
3651
+ if element.focused?
3652
+ debug_to_log('Element already has focus.')
3653
+ which = :already
3654
+ else
3655
+ element.fire_event('onclick')
3656
+ debug_to_log("Fired 'onclick' event")
3657
+ which = :onclick
3658
+ unless element.focused?
3659
+ element.fire_event('onfocus')
3660
+ debug_to_log("Fired 'onfocus' event")
3661
+ which = :onfocus
3662
+ unless element.focused?
3663
+ element.focus
3664
+ debug_to_log("Called focus method")
3665
+ which = :focus
3666
+ unless element.focused?
3667
+ element.click
3668
+ debug_to_log("Called click method")
3669
+ which = :click
3670
+ unless element.focused?
3671
+ container.send_keys([:shift, :tab])
3672
+ debug_to_log("Sent shift tab")
3673
+ which = :shift_tab
3674
+ end
3675
+ end
3676
+ end
3677
+ end
3678
+ if element.focused?
3679
+ passed_to_log(with_caller("#{element.tag_name}", msg))
3680
+ else
3681
+ failed_to_log(unable_to(msg))
3682
+ which = :fail
3683
+ ok = false
3684
+ end
3685
+ end
3686
+ begin
3687
+ @focus_moves[:remove][which] += 1 if @focus_moves
3688
+ rescue
3689
+ debug_to_log(with_caller("'#{$!}'", msg))
3690
+ end
3691
+ ok
3692
+ rescue
3693
+ failed_to_log(unable_to(msg))
3694
+ end
3695
+
3696
+ #TODO: needs work: should succeed if browser is other container or element
3697
+ def get_browser_coord(browser, dbg=nil)
3698
+ title = browser.title
3699
+ x, y = browser.position
3700
+ w, h = browser.size
3701
+ if dbg
3702
+ debug_to_log("\n\t\tBrowser #{browser.inspect}\n"+
3703
+ "\t\tdimensions: x: #{w} y: #{h}"+
3704
+ "\t\tscreen offset x: #{x} y: #{y}")
3705
+ end
3706
+ [x, y, w, h]
3707
+ end
3708
+
3709
+ def get_element_screen_coordinates(browser, element, dbg = nil)
3710
+ hash = Hash.new
3711
+ bx, by = browser.position
3712
+ ox, oy = window_viewport_offsets(browser)
3713
+ rect = element.bounding_client_rectangle
3714
+ w = rect['width']
3715
+ h = rect['height']
3716
+ hash['width'] = w
3717
+ hash['height'] = h
3718
+ xc = rect['left']
3719
+ yc = rect['top']
3720
+ xcc = xc + w/2
3721
+ ycc = yc + h/2
3722
+ # screen offset:
3723
+ xs = bx + ox + xc - 1
3724
+ ys = by + oy + yc - 1
3725
+ hash['left'] = xs
3726
+ hash['top'] = ys
3727
+ # screen center:
3728
+ xsc = xs + w/2
3729
+ ysc = ys + h/2
3730
+ hash['screen_center_left'] = xsc
3731
+ hash['screen_center_top'] = ysc
3732
+ xslr = xs + w
3733
+ yslr = ys + h
3734
+ hash['screen_lower_right_left'] = xslr
3735
+ hash['screen_lower_right_top'] = xs
3736
+ if dbg
3737
+ debug_to_log(
3738
+ "\n\t\tElement: #{element.inspect}"+
3739
+ "\n\t\tbrowser screen offset: x: #{bx} y: #{by}"+
3740
+ "\n\t\t dimensions: x: #{w} y: #{h}"+
3741
+ "\n\t\t client offset x: #{xc} y: #{yc}"+
3742
+ "\n\t\t screen offset x: #{xs} y: #{ys}"+
3743
+ "\n\t\t client center x: #{xcc} y: #{ycc}"+
3744
+ "\n\t\t screen center x: #{xsc} y: #{ysc}"+
3745
+ "\n\t\t screen lower right x: #{xslr} y: #{yslr}")
3746
+ end
3747
+ hash
3748
+ end
3749
+
3750
+ def viewport_size(browser, use_body = false)
3751
+ browser = browser.browser if browser.respond_to?(:tag_name)
3752
+ if @targetBrowser.abbrev == 'IE' and @browserVersion.to_i < 9
3753
+ x, y = insert_viewport_div(browser)
3754
+ else
3755
+ if use_body
3756
+ x = browser.body.attribute_value('clientWidth')
3757
+ y = browser.body.attribute_value('clientHeight')
3758
+ else
3759
+ x = browser.execute_script("return window.innerWidth")
3760
+ y = browser.execute_script("return window.innerHeight")
3761
+ end
3762
+ end
3763
+
3764
+ [x, y]
3765
+
3766
+ rescue => e
3767
+ unless rescue_me(e, __method__, "#{__method__}(browser, #{use_body})")
3768
+ raise e
3769
+ end
3770
+ end
3771
+
3772
+ def screen_size(browser)
3773
+ [browser.execute_script('return screen.width'),
3774
+ browser.execute_script('return screen.height')]
3775
+ rescue => e
3776
+ unless rescue_me(e, __method__, "#{__method__}(browser)")
3777
+ raise e
3778
+ end
3779
+ end
3780
+
3781
+ def screen_available_size(browser)
3782
+ [browser.execute_script('return screen.availWidth'),
3783
+ browser.execute_script('return screen.availHeight')]
3784
+ rescue => e
3785
+ unless rescue_me(e, __method__, "#{__method__}(browser)")
3786
+ raise e
3787
+ end
3788
+ end
3789
+
3790
+ def insert_viewport_div(browser)
3791
+ browser.execute_script(
3792
+ 'var test = document.createElement( "div" );' +
3793
+ 'test.style.cssText = "position: fixed;top: 0;left: 0;bottom: 0;right: 0;"; ' +
3794
+ 'test.id = "awetest-temp-viewport"; ' +
3795
+ 'document.documentElement.insertBefore( test, document.documentElement.firstChild ); '
3796
+ )
3797
+ viewport = browser.div(:id, 'awetest-temp-viewport')
3798
+ x = browser.execute_script("return arguments[0].offsetWidth", viewport)
3799
+ y = browser.execute_script("return arguments[0].offsetHeight", viewport)
3800
+ browser.execute_script("document.documentElement.removeChild( arguments[0] )", viewport)
3801
+ [x, y]
3802
+ end
3803
+
3804
+ def scroll_into_view(container, element, how, what, desc = '', refs = '', options = {})
3805
+ msg = build_message(desc, "#{__method__.to_s.humanize} :#{element.to_s.upcase} :#{how}='#{what}'", refs)
3806
+ code = build_webdriver_fetch(element, how, what, options)
3807
+ point = eval("#{code}.when_present.wd.location_once_scrolled_into_view")
3808
+ if point
3809
+ passed_to_log(msg)
3810
+ [point.x, point.y]
3811
+ else
3812
+ failed_to_log(msg)
3813
+ end
3814
+ rescue
3815
+ failed_to_log(unable_to(msg))
3816
+ end
3817
+
3818
+ def scroll_element_into_view(element, desc = '', refs = '')
3819
+ msg = build_message(desc, "#{__method__.to_s.humanize}", refs)
3820
+ point = element.wd.location_once_scrolled_into_view
3821
+ if point
3822
+ passed_to_log(msg)
3823
+ [point.x, point.y]
3824
+ else
3825
+ failed_to_log(msg)
3826
+ end
3827
+ rescue
3828
+ failed_to_log(unable_to(desc))
3829
+ end
3830
+
3831
+ def scroll_to(browser, param, desc = '', refs = '')
3832
+ ok = true
3833
+ case param
3834
+ when Array
3835
+ what = nice_array(param)
3836
+ when param.respond_to?(:tag_name)
3837
+ what = translate_tag_name(param)
3838
+ else
3839
+ what = "#{param}"
3840
+ end
3841
+
3842
+ #Thanks to Alex Rodionov (p0deje)
3843
+ args = case param
3844
+ when :top, :start
3845
+ 'window.scrollTo(0, 0);'
3846
+ when :center
3847
+ 'window.scrollTo(document.body.scrollWidth / 2, document.body.scrollHeight / 2);'
3848
+ when :bottom, :end
3849
+ 'window.scrollTo(0, document.body.scrollHeight);'
3850
+ when Watir::Element, Watir::WhenPresentDecorator
3851
+ ['arguments[0].scrollIntoView();', param]
3852
+ when Array
3853
+ ['window.scrollTo(arguments[0], arguments[1]);', Integer(param[0]), Integer(param[1])]
3854
+ else
3855
+ if param.respond_to?(:tag_name)
3856
+ target = param.element
3857
+ ['arguments[0].scrollIntoView();', target]
3858
+ else
3859
+ failed_to_log(build_message(with_caller(desc, what), refs, "Don't know how to scroll to: #{param.to_s}!"))
3860
+ ok = false
3861
+ end
3862
+ end
3863
+
3864
+ if ok
3865
+ browser.execute_script(*args)
3866
+ end
3867
+ ok
3868
+ rescue
3869
+ failed_to_log(unable_to(build_message(desc, what, refs)))
3870
+ end
3871
+
3872
+ def scroll_in_element(element, direction, amount)
3873
+ js = 'return arguments[0].scroll@@@ = arguments[1];",EEEEE, PPPPP'
3874
+ ortho = ''
3875
+ pixels = amount
3876
+ case direction
3877
+ when :up
3878
+ ortho = 'Top'
3879
+ when :down
3880
+ ortho = 'Top'
3881
+ pixels = -amount
3882
+ when :left
3883
+ ortho = 'Left'
3884
+ when :right
3885
+ ortho = 'Left'
3886
+ pixels = -amount
3887
+ else
3888
+ failed_to_log(with_caller("Invalid direction '#{direction}'"))
3889
+ end
3890
+ element.browser.execute_script("return arguments[0].scroll#{ortho} = arguments[1];\"", element, pixels)
3891
+
3892
+ # Scroll inside web element vertically (e.g. 100 pixel)
3893
+ # js.executeScript("arguments[0].scrollTop = arguments[1];",driver.findElement(By.id("<div-id>")), 100);
3894
+
3895
+ # eula = dr.find_element_by_id('eulaFrame')
3896
+ # dr.execute_script('arguments[0].scrollTop = arguments[0].scrollHeight', eula)
3897
+
3898
+ # JavascriptExecutor jse = (JavascriptExecutor) localDriver;
3899
+ # //locate web element you need for scroll and its height
3900
+ # WebElement element = localDriver.findElement(By.id("DIV_element"));
3901
+ # String blockHeight = "return arguments[0].offsetHeight";
3902
+ #
3903
+ # String myscript = "arguments[0].scrollTop"+jse.executeScript(blockHeight,element);
3904
+ #
3905
+ # element.click();
3906
+ # pause(100);
3907
+ # jse.executeScript(myscript, element);
3908
+
3909
+ # If you want to scroll inner div element, not window you can try this below code:
3910
+ # //Get div element having scroll bar you want to do
3911
+ # WebElement scrollArea = driver.findElement(By.xpath("//"));
3912
+ # // Initialize Javascript executor
3913
+ # JavascriptExecutor js = (JavascriptExecutor) driver;
3914
+ # // Scroll inside web element vertically (e.g. 1000 pixel)
3915
+ # js.executeScript("arguments[0].scrollTop = arguments[1];",scrollArea, 1000);
3916
+ # Thread.sleep(1000);
3917
+ # // do something (ex. choose an item in list ...)
3918
+ # Good luck! hihi
3919
+ rescue
3920
+ failed_to_log(unable_to(ortho, pixels))
3921
+ end
3922
+
3923
+ def window_viewport_offsets(browser)
3924
+ x = 0
3925
+ y = 0
3926
+
3927
+ if $mobile
3928
+ debug_to_log(with_caller("Not supported for mobile browsers"))
3929
+ else
3930
+ browser = browser.browser if browser.respond_to?(:tag_name)
3931
+ wd_dim = browser.window.size
3932
+ vp_dim = viewport_size(browser)
3933
+ x = (wd_dim.width - vp_dim[0])
3934
+ y = (wd_dim.height - vp_dim[1])
3935
+ y += 1 if @targetBrowser.abbrev == 'FF'
3936
+ end
3937
+
3938
+ [x, y]
3939
+ rescue
3940
+ failed_to_log(unable_to)
3941
+ end
3942
+
3943
+ def window_dimensions(browser)
3944
+ browser = browser.browser if browser.respond_to?(:tag_name)
3945
+ wd_dim = browser.window.size
3946
+ wd_pos = browser.window.position
3947
+ vp_dim = viewport_size(browser)
3948
+ off_x = (wd_dim.width - vp_dim[0])
3949
+ off_y = (wd_dim.height - vp_dim[1])
3950
+ off_y += 1 if @targetBrowser.abbrev == 'FF'
3951
+
3952
+ just_inside_x = wd_pos.x + wd_dim.width - off_x - 3
3953
+ just_inside_y = wd_pos.y + off_x + 3
3954
+
3955
+ debug_to_log(with_caller("\nposition: [#{wd_pos.x},#{wd_pos.y}]",
3956
+ "\nsize: [#{wd_dim.width},#{wd_dim.height}] ",
3957
+ "\nviewport: [#{vp_dim[0]},#{vp_dim[1]}]",
3958
+ "\noffsets: [#{off_x},#{off_y}]",
3959
+ "\njust_inside: [#{just_inside_x},#{just_inside_y}]"
3960
+ ))
3961
+ [wd_pos.x, wd_pos.y,
3962
+ wd_dim.width, wd_dim.height,
3963
+ vp_dim[0], vp_dim[1],
3964
+ off_x, off_y,
3965
+ just_inside_x, just_inside_y]
3966
+ rescue
3967
+ failed_to_log(unable_to)
3968
+ end
3969
+
3970
+ def mouse_to_browser_edge(container, offset_x = -3, offset_y = -3)
3971
+ x, y = window_dimensions(container)[4, 2]
3972
+ container.driver.mouse.move_to(container.driver[:tag_name => 'body'], x - offset_x, y - offset_y)
3973
+ container.driver.mouse.down
3974
+ container.driver.mouse.up
3975
+ end
3976
+
3977
+ def set_viewport_size(browser, width, height, diff = nil, move_to_origin = true, use_body = false, desc = '', refs = '')
3978
+ if $mobile
3979
+ debug_to_log(with_caller("Not supported for mobile browsers"))
3980
+ else
3981
+ diff = window_viewport_offsets(browser.browser) unless diff
3982
+ resize_browser_window(browser.browser, width + diff[0], height + diff[1], move_to_origin)
3983
+ sleep(0.5)
3984
+ msg = build_message(desc, "viewport (#{width}, #{height})",
3985
+ "(offsets (#{diff[0]}, #{diff[1]}))")
3986
+ act_x, act_y = viewport_size(browser.browser, use_body)
3987
+ if width == act_x.to_i and height == act_y.to_i
3988
+ if @targetBrowser.abbrev == 'FF'
3989
+ debug_to_log(with_caller(msg, refs))
3990
+ else
3991
+ passed_to_log(with_caller(msg, refs))
3992
+ end
3993
+ true
3994
+ else
3995
+ if @targetBrowser.abbrev == 'FF'
3996
+ debug_to_report(with_caller(msg, "Found (#{act_x}, #{act_y})", refs))
3997
+ else
3998
+ failed_to_log(with_caller(msg, "Found (#{act_x}, #{act_y})", refs))
3999
+ end
4000
+ end
4001
+ end
4002
+ rescue
4003
+ failed_to_log(unable_to)
4004
+ end
4005
+
4006
+ # @deprecated
4007
+ def get_viewport_to_win_diff(browser)
4008
+ window_viewport_offsets(browser)[0]
4009
+ end
4010
+
4011
+ def overlay?(inner, outer, side = :bottom)
4012
+ i_dims = inner.bounding_client_rectangle
4013
+ o_dims = outer.bounding_client_rectangle
4014
+ case side
4015
+ when :bottom
4016
+ overlay = i_dims['bottom'] > o_dims['top']
4017
+ when :top
4018
+ overlay = i_dims['top'] > o_dims['top']
4019
+ when :left
4020
+ overlay = i_dims['left'] > o_dims['right']
4021
+ when :right
4022
+ overlay = i_dims['right'] > o_dims['right']
4023
+ when :inside
4024
+ overlay =
4025
+ !(i_dims['top'] > o_dims['top'] and
4026
+ i_dims['right'] < o_dims['right'] and
4027
+ i_dims['left'] > o_dims['left'] and
4028
+ i_dims['bottom'] < o_dims['bottom']
4029
+ )
4030
+ else
4031
+ overlay =
4032
+ (i_dims['top'] > o_dims['bottom'] or
4033
+ i_dims['right'] < o_dims['left'] or
4034
+ i_dims['left'] > o_dims['right'] or
4035
+ i_dims['bottom'] < o_dims['top']
4036
+ )
4037
+ end
4038
+ overlay
4039
+ rescue
4040
+ failed_to_log("Unable to determine overlay. '#{$!}'")
4041
+ end
4042
+
4043
+ def get_element_dimensions(container, element, desc = '', refs = '')
4044
+ hash = Hash.new
4045
+ #hash[:text] = element.text
4046
+ #hash[:unit] = element
4047
+ hash[:clientLeft] = element.attribute_value('clientLeft').to_i
4048
+ hash[:clientTop] = element.attribute_value('clientTop').to_i
4049
+ hash[:clientWidth] = element.attribute_value('clientWidth').to_i
4050
+ hash[:clientHeight] = element.attribute_value('clientHeight').to_i
4051
+ #hash[:offsetParent] = element.attribute_value('offsetParent')
4052
+ hash[:offsetLeft] = element.attribute_value('offsetLeft').to_i
4053
+ hash[:offsetTop] = element.attribute_value('offsetTop').to_i
4054
+ hash[:offsetWidth] = element.attribute_value('offsetWidth').to_i
4055
+ hash[:offsetHeight] = element.attribute_value('offsetHeight').to_i
4056
+ hash[:scrollLeft] = element.attribute_value('scrollLeft').to_i
4057
+ hash[:scrollTop] = element.attribute_value('scrollTop').to_i
4058
+ hash[:scrollWidth] = element.attribute_value('scrollWidth').to_i
4059
+ hash[:scrollHeight] = element.attribute_value('scrollHeight').to_i
4060
+ if desc.length > 0
4061
+ debug_to_log("#{desc} #{refs}\n#{hash.to_yaml}")
4062
+ end
4063
+ hash
4064
+ rescue
4065
+ failed_to_log(unable_to)
4066
+ end
4067
+
4068
+ def get_element_dimensions1(container, element, desc = '', refs = '')
4069
+ hash = Hash.new
4070
+ #hash[:text] = element.text
4071
+ #hash[:unit] = element
4072
+ hash[:clientLeft] = container.execute_script("return arguments[0].clientLeft", element)
4073
+ hash[:clientTop] = container.execute_script("return arguments[0].clientTop", element)
4074
+ hash[:clientWidth] = container.execute_script("return arguments[0].clientWidth", element)
4075
+ hash[:clientHeight] = container.execute_script("return arguments[0].clientHeight", element)
4076
+ #hash[:offsetParent] = container.execute_script("return arguments[0].offsetParent", element)
4077
+ hash[:offsetLeft] = container.execute_script("return arguments[0].offsetLeft", element)
4078
+ hash[:offsetTop] = container.execute_script("return arguments[0].offsetTop", element)
4079
+ hash[:offsetWidth] = container.execute_script("return arguments[0].offsetWidth", element)
4080
+ hash[:offsetHeight] = container.execute_script("return arguments[0].offsetHeight", element)
4081
+ hash[:scrollLeft] = container.execute_script("return arguments[0].scrollLeft", element)
4082
+ hash[:scrollTop] = container.execute_script("return arguments[0].scrollTop", element)
4083
+ hash[:scrollWidth] = container.execute_script("return arguments[0].scrollWidth", element)
4084
+ hash[:scrollHeight] = container.execute_script("return arguments[0].scrollHeight", element)
4085
+ if desc.length > 0
4086
+ debug_to_log("#{desc} #{refs}\n#{hash.to_yaml}")
4087
+ end
4088
+ hash
4089
+ rescue
4090
+ failed_to_log(unable_to)
4091
+ end
4092
+
4093
+ def get_outside_location(element, desc = '', refs = '', offset = 10, vertical = 'top', horizontal = 'right')
4094
+ dimensions = get_element_dimensions(element.browser, element, with_caller(desc), refs)
4095
+
4096
+ if vertical =~ /top/i
4097
+ y = dimensions[:offsetTop].to_i
4098
+ else
4099
+ y = dimensions[:offsetTop].to_i + dimensions[:offsetHeight].to_i
4100
+ end
4101
+ if horizontal =~ /right/i
4102
+ x = dimensions[:offsetLeft].to_i + dimensions[:offsetWidth].to_i + offset
4103
+ else
4104
+ x = dimensions[:offsetLeft].to_i - offset
4105
+ end
4106
+
4107
+ [x, y]
4108
+ rescue
4109
+ failed_to_log(unable_to)
4110
+ end
4111
+
4112
+ end
4113
+ end
4114
+ end
4115
+
4116
+ module Watir
4117
+ class Element
4118
+
4119
+ def list_attributes
4120
+ # binding.pry
4121
+ # attributes = browser.execute_script(%Q[
4122
+ # var s = {};
4123
+ # var attrs = arguments[0].attributes;
4124
+ # for (var l = 0; l < attrs.length; ++l) {
4125
+ # var a = attrs[l]; s[a.name] = a.value);
4126
+ # } ;
4127
+ # return s;],
4128
+ # self
4129
+ # )
4130
+ attributes = browser.execute_script(%Q[
4131
+ var s = [];
4132
+ var attrs = arguments[0].attributes;
4133
+ for (var l = 0; l < attrs.length; ++l) {
4134
+ var a = attrs[l]; s.push(a.name + ': ' + a.value);
4135
+ } ;
4136
+ return s;],
4137
+ self
4138
+ )
4139
+ end
4140
+
4141
+ def attribute_values
4142
+ hash = Hash.new
4143
+ ['id', 'offsetParent', 'style', 'currentstyle',
4144
+ 'offsetHeight', 'offsetWidth', 'offsetLeft', 'offsetTop',
4145
+ 'clientHeight', 'clientWidth', 'clientLeft', 'clientTop',
4146
+ 'scrollHeight', 'scrollWidth', 'scrollLeft', 'scrollTop',
4147
+ 'className', 'resizable',
4148
+ 'visible', 'sourceIndex'].each do |attr|
4149
+ hash[attr] = attribute_value(attr)
4150
+ end
4151
+ hash
4152
+ end
4153
+
4154
+ def dimensions
4155
+ hash = bounding_client_rectangle
4156
+ [hash['width'], hash['height']]
4157
+ end
4158
+
4159
+ def bounding_client_rectangle
4160
+ assert_exists
4161
+ self.browser.execute_script("return arguments[0].getBoundingClientRect()", self)
4162
+ end
4163
+
4164
+ ###################################
4165
+ def bottom_edge
4166
+ bounding_client_rectangle['bottom']
4167
+ end
4168
+
4169
+ ###################################
4170
+ def top_edge
4171
+ bounding_client_rectangle['top']
4172
+ end
4173
+
4174
+ ###################################
4175
+ def left_edge
4176
+ bounding_client_rectangle['left']
4177
+ end
4178
+
4179
+ ###################################
4180
+ def right_edge
4181
+ bounding_client_rectangle['right']
4182
+ end
4183
+
4184
+ ###################################
4185
+ def client_offset
4186
+ hash = bounding_client_rectangle
4187
+ [hash['left'], hash['top']]
4188
+ end
4189
+
4190
+
4191
+ end
4192
+ end
4193
+
4194
+ class Hash
4195
+ def depth
4196
+ a = self.to_a
4197
+ d = 1
4198
+ while (a.flatten!(1).map! { |e| (e.is_a? Hash) ? e.to_a.flatten(1) : (e.is_a? Array) ? e : nil }.compact!.size > 0)
4199
+ d += 1
4200
+ end
4201
+ d
4202
+ end
4203
+ end
4204
+
4205
+ class String
4206
+
4207
+ def -(other)
4208
+ self.index(other) == 0 ? self[other.size..self.size] : nil
4209
+ end
4210
+ end
4211
+
4212
+ class HTMLValidationResult
4213
+
4214
+ def validate
4215
+ require 'fileutils'
4216
+
4217
+ html_file = 'tidy_this.html'
4218
+ err_file = 'tidy_err.txt'
4219
+ done_file = 'tidy_done.html'
4220
+ # FileUtils.touch(err_file) unless File.exists?(err_file)
4221
+
4222
+ puts "#{__method__}: #{Dir.pwd}"
4223
+ html = File.new(html_file, 'w')
4224
+ html.puts(@html)
4225
+ html.close
4226
+
4227
+ cmd = "tidy -quiet -f #{err_file} -o #{done_file} #{html_file}"
4228
+
4229
+ out = `#{cmd}`
4230
+ puts out
4231
+
4232
+ errs = File.open(err_file)
4233
+ result = errs.read
4234
+ errs.close
4235
+ result
4236
+
4237
+ end
4238
+
4239
+ end
4240
+