Move to JSTD133
[dygraphs.git] / auto_tests / lib / Asserts.js
CommitLineData
1a27bd14
RK
1opyright 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
15function expectAsserts(count) {
16 jstestdriver.expectedAssertCount = count;
17}
18
19
1a27bd14 20var 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
32function isBoolean_(bool) {
33 if (typeof(bool) != 'boolean') {
1a27bd14 34 fail('Not a boolean: ' + prettyPrintEntity_(bool));
644eff8b
RK
35 }
36}
37
1a27bd14 38
644eff8b
RK
39var 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
59function 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
82function 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
105function 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
125function 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
137function 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
149function 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
164function 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
231function 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
249function 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
261function 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
273function isSame_(expected, actual) {
274 return actual === expected;
1a27bd14 275}
644eff8b
RK
276
277
278function 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
289function 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
301function 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
312function 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
323function 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
335function 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
347function 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
387function 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
400function 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
411function 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
424function assertBoolean(msg, actual) {
1a27bd14
RK
425 var args = argsWithOptionalMsg_(arguments, 2);
426 return assertTypeOf(args[0], 'boolean', args[1]);
644eff8b
RK
427}
428
429
430function assertFunction(msg, actual) {
1a27bd14
RK
431 var args = argsWithOptionalMsg_(arguments, 2);
432 return assertTypeOf(args[0], 'function', args[1]);
644eff8b
RK
433}
434
435
436function assertObject(msg, actual) {
1a27bd14
RK
437 var args = argsWithOptionalMsg_(arguments, 2);
438 return assertTypeOf(args[0], 'object', args[1]);
644eff8b
RK
439}
440
441
442function assertNumber(msg, actual) {
1a27bd14
RK
443 var args = argsWithOptionalMsg_(arguments, 2);
444 return assertTypeOf(args[0], 'number', args[1]);
644eff8b
RK
445}
446
447
448function assertString(msg, actual) {
1a27bd14
RK
449 var args = argsWithOptionalMsg_(arguments, 2);
450 return assertTypeOf(args[0], 'string', args[1]);
644eff8b
RK
451}
452
453
454function 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
469function 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
482function 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
493function 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
510function 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
523function 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
541function 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 */
558function 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
574function 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 643var assert = assertTrue;