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