Move to JSTD133
[dygraphs.git] / auto_tests / lib / Asserts.js
1 opyright 2009 Google Inc.
2 *
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
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
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 */
15 function expectAsserts(count) {
16 jstestdriver.expectedAssertCount = count;
17 }
18
19
20 var fail = function fail(msg) {
21 var err = new Error(msg);
22 err.name = 'AssertError';
23
24 if (!err.message) {
25 err.message = msg;
26 }
27
28 throw err;
29 };
30
31
32 function isBoolean_(bool) {
33 if (typeof(bool) != 'boolean') {
34 fail('Not a boolean: ' + prettyPrintEntity_(bool));
35 }
36 }
37
38
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
58
59 function formatElement_(el) {
60 var tagName;
61
62 try {
63 tagName = el.tagName.toLowerCase();
64 var str = '<' + tagName;
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) {
71 str += ' ' + attribute.nodeName + '=\"' + attribute.nodeValue + '\"';
72 }
73 }
74
75 return str + '>...</' + tagName + '>';
76 } catch (e) {
77 return '[Element]' + (!!tagName ? ' ' + tagName : '');
78 }
79 }
80
81
82 function prettyPrintEntity_(entity) {
83 if (isElement_(entity)) {
84 return formatElement_(entity);
85 }
86
87 var str;
88
89 if (typeof entity == 'function') {
90 try {
91 str = entity.toString().match(/(function [^\(]+\(\))/)[1];
92 } catch (e) {}
93
94 return str || '[function]';
95 }
96
97 try {
98 str = JSON.stringify(entity);
99 } catch (e) {}
100
101 return str || '[' + typeof entity + ']';
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) {
115 fail('expected at least ' + min + ' arguments, got ' + args.length);
116 } else if (args.length == length) {
117 copyOfArgs[0] += ' ';
118 } else {
119 copyOfArgs.unshift('');
120 }
121 return copyOfArgs;
122 }
123
124
125 function assertTrue(msg, actual) {
126 var args = argsWithOptionalMsg_(arguments, 2);
127 jstestdriver.assertCount++;
128
129 isBoolean_(args[1]);
130 if (args[1] != true) {
131 fail(args[0] + 'expected true but was ' + prettyPrintEntity_(args[1]));
132 }
133 return true;
134 }
135
136
137 function assertFalse(msg, actual) {
138 var args = argsWithOptionalMsg_(arguments, 2);
139 jstestdriver.assertCount++;
140
141 isBoolean_(args[1]);
142 if (args[1] != false) {
143 fail(args[0] + 'expected false but was ' + prettyPrintEntity_(args[1]));
144 }
145 return true;
146 }
147
148
149 function assertEquals(msg, expected, actual) {
150 var args = argsWithOptionalMsg_(arguments, 3);
151 jstestdriver.assertCount++;
152 msg = args[0];
153 expected = args[1];
154 actual = args[2];
155
156 if (!compare_(expected, actual)) {
157 fail(msg + 'expected ' + prettyPrintEntity_(expected) + ' but was ' +
158 prettyPrintEntity_(actual) + '');
159 }
160 return true;
161 }
162
163
164 function compare_(expected, actual) {
165 if (expected === actual) {
166 return true;
167 }
168
169 if (typeof expected != 'object' ||
170 typeof actual != 'object' ||
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
199 if (actualLength == 0 && typeof actual.length == 'number') {
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 }
228 }
229
230
231 function assertNotEquals(msg, expected, actual) {
232 try {
233 assertEquals.apply(this, arguments);
234 } catch (e) {
235 if (e.name == 'AssertError') {
236 return true;
237 }
238
239 throw e;
240 }
241
242 var args = argsWithOptionalMsg_(arguments, 3);
243
244 fail(args[0] + 'expected ' + prettyPrintEntity_(args[1]) +
245 ' not to be equal to ' + prettyPrintEntity_(args[2]));
246 }
247
248
249 function assertSame(msg, expected, actual) {
250 var args = argsWithOptionalMsg_(arguments, 3);
251 jstestdriver.assertCount++;
252
253 if (!isSame_(args[2], args[1])) {
254 fail(args[0] + 'expected ' + prettyPrintEntity_(args[1]) + ' but was ' +
255 prettyPrintEntity_(args[2]));
256 }
257 return true;
258 }
259
260
261 function assertNotSame(msg, expected, actual) {
262 var args = argsWithOptionalMsg_(arguments, 3);
263 jstestdriver.assertCount++;
264
265 if (isSame_(args[2], args[1])) {
266 fail(args[0] + 'expected not same as ' + prettyPrintEntity_(args[1]) +
267 ' but was ' + prettyPrintEntity_(args[2]));
268 }
269 return true;
270 }
271
272
273 function isSame_(expected, actual) {
274 return actual === expected;
275 }
276
277
278 function assertNull(msg, actual) {
279 var args = argsWithOptionalMsg_(arguments, 2);
280 jstestdriver.assertCount++;
281
282 if (args[1] !== null) {
283 fail(args[0] + 'expected null but was ' + prettyPrintEntity_(args[1]));
284 }
285 return true;
286 }
287
288
289 function assertNotNull(msg, actual) {
290 var args = argsWithOptionalMsg_(arguments, 2);
291 jstestdriver.assertCount++;
292
293 if (args[1] === null) {
294 fail(args[0] + 'expected not null but was null');
295 }
296
297 return true;
298 }
299
300
301 function assertUndefined(msg, actual) {
302 var args = argsWithOptionalMsg_(arguments, 2);
303 jstestdriver.assertCount++;
304
305 if (typeof args[1] != 'undefined') {
306 fail(args[2] + 'expected undefined but was ' + prettyPrintEntity_(args[1]));
307 }
308 return true;
309 }
310
311
312 function assertNotUndefined(msg, actual) {
313 var args = argsWithOptionalMsg_(arguments, 2);
314 jstestdriver.assertCount++;
315
316 if (typeof args[1] == 'undefined') {
317 fail(args[0] + 'expected not undefined but was undefined');
318 }
319 return true;
320 }
321
322
323 function assertNaN(msg, actual) {
324 var args = argsWithOptionalMsg_(arguments, 2);
325 jstestdriver.assertCount++;
326
327 if (!isNaN(args[1])) {
328 fail(args[0] + 'expected to be NaN but was ' + args[1]);
329 }
330
331 return true;
332 }
333
334
335 function assertNotNaN(msg, actual) {
336 var args = argsWithOptionalMsg_(arguments, 2);
337 jstestdriver.assertCount++;
338
339 if (isNaN(args[1])) {
340 fail(args[0] + 'expected not to be NaN');
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;
351 msg = '';
352 } else if (arguments.length == 2) {
353 if (typeof callback != 'function') {
354 // assertThrows(callback, type)
355 error = callback;
356 callback = msg;
357 msg = '';
358 } else {
359 // assertThrows(msg, callback)
360 msg += ' ';
361 }
362 } else {
363 // assertThrows(msg, callback, type)
364 msg += ' ';
365 }
366
367 jstestdriver.assertCount++;
368
369 try {
370 callback();
371 } catch(e) {
372 if (e.name == 'AssertError') {
373 throw e;
374 }
375
376 if (error && e.name != error) {
377 fail(msg + 'expected to throw ' + error + ' but threw ' + e.name);
378 }
379
380 return true;
381 }
382
383 fail(msg + 'expected to throw exception');
384 }
385
386
387 function assertNoException(msg, callback) {
388 var args = argsWithOptionalMsg_(arguments, 2);
389 jstestdriver.assertCount++;
390
391 try {
392 args[1]();
393 } catch(e) {
394 fail(args[0] + 'expected not to throw exception, but threw ' + e.name +
395 ' (' + e.message + ')');
396 }
397 }
398
399
400 function assertArray(msg, actual) {
401 var args = argsWithOptionalMsg_(arguments, 2);
402 jstestdriver.assertCount++;
403
404 if (!jstestdriver.jQuery.isArray(args[1])) {
405 fail(args[0] + 'expected to be array, but was ' +
406 prettyPrintEntity_(args[1]));
407 }
408 }
409
410
411 function assertTypeOf(msg, expected, value) {
412 var args = argsWithOptionalMsg_(arguments, 3);
413 jstestdriver.assertCount++;
414 var actual = typeof args[2];
415
416 if (actual != args[1]) {
417 fail(args[0] + 'expected to be ' + args[1] + ' but was ' + actual);
418 }
419
420 return true;
421 }
422
423
424 function assertBoolean(msg, actual) {
425 var args = argsWithOptionalMsg_(arguments, 2);
426 return assertTypeOf(args[0], 'boolean', args[1]);
427 }
428
429
430 function assertFunction(msg, actual) {
431 var args = argsWithOptionalMsg_(arguments, 2);
432 return assertTypeOf(args[0], 'function', args[1]);
433 }
434
435
436 function assertObject(msg, actual) {
437 var args = argsWithOptionalMsg_(arguments, 2);
438 return assertTypeOf(args[0], 'object', args[1]);
439 }
440
441
442 function assertNumber(msg, actual) {
443 var args = argsWithOptionalMsg_(arguments, 2);
444 return assertTypeOf(args[0], 'number', args[1]);
445 }
446
447
448 function assertString(msg, actual) {
449 var args = argsWithOptionalMsg_(arguments, 2);
450 return assertTypeOf(args[0], 'string', args[1]);
451 }
452
453
454 function assertMatch(msg, regexp, actual) {
455 var args = argsWithOptionalMsg_(arguments, 3);
456 var isUndef = typeof args[2] == 'undefined';
457 jstestdriver.assertCount++;
458 var _undef;
459
460 if (isUndef || !args[1].test(args[2])) {
461 actual = (isUndef ? _undef : prettyPrintEntity_(args[2]));
462 fail(args[0] + 'expected ' + actual + ' to match ' + args[1]);
463 }
464
465 return true;
466 }
467
468
469 function assertNoMatch(msg, regexp, actual) {
470 var args = argsWithOptionalMsg_(arguments, 3);
471 jstestdriver.assertCount++;
472
473 if (args[1].test(args[2])) {
474 fail(args[0] + 'expected ' + prettyPrintEntity_(args[2]) +
475 ' not to match ' + args[1]);
476 }
477
478 return true;
479 }
480
481
482 function assertTagName(msg, tagName, element) {
483 var args = argsWithOptionalMsg_(arguments, 3);
484 var actual = args[2] && args[2].tagName;
485
486 if (String(actual).toUpperCase() != args[1].toUpperCase()) {
487 fail(args[0] + 'expected tagName to be ' + args[1] + ' but was ' + actual);
488 }
489 return true;
490 }
491
492
493 function assertClassName(msg, className, element) {
494 var args = argsWithOptionalMsg_(arguments, 3);
495 var actual = args[2] && args[2].className;
496 var regexp = new RegExp('(^|\\s)' + args[1] + '(\\s|$)');
497
498 try {
499 assertMatch(args[0], regexp, actual);
500 } catch (e) {
501 actual = prettyPrintEntity_(actual);
502 fail(args[0] + 'expected class name to include ' +
503 prettyPrintEntity_(args[1]) + ' but was ' + actual);
504 }
505
506 return true;
507 }
508
509
510 function assertElementId(msg, id, element) {
511 var args = argsWithOptionalMsg_(arguments, 3);
512 var actual = args[2] && args[2].id;
513 jstestdriver.assertCount++;
514
515 if (actual !== args[1]) {
516 fail(args[0] + 'expected id to be ' + args[1] + ' but was ' + actual);
517 }
518
519 return true;
520 }
521
522
523 function assertInstanceOf(msg, constructor, actual) {
524 jstestdriver.assertCount++;
525 var args = argsWithOptionalMsg_(arguments, 3);
526 var pretty = prettyPrintEntity_(args[2]);
527 var expected = args[1] && args[1].name || args[1];
528
529 if (args[2] == null) {
530 fail(args[0] + 'expected ' + pretty + ' to be instance of ' + expected);
531 }
532
533 if (!(Object(args[2]) instanceof args[1])) {
534 fail(args[0] + 'expected ' + pretty + ' to be instance of ' + expected);
535 }
536
537 return true;
538 }
539
540
541 function assertNotInstanceOf(msg, constructor, actual) {
542 var args = argsWithOptionalMsg_(arguments, 3);
543 jstestdriver.assertCount++;
544
545 if (Object(args[2]) instanceof args[1]) {
546 var expected = args[1] && args[1].name || args[1];
547 var pretty = prettyPrintEntity_(args[2]);
548 fail(args[0] + 'expected ' + pretty + ' not to be instance of ' + expected);
549 }
550
551 return true;
552 }
553
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
643 var assert = assertTrue;