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

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