| // 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]); |
| } |
| } |