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