396 lines
13 KiB
JavaScript
396 lines
13 KiB
JavaScript
// 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}
|
|
*/
|
|
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}
|
|
*/
|
|
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}
|
|
*/
|
|
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}
|
|
*/
|
|
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}
|
|
*/
|
|
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;
|
|
});
|
|
};
|