Merge pull request #303 from danvk/fix-hidpi
[dygraphs.git] / auto_tests / lib / Asserts.js
CommitLineData
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
16function expectAsserts(count) {
17 jstestdriver.expectedAssertCount = count;
18}
19
20
1a27bd14 21var 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
33function isBoolean_(bool) {
34 if (typeof(bool) != 'boolean') {
1a27bd14 35 fail('Not a boolean: ' + prettyPrintEntity_(bool));
644eff8b
RK
36 }
37}
38
1a27bd14 39
644eff8b
RK
40var 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
60function 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
83function 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
106function 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
126function 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
138function 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
150function 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
165function 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
232function 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
250function 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
262function 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
274function isSame_(expected, actual) {
275 return actual === expected;
1a27bd14 276}
644eff8b
RK
277
278
279function 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
290function 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
302function 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
313function 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
324function 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
336function 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
348function 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
388function 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
401function 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
412function 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
425function assertBoolean(msg, actual) {
1a27bd14
RK
426 var args = argsWithOptionalMsg_(arguments, 2);
427 return assertTypeOf(args[0], 'boolean', args[1]);
644eff8b
RK
428}
429
430
431function assertFunction(msg, actual) {
1a27bd14
RK
432 var args = argsWithOptionalMsg_(arguments, 2);
433 return assertTypeOf(args[0], 'function', args[1]);
644eff8b
RK
434}
435
436
437function assertObject(msg, actual) {
1a27bd14
RK
438 var args = argsWithOptionalMsg_(arguments, 2);
439 return assertTypeOf(args[0], 'object', args[1]);
644eff8b
RK
440}
441
442
443function assertNumber(msg, actual) {
1a27bd14
RK
444 var args = argsWithOptionalMsg_(arguments, 2);
445 return assertTypeOf(args[0], 'number', args[1]);
644eff8b
RK
446}
447
448
449function assertString(msg, actual) {
1a27bd14
RK
450 var args = argsWithOptionalMsg_(arguments, 2);
451 return assertTypeOf(args[0], 'string', args[1]);
644eff8b
RK
452}
453
454
455function 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
470function 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
483function 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
494function 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
511function 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
524function 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
542function 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 */
559function 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
575function 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 644var assert = assertTrue;