Path: blob/trunk/third_party/closure/goog/testing/expectedfailures.js
4501 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56/**7* @fileoverview Helper class to allow for expected unit test failures.8*/910goog.setTestOnly('goog.testing.ExpectedFailures');11goog.provide('goog.testing.ExpectedFailures');1213goog.require('goog.asserts');14goog.require('goog.debug.DivConsole');15goog.require('goog.dom');16goog.require('goog.dom.TagName');17goog.require('goog.events');18goog.require('goog.events.EventType');19goog.require('goog.log');20goog.require('goog.style');21goog.require('goog.testing.JsUnitException');22goog.require('goog.testing.TestCase');23goog.require('goog.testing.asserts');24252627/**28* Helper class for allowing some unit tests to fail, particularly designed to29* mark tests that should be fixed on a given browser.30*31* <pre>32* var expectedFailures = new goog.testing.ExpectedFailures();33*34* function tearDown() {35* expectedFailures.handleTearDown();36* }37*38* function testSomethingThatBreaksInWebKit() {39* expectedFailures.expectFailureFor(goog.userAgent.WEBKIT);40*41* try {42* ...43* assert(somethingThatFailsInWebKit);44* ...45* } catch (e) {46* expectedFailures.handleException(e);47* }48* }49* </pre>50*51* @constructor52* @final53*/54goog.testing.ExpectedFailures = function() {55'use strict';56goog.testing.ExpectedFailures.setUpConsole_();57this.reset_();58};596061/**62* The lazily created debugging console.63* @type {goog.debug.DivConsole?}64* @private65*/66goog.testing.ExpectedFailures.console_ = null;676869/**70* Logger for the expected failures.71* @type {goog.log.Logger}72* @private73*/74goog.testing.ExpectedFailures.prototype.logger_ =75goog.log.getLogger('goog.testing.ExpectedFailures');767778/**79* Whether or not we are expecting failure.80* @type {boolean}81* @private82*/83goog.testing.ExpectedFailures.prototype.expectingFailure_;848586/**87* The string to emit upon an expected failure.88* @type {string}89* @private90*/91goog.testing.ExpectedFailures.prototype.failureMessage_;929394/**95* An array of suppressed failures.96* @type {Array<!Error>}97* @private98*/99goog.testing.ExpectedFailures.prototype.suppressedFailures_;100101102/**103* Sets up the debug console, if it isn't already set up.104* @private105*/106goog.testing.ExpectedFailures.setUpConsole_ = function() {107'use strict';108if (!goog.testing.ExpectedFailures.console_) {109var xButton = goog.dom.createDom(110goog.dom.TagName.DIV, {111'style': 'position: absolute; border-left:1px solid #333;' +112'border-bottom:1px solid #333; right: 0; top: 0; width: 1em;' +113'height: 1em; cursor: pointer; background-color: #cde;' +114'text-align: center; color: black'115},116'X');117var div = goog.dom.createDom(118goog.dom.TagName.DIV, {119'style': 'position: absolute; border: 1px solid #333; right: 10px;' +120'top : 10px; width: 400px; display: none'121},122xButton);123document.body.appendChild(div);124goog.events.listen(xButton, goog.events.EventType.CLICK, function() {125'use strict';126goog.style.setElementShown(div, false);127});128129goog.testing.ExpectedFailures.console_ = new goog.debug.DivConsole(div);130goog.log.addHandler(131goog.testing.ExpectedFailures.prototype.logger_,132goog.bind(goog.style.setElementShown, null, div, true));133goog.log.addHandler(134goog.testing.ExpectedFailures.prototype.logger_,135goog.bind(136goog.testing.ExpectedFailures.console_.addLogRecord,137goog.testing.ExpectedFailures.console_));138}139};140141142/**143* Register to expect failure for the given condition. Multiple calls to this144* function act as a boolean OR. The first applicable message will be used.145* @param {boolean} condition Whether to expect failure.146* @param {string=} opt_message Descriptive message of this expected failure.147*/148goog.testing.ExpectedFailures.prototype.expectFailureFor = function(149condition, opt_message) {150'use strict';151this.expectingFailure_ = this.expectingFailure_ || condition;152if (condition) {153this.failureMessage_ = this.failureMessage_ || opt_message || '';154}155};156157158/**159* Determines if the given exception was expected.160* @param {Object} ex The exception to check.161* @return {boolean} Whether the exception was expected.162*/163goog.testing.ExpectedFailures.prototype.isExceptionExpected = function(ex) {164'use strict';165return this.expectingFailure_ && ex instanceof goog.testing.JsUnitException;166};167168169/**170* Handle an exception, suppressing it if it is a unit test failure that we171* expected.172* @param {Error} ex The exception to handle.173*/174goog.testing.ExpectedFailures.prototype.handleException = function(ex) {175'use strict';176if (this.isExceptionExpected(ex)) {177goog.asserts.assertInstanceof(ex, goog.testing.JsUnitException);178goog.log.info(179this.logger_, 'Suppressing test failure in ' +180goog.testing.TestCase.currentTestName + ':' +181(this.failureMessage_ ? '\n(' + this.failureMessage_ + ')' : ''),182ex);183this.suppressedFailures_.push(ex);184goog.testing.TestCase.invalidateAssertionException(ex);185return;186}187188// Rethrow the exception if we weren't expecting it or if it is a normal189// exception.190throw ex;191};192193194/**195* Run the given function, catching any expected failures.196* @param {Function} func The function to run.197* @param {boolean=} opt_lenient Whether to ignore if the expected failures198* didn't occur. In this case a warning will be logged in handleTearDown.199*/200goog.testing.ExpectedFailures.prototype.run = function(func, opt_lenient) {201'use strict';202try {203func();204} catch (ex) {205this.handleException(ex);206}207208if (!opt_lenient && this.expectingFailure_ &&209!this.suppressedFailures_.length) {210fail(this.getExpectationMessage_());211}212};213214215/**216* @return {string} A warning describing an expected failure that didn't occur.217* @private218*/219goog.testing.ExpectedFailures.prototype.getExpectationMessage_ = function() {220'use strict';221return 'Expected a test failure in \'' +222goog.testing.TestCase.currentTestName + '\' but the test passed.';223};224225226/**227* Handle the tearDown phase of a test, alerting the user if an expected test228* was not suppressed.229*/230goog.testing.ExpectedFailures.prototype.handleTearDown = function() {231'use strict';232if (this.expectingFailure_ && !this.suppressedFailures_.length) {233goog.log.warning(this.logger_, this.getExpectationMessage_());234}235this.reset_();236};237238239/**240* Reset internal state.241* @private242*/243goog.testing.ExpectedFailures.prototype.reset_ = function() {244'use strict';245this.expectingFailure_ = false;246this.failureMessage_ = '';247this.suppressedFailures_ = [];248};249250251