wsl 0.1.4

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.
@@ -0,0 +1,24 @@
1
+ #-------------------------------------------------------------#
2
+ # Summary: A simple convenience script to do stuff at the end
3
+ # of a test run.
4
+ #
5
+ # Purpose: 1) To print a total of passed and failed tests.
6
+ # Pre-con: None.
7
+ # Post-con: None.
8
+ #-------------------------------------------------------------#
9
+
10
+ require "wsl"
11
+
12
+
13
+ ##
14
+ # These are core tasks that have to be performed AFTER any other
15
+ # startup tasks.
16
+ #
17
+ def cleanup_core
18
+ # Print total summary at end of run.
19
+ total_summary
20
+
21
+ rem "Core cleanup activities completed."
22
+ end
23
+
24
+ cleanup_core
@@ -0,0 +1,29 @@
1
+ #-------------------------------------------------------------#
2
+ # Summary: A simple convenience script to do stuff before
3
+ # starting the test suite.
4
+ #
5
+ # Purpose: To perfom actions before starting the test suite.
6
+ # Pre-con: None.
7
+ # Post-con: None.
8
+ #-------------------------------------------------------------#
9
+
10
+ require "wsl"
11
+ require "log4r"
12
+ require "log4r/formatter/patternformatter"
13
+
14
+ ##
15
+ # These are core tasks that have to be performed BEFORE any other
16
+ # startup tasks.
17
+ #
18
+ def startup_core
19
+ # Clear the cache of any old data.
20
+ clear_cache
21
+
22
+ # Workout the test suite name and initialise a suite logger.
23
+ logFile = "logs/" + $0.to_s.split("/")[-1].chomp(".rb") + ".log"
24
+ Wsl::CustomLogger.initializeSuiteLogger(logFile)
25
+
26
+ rem "Core startup activities completed."
27
+ end
28
+
29
+ startup_core
@@ -0,0 +1,600 @@
1
+ require "IEContext"
2
+ require "wslPrivate"
3
+ require "watir/contrib/visible"
4
+
5
+ ##
6
+ # Starts the test.
7
+ #
8
+ # testName: the name of the test.
9
+ # logFile: the file to log to.
10
+ #
11
+ def start(testName, logFile=nil)
12
+ @myBrowser = BrowserContext.new(testName, logFile)
13
+ end
14
+
15
+ ##
16
+ # Opens a new browser with the given url.
17
+ #
18
+ # url: the url to point the browser to.
19
+ #
20
+ def open_url(url)
21
+ @myBrowser.logger.logStep("Opening browser at url: '" + url + "'")
22
+
23
+ # Point to url and open.
24
+ @myBrowser.new_browser_at(url)
25
+ @myBrowser.browser.speed = :zippy
26
+ end
27
+
28
+ ##
29
+ # Returns the current url of the browser.
30
+ #
31
+ def current_url
32
+ @myBrowser.logger.logStep("Current url: '" + @myBrowser.currentUrl + "'")
33
+ return @myBrowser.currentUrl
34
+ end
35
+
36
+ ##
37
+ # Attaches the test to a new browser window
38
+ # TODO: How to close the old window?
39
+ #
40
+ # windowTitle: the name of the new window to attach to
41
+ #
42
+ def attach(windowTitle)
43
+ @myBrowser.logger.logStep("Attaching to new window with title: '" + windowTitle + "'")
44
+ @myBrowser.attach(windowTitle)
45
+ end
46
+
47
+ ##
48
+ # Closes the attached browser window.
49
+ #
50
+ def close(windowTitle=nil)
51
+
52
+ # Attach to the browser with the name passed in.
53
+ attach(windowTitle) if windowTitle != nil
54
+
55
+ @myBrowser.logger.logStep("Closing browser")
56
+ @myBrowser.close_browser
57
+ end
58
+
59
+ ##
60
+ # Navigates to the given url.
61
+ #
62
+ # url: the url to navigate to.
63
+ #
64
+ def go_to(url)
65
+ @myBrowser.logger.logStep("Navigating to url: '" + url + "'")
66
+ @myBrowser.browser.goto(url)
67
+ end
68
+
69
+ ##
70
+ # Browses back a page.
71
+ #
72
+ def back
73
+ @myBrowser.logger.logStep("Navigating back.")
74
+ @myBrowser.browser.back()
75
+ end
76
+
77
+ ##
78
+ # Finishes the test.
79
+ #
80
+ def finish
81
+ @myBrowser.close_browser
82
+ @myBrowser.logger.logEndTest
83
+ @myBrowser.logger.summary
84
+
85
+ # Reset step counter.
86
+ @myBrowser.logger.reset
87
+ end
88
+
89
+ ##
90
+ # Prints the total summary of all passed and
91
+ # failed tests in run.
92
+ #
93
+ def total_summary
94
+ if ! defined? @myBrowser then
95
+ @myBrowser = BrowserContext.new()
96
+ end
97
+
98
+ @myBrowser.logger.totalSummary
99
+
100
+ # Clear the test cache so as not to corrupt the test summary.
101
+ @myBrowser.logger.clearCache
102
+ end
103
+
104
+ ##
105
+ # Clears the cache used by the logger.
106
+ #
107
+ def clear_cache
108
+ if ! defined? @myBrowser then
109
+ @myBrowser = BrowserContext.new()
110
+ end
111
+
112
+ # Clear the test cache so as not to corrupt the test summary.
113
+ @myBrowser.logger.clearCache
114
+ end
115
+
116
+ ##
117
+ # Enters text in the named field.
118
+ # field: The id of the html field.
119
+ # value: The value you want to set.
120
+ #
121
+ # def enter_text_in(field, value)
122
+ # @myBrowser.logger.logStep("Entering text into field '" + field + "' with value '" + value + "'")
123
+ # @myBrowser.enter_text_into_field_with_id(field, value)
124
+ # end
125
+ def enter_text_in(what, how=":id", value=nil)
126
+ @myBrowser.logger.logStep("Entering text into html element with #{how} '" + what + "'")
127
+
128
+ # parse string to build up correct code with right 'how' attribute.
129
+ code = <<TEMPLATE
130
+ @myBrowser.browser.send(tag, #{how}, what)
131
+ TEMPLATE
132
+
133
+ @myBrowser.tagsInContext.each do |tag|
134
+ # Evaluate the code to execute it.
135
+ element = eval(code)
136
+
137
+ # Determine whether the passed in element has the method we want.
138
+ if element.exist? && element.respond_to?(:set) then
139
+ begin
140
+ return element.set(value)
141
+ rescue => ex
142
+ # Do nothing, we want to carry on through the list as
143
+ # more than one type of element may have the set method.
144
+ end
145
+ end
146
+ end
147
+
148
+ # Notify the user element was not find.
149
+ @myBrowser.logger.log(" HTML element with #{how} '" + what + "' not found.")
150
+ end
151
+
152
+ ##
153
+ # Fires an onKeyPress event for the given textbox.
154
+ #
155
+ # field: The textbox to fire the event for (HTML id).
156
+ #
157
+ def key_press_in(field)
158
+ @myBrowser.logger.logStep("Firing onKeyPress event for: '" + field + "'")
159
+ @myBrowser.browser.text_field(:id, field).fire_event('onkeypress')
160
+ end
161
+
162
+ ##
163
+ # Fires an onKeyUp event for the given textbox.
164
+ #
165
+ # field: The textbox to fire the event for (HTML id).
166
+ #
167
+ def key_up_in(field)
168
+ @myBrowser.logger.logStep("Firing onKeyPress event for: '" + field + "'")
169
+ @myBrowser.browser.text_field(:id, field).fire_event('onkeyup')
170
+ end
171
+
172
+ ##
173
+ # Fires a onMouseOver event for the given textbox.
174
+ #
175
+ # field: The textbox to fire the event for (HTML id).
176
+ #
177
+ def mouse_over(field)
178
+ @myBrowser.logger.logStep("Firing onMouseOver event for: '" + field + "'")
179
+ @myBrowser.browser.text_field(:id, field).fire_event('onMouseOver')
180
+ end
181
+
182
+ ##
183
+ # Fires a onMouseDown event for the given textbox.
184
+ #
185
+ # field: The textbox to fire the event for (HTML id).
186
+ #
187
+ def mouse_down(field)
188
+ @myBrowser.logger.logStep("Firing onMouseDown event for: '" + field + "'")
189
+ @myBrowser.browser.text_field(:id, field).fire_event('onMouseDown')
190
+ end
191
+
192
+ ##
193
+ # Selects the named element.
194
+ #
195
+ # what: The element to select.
196
+ # value: if specified true checks it, false unchecks it.
197
+ #
198
+ def select(what, how=":id", value=true)
199
+ @myBrowser.logger.logStep("Selecting html element with #{how} '" + what + "'")
200
+
201
+ # parse string to build up correct code with right 'how' attribute.
202
+ code = <<TEMPLATE
203
+ @myBrowser.browser.send(tag, #{how}, what)
204
+ TEMPLATE
205
+
206
+ @myBrowser.tagsInContext.each do |tag|
207
+ # Evaluate the code to execute it.
208
+ element = eval(code)
209
+
210
+ # Determine whether the passed in element has the method we want.
211
+ if element.exist? && element.respond_to?(:set) then
212
+ begin
213
+ return element.set(value)
214
+ rescue => ex
215
+ # Do nothing, we want to carry on through the list as
216
+ # more than one type of element may have the set method.
217
+ end
218
+ end
219
+ end
220
+
221
+ # Notify the user element was not find.
222
+ @myBrowser.logger.log(" HTML element with #{how} '" + what + "' not found.")
223
+ end
224
+
225
+ ##
226
+ # Clicks the HTML element with the id specified. Note if multiple elements
227
+ # are present it will click the first occurence of it only. The order it
228
+ # searches in is - button, link, image, div, span, and finally text_field.
229
+ #
230
+ def click(what, how=":id")
231
+ @myBrowser.logger.logStep("Clicking on html element with #{how} '" + what + "'")
232
+
233
+ # parse string to build up correct code with right 'how' attribute.
234
+ code = <<TEMPLATE
235
+ @myBrowser.browser.send(tag, #{how}, what)
236
+ TEMPLATE
237
+
238
+ @myBrowser.tagsInContext.each do |tag|
239
+ # Evaluate the code to execute it.
240
+ element = eval(code)
241
+
242
+ # Determine whether the passed in element id exists, and click it.
243
+ if element.exist? && element.respond_to?(:click) then
244
+ return element.click
245
+ end
246
+ end
247
+
248
+ # Notify the user element was not find.
249
+ @myBrowser.logger.log(" HTML element with #{how} '" + what + "' not found.")
250
+ end
251
+
252
+ ##
253
+ # Waits for the HTML element with the id specified to exist on screen.
254
+ # Note if multiple elements are present it will look for the first occurence
255
+ # of it only or until the timeout (in seconds) is exceeded.
256
+ #
257
+ # The order it searches in is -
258
+ # button, link, image, div, span, and finally text_field.
259
+ #
260
+ def wait_for(what, how=":id", timeout=60)
261
+ @myBrowser.logger.logStep("Waiting to load: '" + what + "'")
262
+ tries = 0
263
+
264
+ # parse string to build up correct code with right 'how' attribute.
265
+ code = <<TEMPLATE
266
+ @myBrowser.browser.send(tag, #{how}, what)
267
+ TEMPLATE
268
+
269
+ # Until timeout is exceeded (or element exists).
270
+ until tries >= timeout do
271
+ @myBrowser.tagsInContext.each do |tag|
272
+ element = eval(code)
273
+ # Evaluate the code to execute it and see if it exists.
274
+ return if element.exists?
275
+ end
276
+
277
+ # Sleep for a bit and then try again.
278
+ sleep 0.1
279
+ tries += 0.1
280
+ end
281
+
282
+ # if got to here then notify the user element was not find.
283
+ @myBrowser.logger.log(" HTML element with id '" + what + "' not found.")
284
+ end
285
+
286
+ ##
287
+ # Waits for the browser to catch up. Useful for ajax calls
288
+ # where the browser loads up some javascript.
289
+ #
290
+ def wait(aMoment=0)
291
+ if aMoment == 0 then
292
+ @myBrowser.logger.logStep("Waiting for browser to catch up")
293
+ else
294
+ @myBrowser.logger.logStep("Pausing for " + aMoment.to_s + " secs then waiting for browser to catch up")
295
+ sleep aMoment
296
+ end
297
+
298
+ @myBrowser.browser.wait
299
+ end
300
+
301
+ ##
302
+ # Waits for a div tag to become visible or until the timeout
303
+ # period has elapsed.
304
+ # what: The id of the HTML div tag.
305
+ # timout: maximum amount of time to wait for (default is 60 secs).
306
+ #
307
+ # TODO: Merge with wait_for method (add visible? to if condition)
308
+ #
309
+ def wait_until_visible(what, how=":id", timeout=60)
310
+ @myBrowser.logger.logStep("Waiting for : '" + what + "' to become visible")
311
+
312
+ tries = 0
313
+
314
+ # parse string to build up correct code with right 'how' attribute.
315
+ code = <<TEMPLATE
316
+ @myBrowser.browser.send(tag, #{how}, what)
317
+ TEMPLATE
318
+
319
+ # Until timeout is exceeded (or element exists).
320
+ until tries >= timeout do
321
+ @myBrowser.tagsInContext.each do |tag|
322
+ # Evaluate the code to execute it and see if it exists.
323
+ element = eval(code)
324
+
325
+ # Element exists and is visible.
326
+ return element.visible? if element.exist? && element.visible?
327
+ end
328
+
329
+ # Sleep for a bit and then try again.
330
+ sleep 0.1
331
+ tries += 0.1
332
+ end
333
+
334
+ # if got to here then notify the user element was not find.
335
+ @myBrowser.logger.log(" HTML element with id '" + what + "' has not become visible before timeout.")
336
+ end
337
+
338
+ ##
339
+ # Records expected result, then asserts whether the
340
+ # text is displayed on screen to verify the expected
341
+ # result.
342
+ #
343
+ # text: The text to look for on screen.
344
+ # expectedResult: The expected result we are trying to verify. - This could potentially be factored out???
345
+ #
346
+ def assert_text(text, expectedResult=nil, timeout=60)
347
+ @myBrowser.logger.logExpectedResult("'" + text + "' " + expectedResult) if expectedResult != nil
348
+ isFound = check_for_text(text)
349
+
350
+ # Until conditions met sleep for 1 sec and then try again.
351
+ if timeout > 0 then
352
+ tries = 0
353
+
354
+ until isFound || tries >= timeout do # URL match found or timeout exceeded.
355
+ isFound = check_for_text(text)
356
+ sleep 1
357
+ tries += 1
358
+ end
359
+ end
360
+
361
+ if isFound then
362
+ # Text found
363
+ if expectedResult != nil then
364
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::pass, "'" + text + "' found on screen.")
365
+ end
366
+ return true
367
+ else
368
+ # Text wasn't found
369
+ if expectedResult != nil then
370
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::fail, "'" + text + "' NOT found on screen.")
371
+ end
372
+ return false
373
+ end
374
+ end
375
+
376
+ ##
377
+ # Records expected result, then asserts whether the
378
+ # text is NOT displayed on screen to verify the expected
379
+ # result.
380
+ #
381
+ # text: The text to look for on screen.
382
+ # expectedResult: The expected result we are trying to verify. - This could potentially be factored out???
383
+ #
384
+ def assert_text!(text, expectedResult=nil)
385
+ @myBrowser.logger.logExpectedResult("'" + text+ "' " + expectedResult) if expectedResult != nil
386
+
387
+ begin
388
+ if defined? @myBrowser.assert_text_in_body(text) then
389
+
390
+ # If this is nil then we are doing a flow control assert - Do not log a test result
391
+ if expectedResult != nil then
392
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::fail, "'" + text + "' found on screen.")
393
+ end
394
+
395
+ return false
396
+ else
397
+ # If this is nil then we are doing a flow control assert - Do not log a test result
398
+ if expectedResult != nil then
399
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::pass, "'" + text + "' NOT found on screen.")
400
+ end
401
+
402
+ return true
403
+ end
404
+ rescue => ex
405
+ # Remember exception thrown when text not found.
406
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::pass, "'" + text + "' NOT found on screen.")
407
+ return false
408
+ end
409
+ end
410
+
411
+ def assert_all_text(args)
412
+ @myBrowser.logger.logExpectedResult("Asserting all text is shown on screen...")
413
+
414
+ # Iterate and return false if any member of the array doesn't exist.
415
+ args.each do |at|
416
+ return false if !assert_text(at, "Expecting " + at + " to exist on screen.")
417
+ end
418
+
419
+ # Otherwise assertion is true.
420
+ return true
421
+ end
422
+
423
+ ##
424
+ # Asserts that the current url matches the pased in url. If orFailValue is
425
+ # specified then a clever assertion is done whereby the method asserts
426
+ # every second until the url is matched, or the 'orFailValue' is matched to
427
+ # the url OR found in the text body. If neither of these conditions are met
428
+ # within the timeout period then a fail due to a time out is registered
429
+ # for this assertion.
430
+ #
431
+ # The clever assertion is a workaround for any ajax submissions we do.
432
+ # currently there is no way to determine a response for an ajax call using
433
+ # Watir (There is an outstanding development request regarding this).
434
+ #
435
+ # url: The url to match on.
436
+ # expectedResult: The expected result message to show on screen.
437
+ # timeout: period in seconds before registering a failed assertion.
438
+ # orFailValue: a value if found in the url or body text registers a fail.
439
+ #
440
+ def assert_url(url, expectedResult="is current url.", timeout=60, orFailValue=nil)
441
+ # Get rid of the query string portion.
442
+ splitUrl = @myBrowser.currentUrl.split("?")[0]
443
+
444
+ @myBrowser.logger.logExpectedResult("'" + url.to_s + "' " + expectedResult.to_s)
445
+ tries = 0
446
+
447
+ begin
448
+ # Clever assertion.
449
+ if orFailValue != nil then
450
+ # Until conditions met sleep for 1 sec and then try again.
451
+ until splitUrl.downcase == url.downcase || # URL match found.
452
+ splitUrl.downcase == orFailValue.downcase || # Fail value found in url.
453
+ @myBrowser.assert_text_in_body(orFailValue) == nil || # Fail value found in body.
454
+ tries >= timout do # Timeout exceeded.
455
+ sleep 1
456
+ tries += 1
457
+ end
458
+ # Simple assertion.
459
+ else
460
+ # Until conditions met sleep for 1 sec and then try again.
461
+ until splitUrl.downcase == url.downcase || # URL match found.
462
+ tries >= timeout do # Timeout exceeded.
463
+ sleep 1
464
+ tries += 1
465
+ end
466
+ end
467
+
468
+ # Assert pass or fail.
469
+ assert_url_conditions(splitUrl, url, timeout, orFailValue)
470
+ rescue => ex
471
+ @myBrowser.logger.logException ex
472
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::fail,
473
+ "'" + url.to_s + "' NOT current url or on screen." +
474
+ "\n '" + @myBrowser.currentUrl + "' is current url.")
475
+ return false
476
+ end
477
+ end
478
+
479
+ ##
480
+ # Logs a comment.
481
+ #
482
+ # text: The comment to log.
483
+ #
484
+ def rem(text)
485
+ @myBrowser.logger.logComment(text)
486
+ end
487
+
488
+ def manual_test(steps)
489
+ @myBrowser.logger.log(" Manual steps to perform:")
490
+
491
+ # Log the steps
492
+ steps.each do |step|
493
+ @myBrowser.logger.logStep(step)
494
+ end
495
+
496
+ # Ask for pass or fail
497
+ result = ""
498
+
499
+ until result.upcase == "P" || result.upcase == "F" do
500
+ puts " Manual test pass or fail (P/F)? "
501
+ result = gets.chomp
502
+ end
503
+
504
+ # Log result
505
+ @myBrowser.logger.logExpectedResult("Manual test passes")
506
+
507
+ if result.upcase == "P" then
508
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::pass, "Manual test passed")
509
+ else
510
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::fail, "Manual test failed")
511
+ end
512
+ end
513
+
514
+ ##
515
+ # Records a PASS if the link exists
516
+ #
517
+ # what: The HTML id of the link
518
+ #
519
+ def assert_link_exists(what, expectedResult)
520
+ @myBrowser.logger.logExpectedResult(expectedResult)
521
+
522
+ if @myBrowser.browser.link(:id, what).exists? then
523
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::pass, "Link does exist")
524
+ return true
525
+ else
526
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::fail, "Link does not exist")
527
+ return false
528
+ end
529
+ end
530
+
531
+ ##
532
+ # Records a PASS if the button exists
533
+ #
534
+ # what: The HTML id of the button
535
+ #
536
+ def assert_button_exists(what, expectedResult)
537
+ @myBrowser.logger.logExpectedResult(expectedResult)
538
+
539
+ if @myBrowser.browser.button(:id, what).exists? then
540
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::pass, "Button does exist")
541
+ return true
542
+ else
543
+ @myBrowser.logger.logActualResult(Wsl::CustomLogger::fail, "Button does not exist")
544
+ return false
545
+ end
546
+ end
547
+
548
+ ##
549
+ # Allows other steps to be executed and if certain conditions are not met then
550
+ # the steps are repeated. Ideal for performing some manual steps which if not
551
+ # done correctly then need to be repeated. If in the passed in block of steps
552
+ # conditions are not met then call retryable_steps_error with appropriate message
553
+ # to prompt for a repeat.
554
+ #
555
+ # -------------------------------------------------------------------------------
556
+ # Example usage:
557
+ # retryable_steps{
558
+ # Do some steps here
559
+ # ...
560
+ # if pass condition is fail then
561
+ # Do any further steps if needed
562
+ # ...
563
+ # # Record the error with message
564
+ # retryable_steps_error "The steps failed you need to retry again"
565
+ # end
566
+ #}
567
+ # -------------------------------------------------------------------------------
568
+ #
569
+ # &block: The block of code to pass in (must be surrounded by '{' and '}')
570
+ #
571
+ def retryable_steps(&block)
572
+ begin
573
+ # Call the block
574
+ yield
575
+ rescue => ex
576
+ # Output the message for completeness and then retry.
577
+ rem ex.message
578
+ retry
579
+ end
580
+ end
581
+
582
+ ##
583
+ # Used to report a retryable_steps needs to be re-tried.
584
+ # If in the retryable steps the condition(s) to determine
585
+ # pass/fail of the steps fails then call this.
586
+ #
587
+ # message: The message to display before retrying.
588
+ #
589
+ def retryable_steps_error(message)
590
+ # TODO: Create a custom error/exception?
591
+ raise ArgumentError, message
592
+ end
593
+
594
+ ##
595
+ # Shows all the elements in context in the order they are searched through.
596
+ #
597
+ def elements_in_context
598
+ rem "elements in context in order of precedence: \n[" +
599
+ @myBrowser.tagsInContext().join(", ") + "]"
600
+ end