blob: 68d8e252450fa569bca1ca4f5a76a72c58699dbf [file] [log] [blame]
// 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.
goog.provide('goog.testing.mockmatchersTest');
goog.setTestOnly('goog.testing.mockmatchersTest');
goog.require('goog.dom');
goog.require('goog.testing.jsunit');
goog.require('goog.testing.mockmatchers');
goog.require('goog.testing.mockmatchers.ArgumentMatcher');
// A local reference to the mockmatchers namespace.
var matchers = goog.testing.mockmatchers;
// Simple classes to test the InstanceOf matcher.
var foo = function() {};
var bar = function() {};
// Simple class to test adding error messages to
// MockExpectation objects
function MockMock() {
this.errorMessages = [];
}
var mockExpect = null;
MockMock.prototype.addErrorMessage = function(msg) {
this.errorMessages.push(msg);
};
MockMock.prototype.getErrorMessageCount = function() {
return this.errorMessages.length;
};
function setUp() {
mockExpect = new MockMock();
}
function testNoMatchName() {
// A matcher that does not fill in the match name
var matcher = new goog.testing.mockmatchers.ArgumentMatcher(goog.isString);
// Make sure the lack of match name doesn't affect the ability
// to return True/False
assertTrue(matcher.matches('hello'));
assertFalse(matcher.matches(123));
// Make sure we handle the lack of a match name
assertFalse(matcher.matches(456, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: missing mockmatcher description ' +
'but was: <456> (Number)', mockExpect.errorMessages[0]);
}
function testInstanceOf() {
var matcher = new matchers.InstanceOf(foo);
assertTrue(matcher.matches(new foo()));
assertFalse(matcher.matches(new bar()));
assertFalse(matcher.matches(new bar(), mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: instanceOf() ' +
'but was: <[object Object]> (Object)',
mockExpect.errorMessages[0]);
}
function testTypeOf() {
var matcher = new matchers.TypeOf('number');
assertTrue(matcher.matches(1));
assertTrue(matcher.matches(2));
assertFalse(matcher.matches('test'));
assertFalse(matcher.matches(true, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: typeOf(number) but was: <true> (Boolean)',
mockExpect.errorMessages[0]);
}
function testRegexpMatch() {
var matcher = new matchers.RegexpMatch(/^cho[dtp]/);
assertTrue(matcher.matches('chodhop'));
assertTrue(matcher.matches('chopper'));
assertFalse(matcher.matches('chocolate'));
assertFalse(matcher.matches(null));
assertFalse(matcher.matches('an anger', mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: match(/^cho[dtp]/) but was: <an anger> (String)',
mockExpect.errorMessages[0]);
}
function testObjectEquals() {
// Test a simple match.
var simpleMatcher = new matchers.ObjectEquals({name: 'Bob', age: 42});
assertTrue(simpleMatcher.matches({name: 'Bob', age: 42}, mockExpect));
assertEquals(0, mockExpect.getErrorMessageCount());
expectObjectEqualsFailure(simpleMatcher, {name: 'Bill', age: 42},
'name: Expected <Bob> (String) but was <Bill> (String)');
expectObjectEqualsFailure(simpleMatcher, {name: 'Bob', age: 21},
'age: Expected <42> (Number) but was <21> (Number)');
expectObjectEqualsFailure(simpleMatcher, {name: 'Bob'},
'property age not present in actual Object');
expectObjectEqualsFailure(simpleMatcher,
{name: 'Bob', age: 42, country: 'USA'},
'property country not present in expected Object');
// Multiple mismatches should include multiple messages.
expectObjectEqualsFailure(simpleMatcher, {name: 'Jim', age: 36},
'name: Expected <Bob> (String) but was <Jim> (String)\n' +
' age: Expected <42> (Number) but was <36> (Number)');
}
function testComplexObjectEquals() {
var complexMatcher = new matchers.ObjectEquals(
{a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'baz', sub2: -1}});
assertTrue(complexMatcher.matches(
{a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'baz', sub2: -1}}));
expectObjectEqualsFailure(complexMatcher,
{a: 'foo', b: 2, c: ['bar', 3], d: {sub1: 'zap', sub2: -1}},
'sub1: Expected <baz> (String) but was <zap> (String)');
expectObjectEqualsFailure(complexMatcher,
{a: 'foo', b: 2, c: ['bar', 6], d: {sub1: 'baz', sub2: -1}},
'c[1]: Expected <3> (Number) but was <6> (Number)');
}
function testSaveArgument() {
var saveMatcher = new matchers.SaveArgument();
assertTrue(saveMatcher.matches(42));
assertEquals(42, saveMatcher.arg);
saveMatcher = new matchers.SaveArgument(goog.isString);
assertTrue(saveMatcher.matches('test'));
assertEquals('test', saveMatcher.arg);
assertFalse(saveMatcher.matches(17));
assertEquals(17, saveMatcher.arg);
saveMatcher = new matchers.SaveArgument(new matchers.ObjectEquals({
value: 'value'
}));
assertTrue(saveMatcher.matches({ value: 'value' }));
assertEquals('value', saveMatcher.arg.value);
assertFalse(saveMatcher.matches('test'));
assertEquals('test', saveMatcher.arg);
}
function testIsArray() {
assertTrue(matchers.isArray.matches([]));
assertTrue(matchers.isArray.matches(new Array()));
assertFalse(matchers.isArray.matches('test'));
assertFalse(matchers.isArray.matches({}, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isArray but was: <[object Object]> (Object)',
mockExpect.errorMessages[0]);
}
function testIsArrayLike() {
var nodeList = (function() {
var div = document.createElement('div');
div.appendChild(document.createElement('p'));
div.appendChild(document.createElement('p'));
return div.getElementsByTagName('div');
})();
assertTrue(matchers.isArrayLike.matches([]));
assertTrue(matchers.isArrayLike.matches(new Array()));
assertTrue(matchers.isArrayLike.matches(nodeList));
assertFalse(matchers.isArrayLike.matches('test'));
assertFalse(matchers.isArrayLike.matches(3, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isArrayLike but was: <3> (Number)',
mockExpect.errorMessages[0]);
}
function testIsDateLike() {
assertTrue(matchers.isDateLike.matches(new Date()));
assertFalse(matchers.isDateLike.matches('test'));
assertFalse(matchers.isDateLike.matches('test', mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isDateLike but was: <test> (String)',
mockExpect.errorMessages[0]);
}
function testIsString() {
assertTrue(matchers.isString.matches('a'));
assertTrue(matchers.isString.matches('b'));
assertFalse(matchers.isString.matches(null));
assertFalse(matchers.isString.matches(null, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isString but was: <null>',
mockExpect.errorMessages[0]);
}
function testIsBoolean() {
assertTrue(matchers.isBoolean.matches(true));
assertTrue(matchers.isBoolean.matches(false));
assertFalse(matchers.isBoolean.matches(null));
assertFalse(matchers.isBoolean.matches([], mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isBoolean but was: <> (Array)',
mockExpect.errorMessages[0]);
}
function testIsNumber() {
assertTrue(matchers.isNumber.matches(-1));
assertTrue(matchers.isNumber.matches(1));
assertTrue(matchers.isNumber.matches(1.25));
assertFalse(matchers.isNumber.matches(null));
assertFalse(matchers.isNumber.matches('hello', mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isNumber but was: <hello> (String)',
mockExpect.errorMessages[0]);
}
function testIsFunction() {
assertTrue(matchers.isFunction.matches(function() {}));
assertFalse(matchers.isFunction.matches('test'));
assertFalse(matchers.isFunction.matches({}, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isFunction but was: <[object Object]> (Object)',
mockExpect.errorMessages[0]);
}
function testIsObject() {
assertTrue(matchers.isObject.matches({}));
assertTrue(matchers.isObject.matches(new Object()));
assertTrue(matchers.isObject.matches(new function() {}));
assertTrue(matchers.isObject.matches([]));
assertTrue(matchers.isObject.matches(new Array()));
assertTrue(matchers.isObject.matches(function() {}));
assertFalse(matchers.isObject.matches(null));
assertFalse(matchers.isObject.matches(1234, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isObject but was: <1234> (Number)',
mockExpect.errorMessages[0]);
}
function testIsNodeLike() {
assertFalse(matchers.isNodeLike.matches({}));
assertFalse(matchers.isNodeLike.matches(1));
assertFalse(matchers.isNodeLike.matches(function() {}));
assertFalse(matchers.isNodeLike.matches(false));
assertTrue(matchers.isNodeLike.matches(document.body));
assertTrue(matchers.isNodeLike.matches(goog.dom.getElement('someDiv')));
assertFalse(matchers.isNodeLike.matches('test', mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals('Expected: isNodeLike but was: <test> (String)',
mockExpect.errorMessages[0]);
}
function testIgnoreArgumentsMatcher() {
// ignoreArgument always returns true:
assertTrue(matchers.ignoreArgument.matches());
assertTrue(matchers.ignoreArgument.matches(356));
assertTrue(matchers.ignoreArgument.matches('str'));
assertTrue(matchers.ignoreArgument.matches(['array', 123, false]));
assertTrue(matchers.ignoreArgument.matches({'map': 1, key2: 'value2'}));
}
function testFlexibleArrayMatcher() {
// Test that basic lists are verified properly.
var a1 = [1, 'test'];
var a2 = [1, 'test'];
var a3 = [1, 'test', 'extra'];
assertTrue(matchers.flexibleArrayMatcher(a1, a2));
assertFalse(matchers.flexibleArrayMatcher(a1, a3));
// Test that basic lists with basic class instances are verified properly.
var instance = new foo();
a1 = [1, 'test', instance];
a2 = [1, 'test', instance];
a3 = [1, 'test', new foo()];
assertTrue(matchers.flexibleArrayMatcher(a1, a2));
assertTrue(matchers.flexibleArrayMatcher(a1, a3));
// Create an argument verifier that returns a consistent value.
var verifyValue = true;
var argVerifier = function() {};
goog.inherits(argVerifier, matchers.ArgumentMatcher);
argVerifier.prototype.matches = function(arg) {
return verifyValue;
};
// Test that the arguments are always verified when the verifier returns
// true.
a1 = [1, 'test', new argVerifier()];
a2 = [1, 'test', 'anything'];
a3 = [1, 'test', 12345];
assertTrue(matchers.flexibleArrayMatcher(a1, a2));
assertTrue(matchers.flexibleArrayMatcher(a1, a3));
// Now test the case when then verifier returns false.
verifyValue = false;
assertFalse(matchers.flexibleArrayMatcher(a1, a2));
assertFalse(matchers.flexibleArrayMatcher(a1, a3));
// And test we report errors back up via the opt_expectation
assertFalse(matchers.flexibleArrayMatcher(a2, a3, mockExpect));
assertEquals(1, mockExpect.errorMessages.length);
assertEquals(
'Expected <anything> (String) but was <12345> (Number)\n' +
' Expected <anything> (String) but was <12345> (Number)',
mockExpect.errorMessages[0]);
// And test we report errors found via the matcher
a1 = [1, goog.testing.mockmatchers.isString];
a2 = [1, 'test string'];
a3 = [1, null];
assertTrue(matchers.flexibleArrayMatcher(a1, a2, mockExpect));
assertFalse(matchers.flexibleArrayMatcher(a1, a3, mockExpect));
// Old error is still there
assertEquals(2, mockExpect.errorMessages.length);
assertEquals(
'Expected <anything> (String) but was <12345> (Number)\n' +
' Expected <anything> (String) but was <12345> (Number)',
mockExpect.errorMessages[0]);
// plus the new error...
assertEquals('Expected: isString but was: <null>',
mockExpect.errorMessages[1]);
}
/**
* Utility method for checking for an ObjectEquals match failure. Checks that
* the expected error message was included in the error messages appended to
* the expectation object.
* @param {goog.testing.mockmatchers.ArgumentMatcher.ObjectEquals} matcher
* The matcher to test against.
* @param {Object} matchObject The object to compare.
* @param {string=} opt_errorMsg The deep object comparison failure message
* to check for.
*/
function expectObjectEqualsFailure(matcher, matchObject, opt_errorMsg) {
mockExpect.errorMessages = [];
assertFalse(matcher.matches(matchObject, mockExpect));
assertNotEquals(0, mockExpect.getErrorMessageCount());
if (opt_errorMsg) {
assertContains(opt_errorMsg, mockExpect.errorMessages[0]);
}
}