1 jasmine.Matchers = function(env, actual, results) { 2 this.env = env; 3 this.actual = actual; 4 this.passing_message = 'Passed.'; 5 this.results = results || new jasmine.NestedResults(); 6 }; 7 8 jasmine.Matchers.pp = function(str) { 9 return jasmine.util.htmlEscape(jasmine.pp(str)); 10 }; 11 12 jasmine.Matchers.prototype.getResults = function() { 13 return this.results; 14 }; 15 16 jasmine.Matchers.prototype.report = function(result, failing_message, details) { 17 this.results.addResult(new jasmine.ExpectationResult(result, result ? this.passing_message : failing_message, details)); 18 return result; 19 }; 20 21 /** 22 * Matcher that compares the actual to the expected using ===. 23 * 24 * @param expected 25 */ 26 jasmine.Matchers.prototype.toBe = function(expected) { 27 return this.report(this.actual === expected, 'Expected<br /><br />' + jasmine.Matchers.pp(expected) 28 + '<br /><br />to be the same object as<br /><br />' + jasmine.Matchers.pp(this.actual) 29 + '<br />'); 30 }; 31 32 /** 33 * Matcher that compares the actual to the expected using !== 34 * @param expected 35 */ 36 jasmine.Matchers.prototype.toNotBe = function(expected) { 37 return this.report(this.actual !== expected, 'Expected<br /><br />' + jasmine.Matchers.pp(expected) 38 + '<br /><br />to be a different object from actual, but they were the same.'); 39 }; 40 41 /** 42 * Matcher that compares the actual to the expected using common sense equality. Handles Objects, Arrays, etc. 43 * 44 * @param expected 45 */ 46 jasmine.Matchers.prototype.toEqual = function(expected) { 47 var mismatchKeys = []; 48 var mismatchValues = []; 49 50 var formatMismatches = function(name, array) { 51 if (array.length == 0) return ''; 52 var errorOutput = '<br /><br />Different ' + name + ':<br />'; 53 for (var i = 0; i < array.length; i++) { 54 errorOutput += array[i] + '<br />'; 55 } 56 return errorOutput; 57 }; 58 59 return this.report(this.env.equals_(this.actual, expected, mismatchKeys, mismatchValues), 60 'Expected<br /><br />' + jasmine.Matchers.pp(expected) 61 + '<br /><br />but got<br /><br />' + jasmine.Matchers.pp(this.actual) 62 + '<br />' 63 + formatMismatches('Keys', mismatchKeys) 64 + formatMismatches('Values', mismatchValues), { 65 matcherName: 'toEqual', expected: expected, actual: this.actual 66 }); 67 }; 68 /** @deprecated */ 69 jasmine.Matchers.prototype.should_equal = jasmine.Matchers.prototype.toEqual; 70 71 /** 72 * Matcher that compares the actual to the expected using the ! of jasmine.Matchers.toEqual 73 * @param expected 74 */ 75 jasmine.Matchers.prototype.toNotEqual = function(expected) { 76 return this.report(!this.env.equals_(this.actual, expected), 77 'Expected ' + jasmine.Matchers.pp(expected) + ' to not equal ' + jasmine.Matchers.pp(this.actual) + ', but it does.'); 78 }; 79 /** @deprecated */ 80 jasmine.Matchers.prototype.should_not_equal = jasmine.Matchers.prototype.toNotEqual; 81 82 /** 83 * Matcher that compares the actual to the expected using a regular expression. Constructs a RegExp, so takes 84 * a pattern or a String. 85 * 86 * @param reg_exp 87 */ 88 jasmine.Matchers.prototype.toMatch = function(reg_exp) { 89 return this.report((new RegExp(reg_exp).test(this.actual)), 90 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to match ' + reg_exp + '.'); 91 }; 92 /** @deprecated */ 93 jasmine.Matchers.prototype.should_match = jasmine.Matchers.prototype.toMatch; 94 95 /** 96 * Matcher that compares the actual to the expected using the boolean inverse of jasmine.Matchers.toMatch 97 * @param reg_exp 98 */ 99 jasmine.Matchers.prototype.toNotMatch = function(reg_exp) { 100 return this.report((!new RegExp(reg_exp).test(this.actual)), 101 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to not match ' + reg_exp + '.'); 102 }; 103 /** @deprecated */ 104 jasmine.Matchers.prototype.should_not_match = jasmine.Matchers.prototype.toNotMatch; 105 106 /** 107 * Matcher that compares the acutal to undefined. 108 */ 109 jasmine.Matchers.prototype.toBeDefined = function() { 110 return this.report((this.actual !== undefined), 111 'Expected a value to be defined but it was undefined.'); 112 }; 113 /** @deprecated */ 114 jasmine.Matchers.prototype.should_be_defined = jasmine.Matchers.prototype.toBeDefined; 115 116 /** 117 * Matcher that compares the actual to null. 118 * 119 */ 120 jasmine.Matchers.prototype.toBeNull = function() { 121 return this.report((this.actual === null), 122 'Expected a value to be null but it was ' + jasmine.Matchers.pp(this.actual) + '.'); 123 }; 124 /** @deprecated */ 125 jasmine.Matchers.prototype.should_be_null = jasmine.Matchers.prototype.toBeNull; 126 127 /** 128 * Matcher that boolean not-nots the actual. 129 */ 130 jasmine.Matchers.prototype.toBeTruthy = function() { 131 return this.report(!!this.actual, 132 'Expected a value to be truthy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); 133 }; 134 /** @deprecated */ 135 jasmine.Matchers.prototype.should_be_truthy = jasmine.Matchers.prototype.toBeTruthy; 136 137 /** 138 * Matcher that boolean nots the actual. 139 */ 140 jasmine.Matchers.prototype.toBeFalsy = function() { 141 return this.report(!this.actual, 142 'Expected a value to be falsy but it was ' + jasmine.Matchers.pp(this.actual) + '.'); 143 }; 144 /** @deprecated */ 145 jasmine.Matchers.prototype.should_be_falsy = jasmine.Matchers.prototype.toBeFalsy; 146 147 /** 148 * Matcher that checks to see if the acutal, a Jasmine spy, was called. 149 */ 150 jasmine.Matchers.prototype.wasCalled = function() { 151 if (!this.actual || !this.actual.isSpy) { 152 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); 153 } 154 if (arguments.length > 0) { 155 return this.report(false, 'wasCalled matcher does not take arguments'); 156 } 157 return this.report((this.actual.wasCalled), 158 'Expected spy "' + this.actual.identity + '" to have been called, but it was not.'); 159 }; 160 /** @deprecated */ 161 jasmine.Matchers.prototype.was_called = jasmine.Matchers.prototype.wasCalled; 162 163 /** 164 * Matcher that checks to see if the acutal, a Jasmine spy, was not called. 165 */ 166 jasmine.Matchers.prototype.wasNotCalled = function() { 167 if (!this.actual || !this.actual.isSpy) { 168 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.'); 169 } 170 return this.report((!this.actual.wasCalled), 171 'Expected spy "' + this.actual.identity + '" to not have been called, but it was.'); 172 }; 173 /** @deprecated */ 174 jasmine.Matchers.prototype.was_not_called = jasmine.Matchers.prototype.wasNotCalled; 175 176 /** 177 * Matcher that checks to see if the acutal, a Jasmine spy, was called with a set of parameters. 178 * 179 * @example 180 * 181 */ 182 jasmine.Matchers.prototype.wasCalledWith = function() { 183 if (!this.actual || !this.actual.isSpy) { 184 return this.report(false, 'Expected a spy, but got ' + jasmine.Matchers.pp(this.actual) + '.', { 185 matcherName: 'wasCalledWith' 186 }); 187 } 188 189 var args = jasmine.util.argsToArray(arguments); 190 191 return this.report(this.env.contains_(this.actual.argsForCall, args), 192 'Expected ' + jasmine.Matchers.pp(this.actual.argsForCall) + ' to contain ' + jasmine.Matchers.pp(args) + ', but it does not.', { 193 matcherName: 'wasCalledWith', expected: args, actual: this.actual.argsForCall 194 }); 195 }; 196 197 /** 198 * Matcher that checks that the expected item is an element in the actual Array. 199 * 200 * @param {Object} item 201 */ 202 jasmine.Matchers.prototype.toContain = function(item) { 203 return this.report(this.env.contains_(this.actual, item), 204 'Expected ' + jasmine.Matchers.pp(this.actual) + ' to contain ' + jasmine.Matchers.pp(item) + ', but it does not.', { 205 matcherName: 'toContain', expected: item, actual: this.actual 206 }); 207 }; 208 209 /** 210 * Matcher that checks that the expected item is NOT an element in the actual Array. 211 * 212 * @param {Object} item 213 */ 214 jasmine.Matchers.prototype.toNotContain = function(item) { 215 return this.report(!this.env.contains_(this.actual, item), 216 'Expected ' + jasmine.Matchers.pp(this.actual) + ' not to contain ' + jasmine.Matchers.pp(item) + ', but it does.'); 217 }; 218 219 /** 220 * Matcher that checks that the expected exception was thrown by the actual. 221 * 222 * @param {String} expectedException 223 */ 224 jasmine.Matchers.prototype.toThrow = function(expectedException) { 225 var exception = null; 226 try { 227 this.actual(); 228 } catch (e) { 229 exception = e; 230 } 231 if (expectedException !== undefined) { 232 if (exception == null) { 233 return this.report(false, "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it did not."); 234 } 235 return this.report( 236 this.env.equals_( 237 exception.message || exception, 238 expectedException.message || expectedException), 239 "Expected function to throw " + jasmine.Matchers.pp(expectedException) + ", but it threw " + jasmine.Matchers.pp(exception) + "."); 240 } else { 241 return this.report(exception != null, "Expected function to throw an exception, but it did not."); 242 } 243 }; 244 245 jasmine.Matchers.Any = function(expectedClass) { 246 this.expectedClass = expectedClass; 247 }; 248 249 jasmine.Matchers.Any.prototype.matches = function(other) { 250 if (this.expectedClass == String) { 251 return typeof other == 'string' || other instanceof String; 252 } 253 254 if (this.expectedClass == Number) { 255 return typeof other == 'number' || other instanceof Number; 256 } 257 258 if (this.expectedClass == Function) { 259 return typeof other == 'function' || other instanceof Function; 260 } 261 262 if (this.expectedClass == Object) { 263 return typeof other == 'object'; 264 } 265 266 return other instanceof this.expectedClass; 267 }; 268 269 jasmine.Matchers.Any.prototype.toString = function() { 270 return '<jasmine.any(' + this.expectedClass + ')>'; 271 }; 272 273