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