| // Copyright 2008 The Closure Library Authors. 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 Matchers to be used with the mock utilities. They allow for |
| * flexible matching by type. Custom matchers can be created by passing a |
| * matcher function into an ArgumentMatcher instance. |
| * |
| * For examples, please see the unit test. |
| * |
| */ |
| |
| |
| goog.provide('goog.testing.mockmatchers'); |
| goog.provide('goog.testing.mockmatchers.ArgumentMatcher'); |
| goog.provide('goog.testing.mockmatchers.IgnoreArgument'); |
| goog.provide('goog.testing.mockmatchers.InstanceOf'); |
| goog.provide('goog.testing.mockmatchers.ObjectEquals'); |
| goog.provide('goog.testing.mockmatchers.RegexpMatch'); |
| goog.provide('goog.testing.mockmatchers.SaveArgument'); |
| goog.provide('goog.testing.mockmatchers.TypeOf'); |
| |
| goog.require('goog.array'); |
| goog.require('goog.dom'); |
| goog.require('goog.testing.asserts'); |
| |
| |
| |
| /** |
| * A simple interface for executing argument matching. A match in this case is |
| * testing to see if a supplied object fits a given criteria. True is returned |
| * if the given criteria is met. |
| * @param {Function=} opt_matchFn A function that evaluates a given argument |
| * and returns true if it meets a given criteria. |
| * @param {?string=} opt_matchName The name expressing intent as part of |
| * an error message for when a match fails. |
| * @constructor |
| */ |
| goog.testing.mockmatchers.ArgumentMatcher = |
| function(opt_matchFn, opt_matchName) { |
| /** |
| * A function that evaluates a given argument and returns true if it meets a |
| * given criteria. |
| * @type {Function} |
| * @private |
| */ |
| this.matchFn_ = opt_matchFn || null; |
| |
| /** |
| * A string indicating the match intent (e.g. isBoolean or isString). |
| * @type {?string} |
| * @private |
| */ |
| this.matchName_ = opt_matchName || null; |
| }; |
| |
| |
| /** |
| * A function that takes a match argument and an optional MockExpectation |
| * which (if provided) will get error information and returns whether or |
| * not it matches. |
| * @param {*} toVerify The argument that should be verified. |
| * @param {goog.testing.MockExpectation?=} opt_expectation The expectation |
| * for this match. |
| * @return {boolean} Whether or not a given argument passes verification. |
| */ |
| goog.testing.mockmatchers.ArgumentMatcher.prototype.matches = |
| function(toVerify, opt_expectation) { |
| if (this.matchFn_) { |
| var isamatch = this.matchFn_(toVerify); |
| if (!isamatch && opt_expectation) { |
| if (this.matchName_) { |
| opt_expectation.addErrorMessage('Expected: ' + |
| this.matchName_ + ' but was: ' + _displayStringForValue(toVerify)); |
| } else { |
| opt_expectation.addErrorMessage('Expected: missing mockmatcher' + |
| ' description but was: ' + |
| _displayStringForValue(toVerify)); |
| } |
| } |
| return isamatch; |
| } else { |
| throw Error('No match function defined for this mock matcher'); |
| } |
| }; |
| |
| |
| |
| /** |
| * A matcher that verifies that an argument is an instance of a given class. |
| * @param {Function} ctor The class that will be used for verification. |
| * @constructor |
| * @extends {goog.testing.mockmatchers.ArgumentMatcher} |
| * @final |
| */ |
| goog.testing.mockmatchers.InstanceOf = function(ctor) { |
| goog.testing.mockmatchers.ArgumentMatcher.call(this, |
| function(obj) { |
| return obj instanceof ctor; |
| // NOTE: Browser differences on ctor.toString() output |
| // make using that here problematic. So for now, just let |
| // people know the instanceOf() failed without providing |
| // browser specific details... |
| }, 'instanceOf()'); |
| }; |
| goog.inherits(goog.testing.mockmatchers.InstanceOf, |
| goog.testing.mockmatchers.ArgumentMatcher); |
| |
| |
| |
| /** |
| * A matcher that verifies that an argument is of a given type (e.g. "object"). |
| * @param {string} type The type that a given argument must have. |
| * @constructor |
| * @extends {goog.testing.mockmatchers.ArgumentMatcher} |
| * @final |
| */ |
| goog.testing.mockmatchers.TypeOf = function(type) { |
| goog.testing.mockmatchers.ArgumentMatcher.call(this, |
| function(obj) { |
| return goog.typeOf(obj) == type; |
| }, 'typeOf(' + type + ')'); |
| }; |
| goog.inherits(goog.testing.mockmatchers.TypeOf, |
| goog.testing.mockmatchers.ArgumentMatcher); |
| |
| |
| |
| /** |
| * A matcher that verifies that an argument matches a given RegExp. |
| * @param {RegExp} regexp The regular expression that the argument must match. |
| * @constructor |
| * @extends {goog.testing.mockmatchers.ArgumentMatcher} |
| * @final |
| */ |
| goog.testing.mockmatchers.RegexpMatch = function(regexp) { |
| goog.testing.mockmatchers.ArgumentMatcher.call(this, |
| function(str) { |
| return regexp.test(str); |
| }, 'match(' + regexp + ')'); |
| }; |
| goog.inherits(goog.testing.mockmatchers.RegexpMatch, |
| goog.testing.mockmatchers.ArgumentMatcher); |
| |
| |
| |
| /** |
| * A matcher that always returns true. It is useful when the user does not care |
| * for some arguments. |
| * For example: mockFunction('username', 'password', IgnoreArgument); |
| * @constructor |
| * @extends {goog.testing.mockmatchers.ArgumentMatcher} |
| * @final |
| */ |
| goog.testing.mockmatchers.IgnoreArgument = function() { |
| goog.testing.mockmatchers.ArgumentMatcher.call(this, |
| function() { |
| return true; |
| }, 'true'); |
| }; |
| goog.inherits(goog.testing.mockmatchers.IgnoreArgument, |
| goog.testing.mockmatchers.ArgumentMatcher); |
| |
| |
| |
| /** |
| * A matcher that verifies that the argument is an object that equals the given |
| * expected object, using a deep comparison. |
| * @param {Object} expectedObject An object to match against when |
| * verifying the argument. |
| * @constructor |
| * @extends {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.ObjectEquals = function(expectedObject) { |
| goog.testing.mockmatchers.ArgumentMatcher.call(this, |
| function(matchObject) { |
| assertObjectEquals('Expected equal objects', expectedObject, |
| matchObject); |
| return true; |
| }, 'objectEquals(' + expectedObject + ')'); |
| }; |
| goog.inherits(goog.testing.mockmatchers.ObjectEquals, |
| goog.testing.mockmatchers.ArgumentMatcher); |
| |
| |
| /** @override */ |
| goog.testing.mockmatchers.ObjectEquals.prototype.matches = |
| function(toVerify, opt_expectation) { |
| // Override the default matches implementation to capture the exception thrown |
| // by assertObjectEquals (if any) and add that message to the expectation. |
| try { |
| return goog.testing.mockmatchers.ObjectEquals.superClass_.matches.call( |
| this, toVerify, opt_expectation); |
| } catch (e) { |
| if (opt_expectation) { |
| opt_expectation.addErrorMessage(e.message); |
| } |
| return false; |
| } |
| }; |
| |
| |
| |
| /** |
| * A matcher that saves the argument that it is verifying so that your unit test |
| * can perform extra tests with this argument later. For example, if the |
| * argument is a callback method, the unit test can then later call this |
| * callback to test the asynchronous portion of the call. |
| * @param {goog.testing.mockmatchers.ArgumentMatcher|Function=} opt_matcher |
| * Argument matcher or matching function that will be used to validate the |
| * argument. By default, argument will always be valid. |
| * @param {?string=} opt_matchName The name expressing intent as part of |
| * an error message for when a match fails. |
| * @constructor |
| * @extends {goog.testing.mockmatchers.ArgumentMatcher} |
| * @final |
| */ |
| goog.testing.mockmatchers.SaveArgument = function(opt_matcher, opt_matchName) { |
| goog.testing.mockmatchers.ArgumentMatcher.call( |
| this, /** @type {Function} */ (opt_matcher), opt_matchName); |
| |
| if (opt_matcher instanceof goog.testing.mockmatchers.ArgumentMatcher) { |
| /** |
| * Delegate match requests to this matcher. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| * @private |
| */ |
| this.delegateMatcher_ = opt_matcher; |
| } else if (!opt_matcher) { |
| this.delegateMatcher_ = goog.testing.mockmatchers.ignoreArgument; |
| } |
| }; |
| goog.inherits(goog.testing.mockmatchers.SaveArgument, |
| goog.testing.mockmatchers.ArgumentMatcher); |
| |
| |
| /** @override */ |
| goog.testing.mockmatchers.SaveArgument.prototype.matches = function( |
| toVerify, opt_expectation) { |
| this.arg = toVerify; |
| if (this.delegateMatcher_) { |
| return this.delegateMatcher_.matches(toVerify, opt_expectation); |
| } |
| return goog.testing.mockmatchers.SaveArgument.superClass_.matches.call( |
| this, toVerify, opt_expectation); |
| }; |
| |
| |
| /** |
| * Saved argument that was verified. |
| * @type {*} |
| */ |
| goog.testing.mockmatchers.SaveArgument.prototype.arg; |
| |
| |
| /** |
| * An instance of the IgnoreArgument matcher. Returns true for all matches. |
| * @type {goog.testing.mockmatchers.IgnoreArgument} |
| */ |
| goog.testing.mockmatchers.ignoreArgument = |
| new goog.testing.mockmatchers.IgnoreArgument(); |
| |
| |
| /** |
| * A matcher that verifies that an argument is an array. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isArray = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isArray, |
| 'isArray'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is a array-like. A NodeList is an |
| * example of a collection that is very close to an array. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isArrayLike = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isArrayLike, |
| 'isArrayLike'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is a date-like. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isDateLike = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isDateLike, |
| 'isDateLike'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is a string. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isString = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isString, |
| 'isString'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is a boolean. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isBoolean = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isBoolean, |
| 'isBoolean'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is a number. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isNumber = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isNumber, |
| 'isNumber'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is a function. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isFunction = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isFunction, |
| 'isFunction'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is an object. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isObject = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.isObject, |
| 'isObject'); |
| |
| |
| /** |
| * A matcher that verifies that an argument is like a DOM node. |
| * @type {goog.testing.mockmatchers.ArgumentMatcher} |
| */ |
| goog.testing.mockmatchers.isNodeLike = |
| new goog.testing.mockmatchers.ArgumentMatcher(goog.dom.isNodeLike, |
| 'isNodeLike'); |
| |
| |
| /** |
| * A function that checks to see if an array matches a given set of |
| * expectations. The expectations array can be a mix of ArgumentMatcher |
| * implementations and values. True will be returned if values are identical or |
| * if a matcher returns a positive result. |
| * @param {Array<?>} expectedArr An array of expectations which can be either |
| * values to check for equality or ArgumentMatchers. |
| * @param {Array<?>} arr The array to match. |
| * @param {goog.testing.MockExpectation?=} opt_expectation The expectation |
| * for this match. |
| * @return {boolean} Whether or not the given array matches the expectations. |
| */ |
| goog.testing.mockmatchers.flexibleArrayMatcher = |
| function(expectedArr, arr, opt_expectation) { |
| return goog.array.equals(expectedArr, arr, function(a, b) { |
| var errCount = 0; |
| if (opt_expectation) { |
| errCount = opt_expectation.getErrorMessageCount(); |
| } |
| var isamatch = a === b || |
| a instanceof goog.testing.mockmatchers.ArgumentMatcher && |
| a.matches(b, opt_expectation); |
| var failureMessage = null; |
| if (!isamatch) { |
| failureMessage = goog.testing.asserts.findDifferences(a, b); |
| isamatch = !failureMessage; |
| } |
| if (!isamatch && opt_expectation) { |
| // If the error count changed, the match sent out an error |
| // message. If the error count has not changed, then |
| // we need to send out an error message... |
| if (errCount == opt_expectation.getErrorMessageCount()) { |
| // Use the _displayStringForValue() from assert.js |
| // for consistency... |
| if (!failureMessage) { |
| failureMessage = 'Expected: ' + _displayStringForValue(a) + |
| ' but was: ' + _displayStringForValue(b); |
| } |
| opt_expectation.addErrorMessage(failureMessage); |
| } |
| } |
| return isamatch; |
| }); |
| }; |