| // Copyright 2011 Software Freedom Conservancy. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| /** |
| * @fileoverview Defines a special test case that runs each test inside of a |
| * {@code webdriver.Application}. This allows each phase to schedule |
| * asynchronous actions that run to completion before the next phase of the |
| * test. |
| * |
| * This file requires the global {@code G_testRunner} to be initialized before |
| * use. This can be accomplished by also importing |
| * {@link webdriver.testing.jsunit}. This namespace is not required by default |
| * to improve interoperability with other namespaces that may initialize |
| * G_testRunner. |
| */ |
| |
| goog.provide('webdriver.testing.TestCase'); |
| |
| goog.require('goog.testing.TestCase'); |
| goog.require('webdriver.promise.Application'); |
| /** @suppress {extraRequire} Imported for user convenience. */ |
| goog.require('webdriver.testing.asserts'); |
| |
| |
| |
| /** |
| * Constructs a test case that synchronizes each test case with the singleton |
| * {@code webdriver.promise.Application}. |
| * |
| * @param {string=} opt_name The name of the test case, defaults to |
| * 'Untitled Test Case'. |
| * @constructor |
| * @extends {goog.testing.TestCase} |
| */ |
| webdriver.testing.TestCase = function(opt_name) { |
| goog.base(this, opt_name); |
| }; |
| goog.inherits(webdriver.testing.TestCase, goog.testing.TestCase); |
| |
| |
| /** |
| * Executes the next test inside its own {@code webdriver.Application}. |
| * @override |
| */ |
| webdriver.testing.TestCase.prototype.cycleTests = function() { |
| var test = this.next(); |
| if (!test) { |
| this.finalize(); |
| return; |
| } |
| |
| goog.testing.TestCase.currentTestName = test.name; |
| this.result_.runCount++; |
| this.log('Running test: ' + test.name); |
| |
| var self = this; |
| var hadError = false; |
| var app = webdriver.promise.Application.getInstance(); |
| |
| this.runSingleTest_(test, onError).then(function() { |
| hadError || self.doSuccess(test); |
| self.timeout(function() { |
| self.cycleTests(); |
| }, 100); |
| }); |
| |
| function onError(e) { |
| hadError = true; |
| self.doError(test, app.annotateError(e)); |
| } |
| }; |
| |
| |
| /** @override */ |
| webdriver.testing.TestCase.prototype.logError = function(name, opt_e) { |
| var errMsg = null; |
| var stack = null; |
| if (opt_e) { |
| this.log(opt_e); |
| if (goog.isString(opt_e)) { |
| errMsg = opt_e; |
| } else { |
| // In case someone calls this function directly, make sure we have a |
| // properly annotated error. |
| webdriver.promise.Application.getInstance().annotateError(opt_e); |
| errMsg = opt_e.toString(); |
| stack = opt_e.stack.substring(errMsg.length + 1); |
| } |
| } else { |
| errMsg = 'An unknown error occurred'; |
| } |
| var err = new goog.testing.TestCase.Error(name, errMsg, stack); |
| |
| // Avoid double logging. |
| if (!opt_e || !opt_e['isJsUnitException'] || |
| !opt_e['loggedJsUnitException']) { |
| this.saveMessage(err.toString()); |
| } |
| |
| if (opt_e && opt_e['isJsUnitException']) { |
| opt_e['loggedJsUnitException'] = true; |
| } |
| |
| return err; |
| }; |
| |
| |
| /** |
| * Executes a single test, scheduling each phase with the global application. |
| * Each phase will wait for the application to go idle before moving on to the |
| * next test phase. This function models the follow basic test flow: |
| * |
| * try { |
| * this.setUp.call(test.scope); |
| * test.ref.call(test.scope); |
| * } catch (ex) { |
| * onError(ex); |
| * } finally { |
| * try { |
| * this.tearDown.call(test.scope); |
| * } catch (e) { |
| * onError(e); |
| * } |
| * } |
| * |
| * @param {!goog.testing.TestCase.Test} test The test to run. |
| * @param {function(*)} onError The function to call each time an error is |
| * detected. |
| * @return {!webdriver.promise.Promise} A promise that will be resolved when the |
| * test has finished running. |
| * @private |
| */ |
| webdriver.testing.TestCase.prototype.runSingleTest_ = function(test, onError) { |
| var app = webdriver.promise.Application.getInstance(); |
| app.clearHistory(); |
| |
| return schedule(test.name + '.setUp()', this.setUp)(). |
| addCallback(schedule(test.name + '()', test.ref)). |
| addErrback(onError). |
| addCallback(schedule(test.name + '.tearDown()', this.tearDown)). |
| addErrback(onError); |
| |
| function schedule(description, fn) { |
| return function() { |
| return app.schedule(description, goog.bind(fn, test.scope)); |
| } |
| } |
| }; |