Commit | Line | Data |
---|---|---|
1a27bd14 RK |
1 | opyright 2009 Google Inc. |
2 | * | |
644eff8b RK |
3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
4 | * use this file except in compliance with the License. You may obtain a copy of | |
5 | * the License at | |
1a27bd14 | 6 | * |
644eff8b | 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
1a27bd14 | 8 | * |
644eff8b RK |
9 | * Unless required by applicable law or agreed to in writing, software |
10 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
11 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
12 | * License for the specific language governing permissions and limitations under | |
13 | * the License. | |
14 | */ | |
644eff8b RK |
15 | function expectAsserts(count) { |
16 | jstestdriver.expectedAssertCount = count; | |
17 | } | |
18 | ||
19 | ||
1a27bd14 | 20 | var fail = function fail(msg) { |
644eff8b RK |
21 | var err = new Error(msg); |
22 | err.name = 'AssertError'; | |
23 | ||
24 | if (!err.message) { | |
25 | err.message = msg; | |
26 | } | |
27 | ||
28 | throw err; | |
1a27bd14 | 29 | }; |
644eff8b RK |
30 | |
31 | ||
32 | function isBoolean_(bool) { | |
33 | if (typeof(bool) != 'boolean') { | |
1a27bd14 | 34 | fail('Not a boolean: ' + prettyPrintEntity_(bool)); |
644eff8b RK |
35 | } |
36 | } | |
37 | ||
1a27bd14 | 38 | |
644eff8b RK |
39 | var isElement_ = (function () { |
40 | var div = document.createElement('div'); | |
41 | ||
42 | function isNode(obj) { | |
43 | try { | |
44 | div.appendChild(obj); | |
45 | div.removeChild(obj); | |
46 | } catch (e) { | |
47 | return false; | |
48 | } | |
49 | ||
50 | return true; | |
51 | } | |
52 | ||
53 | return function isElement(obj) { | |
54 | return obj && obj.nodeType === 1 && isNode(obj); | |
55 | }; | |
56 | }()); | |
57 | ||
1a27bd14 | 58 | |
644eff8b RK |
59 | function formatElement_(el) { |
60 | var tagName; | |
61 | ||
62 | try { | |
63 | tagName = el.tagName.toLowerCase(); | |
1a27bd14 | 64 | var str = '<' + tagName; |
644eff8b RK |
65 | var attrs = el.attributes, attribute; |
66 | ||
67 | for (var i = 0, l = attrs.length; i < l; i++) { | |
68 | attribute = attrs.item(i); | |
69 | ||
70 | if (!!attribute.nodeValue) { | |
1a27bd14 | 71 | str += ' ' + attribute.nodeName + '=\"' + attribute.nodeValue + '\"'; |
644eff8b RK |
72 | } |
73 | } | |
74 | ||
1a27bd14 | 75 | return str + '>...</' + tagName + '>'; |
644eff8b | 76 | } catch (e) { |
1a27bd14 | 77 | return '[Element]' + (!!tagName ? ' ' + tagName : ''); |
644eff8b RK |
78 | } |
79 | } | |
80 | ||
1a27bd14 | 81 | |
644eff8b RK |
82 | function prettyPrintEntity_(entity) { |
83 | if (isElement_(entity)) { | |
84 | return formatElement_(entity); | |
85 | } | |
86 | ||
87 | var str; | |
88 | ||
1a27bd14 | 89 | if (typeof entity == 'function') { |
644eff8b RK |
90 | try { |
91 | str = entity.toString().match(/(function [^\(]+\(\))/)[1]; | |
92 | } catch (e) {} | |
93 | ||
1a27bd14 | 94 | return str || '[function]'; |
644eff8b RK |
95 | } |
96 | ||
97 | try { | |
1a27bd14 | 98 | str = JSON.stringify(entity); |
644eff8b RK |
99 | } catch (e) {} |
100 | ||
1a27bd14 | 101 | return str || '[' + typeof entity + ']'; |
644eff8b RK |
102 | } |
103 | ||
104 | ||
105 | function argsWithOptionalMsg_(args, length) { | |
106 | var copyOfArgs = []; | |
107 | // make copy because it's bad practice to change a passed in mutable | |
108 | // And to ensure we aren't working with an arguments array. IE gets bitchy. | |
109 | for(var i = 0; i < args.length; i++) { | |
110 | copyOfArgs.push(args[i]); | |
111 | } | |
112 | var min = length - 1; | |
113 | ||
114 | if (args.length < min) { | |
1a27bd14 | 115 | fail('expected at least ' + min + ' arguments, got ' + args.length); |
644eff8b | 116 | } else if (args.length == length) { |
1a27bd14 | 117 | copyOfArgs[0] += ' '; |
644eff8b | 118 | } else { |
1a27bd14 | 119 | copyOfArgs.unshift(''); |
644eff8b RK |
120 | } |
121 | return copyOfArgs; | |
122 | } | |
123 | ||
124 | ||
125 | function assertTrue(msg, actual) { | |
1a27bd14 | 126 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
127 | jstestdriver.assertCount++; |
128 | ||
129 | isBoolean_(args[1]); | |
130 | if (args[1] != true) { | |
1a27bd14 | 131 | fail(args[0] + 'expected true but was ' + prettyPrintEntity_(args[1])); |
644eff8b RK |
132 | } |
133 | return true; | |
1a27bd14 | 134 | } |
644eff8b RK |
135 | |
136 | ||
137 | function assertFalse(msg, actual) { | |
1a27bd14 | 138 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
139 | jstestdriver.assertCount++; |
140 | ||
141 | isBoolean_(args[1]); | |
142 | if (args[1] != false) { | |
1a27bd14 | 143 | fail(args[0] + 'expected false but was ' + prettyPrintEntity_(args[1])); |
644eff8b RK |
144 | } |
145 | return true; | |
1a27bd14 | 146 | } |
644eff8b RK |
147 | |
148 | ||
149 | function assertEquals(msg, expected, actual) { | |
1a27bd14 | 150 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
151 | jstestdriver.assertCount++; |
152 | msg = args[0]; | |
153 | expected = args[1]; | |
154 | actual = args[2]; | |
155 | ||
156 | if (!compare_(expected, actual)) { | |
1a27bd14 RK |
157 | fail(msg + 'expected ' + prettyPrintEntity_(expected) + ' but was ' + |
158 | prettyPrintEntity_(actual) + ''); | |
644eff8b RK |
159 | } |
160 | return true; | |
1a27bd14 | 161 | } |
644eff8b RK |
162 | |
163 | ||
164 | function compare_(expected, actual) { | |
165 | if (expected === actual) { | |
166 | return true; | |
167 | } | |
168 | ||
1a27bd14 RK |
169 | if (typeof expected != 'object' || |
170 | typeof actual != 'object' || | |
644eff8b RK |
171 | !expected || !actual) { |
172 | return expected == actual; | |
173 | } | |
174 | ||
175 | if (isElement_(expected) || isElement_(actual)) { | |
176 | return false; | |
177 | } | |
178 | ||
179 | var key = null; | |
180 | var actualLength = 0; | |
181 | var expectedLength = 0; | |
182 | ||
183 | try { | |
184 | // If an array is expected the length of actual should be simple to | |
185 | // determine. If it is not it is undefined. | |
186 | if (jstestdriver.jQuery.isArray(actual)) { | |
187 | actualLength = actual.length; | |
188 | } else { | |
189 | // In case it is an object it is a little bit more complicated to | |
190 | // get the length. | |
191 | for (key in actual) { | |
192 | if (actual.hasOwnProperty(key)) { | |
193 | ++actualLength; | |
194 | } | |
195 | } | |
196 | } | |
197 | ||
198 | // Arguments object | |
1a27bd14 | 199 | if (actualLength == 0 && typeof actual.length == 'number') { |
644eff8b RK |
200 | actualLength = actual.length; |
201 | ||
202 | for (var i = 0, l = actualLength; i < l; i++) { | |
203 | if (!(i in actual)) { | |
204 | actualLength = 0; | |
205 | break; | |
206 | } | |
207 | } | |
208 | } | |
209 | ||
210 | for (key in expected) { | |
211 | if (expected.hasOwnProperty(key)) { | |
212 | if (!compare_(expected[key], actual[key])) { | |
213 | return false; | |
214 | } | |
215 | ||
216 | ++expectedLength; | |
217 | } | |
218 | } | |
219 | ||
220 | if (expectedLength != actualLength) { | |
221 | return false; | |
222 | } | |
223 | ||
224 | return expectedLength == 0 ? expected.toString() == actual.toString() : true; | |
225 | } catch (e) { | |
226 | return false; | |
227 | } | |
1a27bd14 | 228 | } |
644eff8b RK |
229 | |
230 | ||
231 | function assertNotEquals(msg, expected, actual) { | |
232 | try { | |
233 | assertEquals.apply(this, arguments); | |
234 | } catch (e) { | |
1a27bd14 | 235 | if (e.name == 'AssertError') { |
644eff8b RK |
236 | return true; |
237 | } | |
238 | ||
239 | throw e; | |
240 | } | |
241 | ||
1a27bd14 | 242 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b | 243 | |
1a27bd14 RK |
244 | fail(args[0] + 'expected ' + prettyPrintEntity_(args[1]) + |
245 | ' not to be equal to ' + prettyPrintEntity_(args[2])); | |
644eff8b RK |
246 | } |
247 | ||
248 | ||
249 | function assertSame(msg, expected, actual) { | |
1a27bd14 | 250 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
251 | jstestdriver.assertCount++; |
252 | ||
253 | if (!isSame_(args[2], args[1])) { | |
1a27bd14 RK |
254 | fail(args[0] + 'expected ' + prettyPrintEntity_(args[1]) + ' but was ' + |
255 | prettyPrintEntity_(args[2])); | |
644eff8b RK |
256 | } |
257 | return true; | |
1a27bd14 | 258 | } |
644eff8b RK |
259 | |
260 | ||
261 | function assertNotSame(msg, expected, actual) { | |
1a27bd14 | 262 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
263 | jstestdriver.assertCount++; |
264 | ||
265 | if (isSame_(args[2], args[1])) { | |
1a27bd14 RK |
266 | fail(args[0] + 'expected not same as ' + prettyPrintEntity_(args[1]) + |
267 | ' but was ' + prettyPrintEntity_(args[2])); | |
644eff8b RK |
268 | } |
269 | return true; | |
1a27bd14 | 270 | } |
644eff8b RK |
271 | |
272 | ||
273 | function isSame_(expected, actual) { | |
274 | return actual === expected; | |
1a27bd14 | 275 | } |
644eff8b RK |
276 | |
277 | ||
278 | function assertNull(msg, actual) { | |
1a27bd14 | 279 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
280 | jstestdriver.assertCount++; |
281 | ||
282 | if (args[1] !== null) { | |
1a27bd14 | 283 | fail(args[0] + 'expected null but was ' + prettyPrintEntity_(args[1])); |
644eff8b RK |
284 | } |
285 | return true; | |
1a27bd14 | 286 | } |
644eff8b RK |
287 | |
288 | ||
289 | function assertNotNull(msg, actual) { | |
1a27bd14 | 290 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
291 | jstestdriver.assertCount++; |
292 | ||
293 | if (args[1] === null) { | |
1a27bd14 | 294 | fail(args[0] + 'expected not null but was null'); |
644eff8b RK |
295 | } |
296 | ||
297 | return true; | |
1a27bd14 | 298 | } |
644eff8b RK |
299 | |
300 | ||
301 | function assertUndefined(msg, actual) { | |
1a27bd14 | 302 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
303 | jstestdriver.assertCount++; |
304 | ||
1a27bd14 RK |
305 | if (typeof args[1] != 'undefined') { |
306 | fail(args[2] + 'expected undefined but was ' + prettyPrintEntity_(args[1])); | |
644eff8b RK |
307 | } |
308 | return true; | |
1a27bd14 | 309 | } |
644eff8b RK |
310 | |
311 | ||
312 | function assertNotUndefined(msg, actual) { | |
1a27bd14 | 313 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
314 | jstestdriver.assertCount++; |
315 | ||
1a27bd14 RK |
316 | if (typeof args[1] == 'undefined') { |
317 | fail(args[0] + 'expected not undefined but was undefined'); | |
644eff8b RK |
318 | } |
319 | return true; | |
1a27bd14 | 320 | } |
644eff8b RK |
321 | |
322 | ||
323 | function assertNaN(msg, actual) { | |
1a27bd14 | 324 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
325 | jstestdriver.assertCount++; |
326 | ||
327 | if (!isNaN(args[1])) { | |
1a27bd14 | 328 | fail(args[0] + 'expected to be NaN but was ' + args[1]); |
644eff8b RK |
329 | } |
330 | ||
331 | return true; | |
332 | } | |
333 | ||
334 | ||
335 | function assertNotNaN(msg, actual) { | |
1a27bd14 | 336 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
337 | jstestdriver.assertCount++; |
338 | ||
339 | if (isNaN(args[1])) { | |
1a27bd14 | 340 | fail(args[0] + 'expected not to be NaN'); |
644eff8b RK |
341 | } |
342 | ||
343 | return true; | |
344 | } | |
345 | ||
346 | ||
347 | function assertException(msg, callback, error) { | |
348 | if (arguments.length == 1) { | |
349 | // assertThrows(callback) | |
350 | callback = msg; | |
1a27bd14 | 351 | msg = ''; |
644eff8b | 352 | } else if (arguments.length == 2) { |
1a27bd14 | 353 | if (typeof callback != 'function') { |
644eff8b RK |
354 | // assertThrows(callback, type) |
355 | error = callback; | |
356 | callback = msg; | |
1a27bd14 | 357 | msg = ''; |
644eff8b RK |
358 | } else { |
359 | // assertThrows(msg, callback) | |
1a27bd14 | 360 | msg += ' '; |
644eff8b RK |
361 | } |
362 | } else { | |
363 | // assertThrows(msg, callback, type) | |
1a27bd14 | 364 | msg += ' '; |
644eff8b RK |
365 | } |
366 | ||
367 | jstestdriver.assertCount++; | |
368 | ||
369 | try { | |
370 | callback(); | |
371 | } catch(e) { | |
1a27bd14 | 372 | if (e.name == 'AssertError') { |
644eff8b RK |
373 | throw e; |
374 | } | |
375 | ||
376 | if (error && e.name != error) { | |
1a27bd14 | 377 | fail(msg + 'expected to throw ' + error + ' but threw ' + e.name); |
644eff8b RK |
378 | } |
379 | ||
380 | return true; | |
381 | } | |
382 | ||
1a27bd14 | 383 | fail(msg + 'expected to throw exception'); |
644eff8b RK |
384 | } |
385 | ||
386 | ||
387 | function assertNoException(msg, callback) { | |
1a27bd14 | 388 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
389 | jstestdriver.assertCount++; |
390 | ||
391 | try { | |
392 | args[1](); | |
393 | } catch(e) { | |
1a27bd14 RK |
394 | fail(args[0] + 'expected not to throw exception, but threw ' + e.name + |
395 | ' (' + e.message + ')'); | |
644eff8b RK |
396 | } |
397 | } | |
398 | ||
399 | ||
400 | function assertArray(msg, actual) { | |
1a27bd14 | 401 | var args = argsWithOptionalMsg_(arguments, 2); |
644eff8b RK |
402 | jstestdriver.assertCount++; |
403 | ||
404 | if (!jstestdriver.jQuery.isArray(args[1])) { | |
1a27bd14 RK |
405 | fail(args[0] + 'expected to be array, but was ' + |
406 | prettyPrintEntity_(args[1])); | |
644eff8b RK |
407 | } |
408 | } | |
409 | ||
410 | ||
411 | function assertTypeOf(msg, expected, value) { | |
1a27bd14 | 412 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
413 | jstestdriver.assertCount++; |
414 | var actual = typeof args[2]; | |
415 | ||
416 | if (actual != args[1]) { | |
1a27bd14 | 417 | fail(args[0] + 'expected to be ' + args[1] + ' but was ' + actual); |
644eff8b RK |
418 | } |
419 | ||
420 | return true; | |
421 | } | |
422 | ||
423 | ||
424 | function assertBoolean(msg, actual) { | |
1a27bd14 RK |
425 | var args = argsWithOptionalMsg_(arguments, 2); |
426 | return assertTypeOf(args[0], 'boolean', args[1]); | |
644eff8b RK |
427 | } |
428 | ||
429 | ||
430 | function assertFunction(msg, actual) { | |
1a27bd14 RK |
431 | var args = argsWithOptionalMsg_(arguments, 2); |
432 | return assertTypeOf(args[0], 'function', args[1]); | |
644eff8b RK |
433 | } |
434 | ||
435 | ||
436 | function assertObject(msg, actual) { | |
1a27bd14 RK |
437 | var args = argsWithOptionalMsg_(arguments, 2); |
438 | return assertTypeOf(args[0], 'object', args[1]); | |
644eff8b RK |
439 | } |
440 | ||
441 | ||
442 | function assertNumber(msg, actual) { | |
1a27bd14 RK |
443 | var args = argsWithOptionalMsg_(arguments, 2); |
444 | return assertTypeOf(args[0], 'number', args[1]); | |
644eff8b RK |
445 | } |
446 | ||
447 | ||
448 | function assertString(msg, actual) { | |
1a27bd14 RK |
449 | var args = argsWithOptionalMsg_(arguments, 2); |
450 | return assertTypeOf(args[0], 'string', args[1]); | |
644eff8b RK |
451 | } |
452 | ||
453 | ||
454 | function assertMatch(msg, regexp, actual) { | |
1a27bd14 RK |
455 | var args = argsWithOptionalMsg_(arguments, 3); |
456 | var isUndef = typeof args[2] == 'undefined'; | |
644eff8b RK |
457 | jstestdriver.assertCount++; |
458 | var _undef; | |
459 | ||
460 | if (isUndef || !args[1].test(args[2])) { | |
1a27bd14 RK |
461 | actual = (isUndef ? _undef : prettyPrintEntity_(args[2])); |
462 | fail(args[0] + 'expected ' + actual + ' to match ' + args[1]); | |
644eff8b RK |
463 | } |
464 | ||
465 | return true; | |
466 | } | |
467 | ||
468 | ||
469 | function assertNoMatch(msg, regexp, actual) { | |
1a27bd14 | 470 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
471 | jstestdriver.assertCount++; |
472 | ||
473 | if (args[1].test(args[2])) { | |
1a27bd14 RK |
474 | fail(args[0] + 'expected ' + prettyPrintEntity_(args[2]) + |
475 | ' not to match ' + args[1]); | |
644eff8b RK |
476 | } |
477 | ||
478 | return true; | |
479 | } | |
480 | ||
481 | ||
482 | function assertTagName(msg, tagName, element) { | |
1a27bd14 | 483 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
484 | var actual = args[2] && args[2].tagName; |
485 | ||
486 | if (String(actual).toUpperCase() != args[1].toUpperCase()) { | |
1a27bd14 | 487 | fail(args[0] + 'expected tagName to be ' + args[1] + ' but was ' + actual); |
644eff8b RK |
488 | } |
489 | return true; | |
490 | } | |
491 | ||
492 | ||
493 | function assertClassName(msg, className, element) { | |
1a27bd14 | 494 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b | 495 | var actual = args[2] && args[2].className; |
1a27bd14 | 496 | var regexp = new RegExp('(^|\\s)' + args[1] + '(\\s|$)'); |
644eff8b RK |
497 | |
498 | try { | |
1a27bd14 | 499 | assertMatch(args[0], regexp, actual); |
644eff8b | 500 | } catch (e) { |
1a27bd14 RK |
501 | actual = prettyPrintEntity_(actual); |
502 | fail(args[0] + 'expected class name to include ' + | |
503 | prettyPrintEntity_(args[1]) + ' but was ' + actual); | |
644eff8b RK |
504 | } |
505 | ||
506 | return true; | |
507 | } | |
508 | ||
509 | ||
510 | function assertElementId(msg, id, element) { | |
1a27bd14 | 511 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
512 | var actual = args[2] && args[2].id; |
513 | jstestdriver.assertCount++; | |
514 | ||
515 | if (actual !== args[1]) { | |
1a27bd14 | 516 | fail(args[0] + 'expected id to be ' + args[1] + ' but was ' + actual); |
644eff8b RK |
517 | } |
518 | ||
519 | return true; | |
520 | } | |
521 | ||
522 | ||
523 | function assertInstanceOf(msg, constructor, actual) { | |
524 | jstestdriver.assertCount++; | |
1a27bd14 RK |
525 | var args = argsWithOptionalMsg_(arguments, 3); |
526 | var pretty = prettyPrintEntity_(args[2]); | |
644eff8b RK |
527 | var expected = args[1] && args[1].name || args[1]; |
528 | ||
529 | if (args[2] == null) { | |
1a27bd14 | 530 | fail(args[0] + 'expected ' + pretty + ' to be instance of ' + expected); |
644eff8b RK |
531 | } |
532 | ||
533 | if (!(Object(args[2]) instanceof args[1])) { | |
1a27bd14 | 534 | fail(args[0] + 'expected ' + pretty + ' to be instance of ' + expected); |
644eff8b RK |
535 | } |
536 | ||
537 | return true; | |
538 | } | |
539 | ||
540 | ||
541 | function assertNotInstanceOf(msg, constructor, actual) { | |
1a27bd14 | 542 | var args = argsWithOptionalMsg_(arguments, 3); |
644eff8b RK |
543 | jstestdriver.assertCount++; |
544 | ||
545 | if (Object(args[2]) instanceof args[1]) { | |
546 | var expected = args[1] && args[1].name || args[1]; | |
1a27bd14 RK |
547 | var pretty = prettyPrintEntity_(args[2]); |
548 | fail(args[0] + 'expected ' + pretty + ' not to be instance of ' + expected); | |
644eff8b RK |
549 | } |
550 | ||
551 | return true; | |
552 | } | |
553 | ||
1a27bd14 RK |
554 | /** |
555 | * Asserts that two doubles, or the elements of two arrays of doubles, | |
556 | * are equal to within a positive delta. | |
557 | */ | |
558 | function assertEqualsDelta(msg, expected, actual, epsilon) { | |
559 | var args = this.argsWithOptionalMsg_(arguments, 4); | |
560 | jstestdriver.assertCount++; | |
561 | msg = args[0]; | |
562 | expected = args[1]; | |
563 | actual = args[2]; | |
564 | epsilon = args[3]; | |
565 | ||
566 | if (!compareDelta_(expected, actual, epsilon)) { | |
567 | this.fail(msg + 'expected ' + epsilon + ' within ' + | |
568 | this.prettyPrintEntity_(expected) + | |
569 | ' but was ' + this.prettyPrintEntity_(actual) + ''); | |
570 | } | |
571 | return true; | |
572 | }; | |
573 | ||
574 | function compareDelta_(expected, actual, epsilon) { | |
575 | var compareDouble = function(e,a,d) { | |
576 | return Math.abs(e - a) <= d; | |
577 | } | |
578 | if (expected === actual) { | |
579 | return true; | |
580 | } | |
581 | ||
582 | if (typeof expected == "number" || | |
583 | typeof actual == "number" || | |
584 | !expected || !actual) { | |
585 | return compareDouble(expected, actual, epsilon); | |
586 | } | |
587 | ||
588 | if (isElement_(expected) || isElement_(actual)) { | |
589 | return false; | |
590 | } | |
591 | ||
592 | var key = null; | |
593 | var actualLength = 0; | |
594 | var expectedLength = 0; | |
595 | ||
596 | try { | |
597 | // If an array is expected the length of actual should be simple to | |
598 | // determine. If it is not it is undefined. | |
599 | if (jstestdriver.jQuery.isArray(actual)) { | |
600 | actualLength = actual.length; | |
601 | } else { | |
602 | // In case it is an object it is a little bit more complicated to | |
603 | // get the length. | |
604 | for (key in actual) { | |
605 | if (actual.hasOwnProperty(key)) { | |
606 | ++actualLength; | |
607 | } | |
608 | } | |
609 | } | |
610 | ||
611 | // Arguments object | |
612 | if (actualLength == 0 && typeof actual.length == "number") { | |
613 | actualLength = actual.length; | |
614 | ||
615 | for (var i = 0, l = actualLength; i < l; i++) { | |
616 | if (!(i in actual)) { | |
617 | actualLength = 0; | |
618 | break; | |
619 | } | |
620 | } | |
621 | } | |
622 | ||
623 | for (key in expected) { | |
624 | if (expected.hasOwnProperty(key)) { | |
625 | if (!compareDelta_(expected[key], actual[key], epsilon)) { | |
626 | return false; | |
627 | } | |
628 | ||
629 | ++expectedLength; | |
630 | } | |
631 | } | |
632 | ||
633 | if (expectedLength != actualLength) { | |
634 | return false; | |
635 | } | |
636 | ||
637 | return expectedLength == 0 ? expected.toString() == actual.toString() : true; | |
638 | } catch (e) { | |
639 | return false; | |
640 | } | |
641 | }; | |
642 | ||
644eff8b | 643 | var assert = assertTrue; |