Commit | Line | Data |
---|---|---|
644eff8b RK |
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 | ||
17 | function expectAsserts(count) { | |
18 | jstestdriver.expectedAssertCount = count; | |
19 | } | |
20 | ||
21 | ||
22 | this.fail = function fail(msg) { | |
23 | var err = new Error(msg); | |
24 | err.name = 'AssertError'; | |
25 | ||
26 | if (!err.message) { | |
27 | err.message = msg; | |
28 | } | |
29 | ||
30 | throw err; | |
31 | } | |
32 | ||
33 | ||
34 | function isBoolean_(bool) { | |
35 | if (typeof(bool) != 'boolean') { | |
36 | this.fail('Not a boolean: ' + this.prettyPrintEntity_(bool)); | |
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 | 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 | function prettyPrintEntity_(entity) { | |
82 | if (isElement_(entity)) { | |
83 | return formatElement_(entity); | |
84 | } | |
85 | ||
86 | var str; | |
87 | ||
88 | if (typeof entity == "function") { | |
89 | try { | |
90 | str = entity.toString().match(/(function [^\(]+\(\))/)[1]; | |
91 | } catch (e) {} | |
92 | ||
93 | return str || "[function]"; | |
94 | } | |
95 | ||
96 | try { | |
97 | str = this.JSON.stringify(entity); | |
98 | } catch (e) {} | |
99 | ||
100 | return str || "[" + typeof entity + "]"; | |
101 | } | |
102 | ||
103 | ||
104 | function argsWithOptionalMsg_(args, length) { | |
105 | var copyOfArgs = []; | |
106 | // make copy because it's bad practice to change a passed in mutable | |
107 | // And to ensure we aren't working with an arguments array. IE gets bitchy. | |
108 | for(var i = 0; i < args.length; i++) { | |
109 | copyOfArgs.push(args[i]); | |
110 | } | |
111 | var min = length - 1; | |
112 | ||
113 | if (args.length < min) { | |
114 | this.fail("expected at least " + | |
115 | 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 = this.argsWithOptionalMsg_(arguments, 2); | |
127 | jstestdriver.assertCount++; | |
128 | ||
129 | isBoolean_(args[1]); | |
130 | if (args[1] != true) { | |
131 | this.fail(args[0] + 'expected true but was ' + | |
132 | this.prettyPrintEntity_(args[1])); | |
133 | } | |
134 | return true; | |
135 | }; | |
136 | ||
137 | ||
138 | function assertFalse(msg, actual) { | |
139 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
140 | jstestdriver.assertCount++; | |
141 | ||
142 | isBoolean_(args[1]); | |
143 | if (args[1] != false) { | |
144 | this.fail(args[0] + 'expected false but was ' + | |
145 | this.prettyPrintEntity_(args[1])); | |
146 | } | |
147 | return true; | |
148 | }; | |
149 | ||
150 | ||
151 | function assertEquals(msg, expected, actual) { | |
152 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
153 | jstestdriver.assertCount++; | |
154 | msg = args[0]; | |
155 | expected = args[1]; | |
156 | actual = args[2]; | |
157 | ||
158 | if (!compare_(expected, actual)) { | |
159 | this.fail(msg + 'expected ' + this.prettyPrintEntity_(expected) + | |
160 | ' but was ' + this.prettyPrintEntity_(actual) + ''); | |
161 | } | |
162 | return true; | |
163 | }; | |
164 | ||
165 | ||
166 | function compare_(expected, actual) { | |
167 | if (expected === actual) { | |
168 | return true; | |
169 | } | |
170 | ||
171 | if (typeof expected != "object" || | |
172 | typeof actual != "object" || | |
173 | !expected || !actual) { | |
174 | return expected == actual; | |
175 | } | |
176 | ||
177 | if (isElement_(expected) || isElement_(actual)) { | |
178 | return false; | |
179 | } | |
180 | ||
181 | var key = null; | |
182 | var actualLength = 0; | |
183 | var expectedLength = 0; | |
184 | ||
185 | try { | |
186 | // If an array is expected the length of actual should be simple to | |
187 | // determine. If it is not it is undefined. | |
188 | if (jstestdriver.jQuery.isArray(actual)) { | |
189 | actualLength = actual.length; | |
190 | } else { | |
191 | // In case it is an object it is a little bit more complicated to | |
192 | // get the length. | |
193 | for (key in actual) { | |
194 | if (actual.hasOwnProperty(key)) { | |
195 | ++actualLength; | |
196 | } | |
197 | } | |
198 | } | |
199 | ||
200 | // Arguments object | |
201 | if (actualLength == 0 && typeof actual.length == "number") { | |
202 | actualLength = actual.length; | |
203 | ||
204 | for (var i = 0, l = actualLength; i < l; i++) { | |
205 | if (!(i in actual)) { | |
206 | actualLength = 0; | |
207 | break; | |
208 | } | |
209 | } | |
210 | } | |
211 | ||
212 | for (key in expected) { | |
213 | if (expected.hasOwnProperty(key)) { | |
214 | if (!compare_(expected[key], actual[key])) { | |
215 | return false; | |
216 | } | |
217 | ||
218 | ++expectedLength; | |
219 | } | |
220 | } | |
221 | ||
222 | if (expectedLength != actualLength) { | |
223 | return false; | |
224 | } | |
225 | ||
226 | return expectedLength == 0 ? expected.toString() == actual.toString() : true; | |
227 | } catch (e) { | |
228 | return false; | |
229 | } | |
230 | }; | |
231 | ||
232 | ||
233 | function assertNotEquals(msg, expected, actual) { | |
234 | try { | |
235 | assertEquals.apply(this, arguments); | |
236 | } catch (e) { | |
237 | if (e.name == "AssertError") { | |
238 | return true; | |
239 | } | |
240 | ||
241 | throw e; | |
242 | } | |
243 | ||
244 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
245 | ||
246 | this.fail(args[0] + "expected " + this.prettyPrintEntity_(args[1]) + | |
247 | " not to be equal to " + this.prettyPrintEntity_(args[2])); | |
248 | } | |
249 | ||
250 | ||
251 | function assertSame(msg, expected, actual) { | |
252 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
253 | jstestdriver.assertCount++; | |
254 | ||
255 | if (!isSame_(args[2], args[1])) { | |
256 | this.fail(args[0] + 'expected ' + this.prettyPrintEntity_(args[1]) + | |
257 | ' but was ' + this.prettyPrintEntity_(args[2])); | |
258 | } | |
259 | return true; | |
260 | }; | |
261 | ||
262 | ||
263 | function assertNotSame(msg, expected, actual) { | |
264 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
265 | jstestdriver.assertCount++; | |
266 | ||
267 | if (isSame_(args[2], args[1])) { | |
268 | this.fail(args[0] + 'expected not same as ' + | |
269 | this.prettyPrintEntity_(args[1]) + ' but was ' + | |
270 | this.prettyPrintEntity_(args[2])); | |
271 | } | |
272 | return true; | |
273 | }; | |
274 | ||
275 | ||
276 | function isSame_(expected, actual) { | |
277 | return actual === expected; | |
278 | }; | |
279 | ||
280 | ||
281 | function assertNull(msg, actual) { | |
282 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
283 | jstestdriver.assertCount++; | |
284 | ||
285 | if (args[1] !== null) { | |
286 | this.fail(args[0] + 'expected null but was ' + | |
287 | this.prettyPrintEntity_(args[1])); | |
288 | } | |
289 | return true; | |
290 | }; | |
291 | ||
292 | ||
293 | function assertNotNull(msg, actual) { | |
294 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
295 | jstestdriver.assertCount++; | |
296 | ||
297 | if (args[1] === null) { | |
298 | this.fail(args[0] + "expected not null but was null"); | |
299 | } | |
300 | ||
301 | return true; | |
302 | }; | |
303 | ||
304 | ||
305 | function assertUndefined(msg, actual) { | |
306 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
307 | jstestdriver.assertCount++; | |
308 | ||
309 | if (typeof args[1] != "undefined") { | |
310 | this.fail(args[2] + "expected undefined but was " + | |
311 | this.prettyPrintEntity_(args[1])); | |
312 | } | |
313 | return true; | |
314 | }; | |
315 | ||
316 | ||
317 | function assertNotUndefined(msg, actual) { | |
318 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
319 | jstestdriver.assertCount++; | |
320 | ||
321 | if (typeof args[1] == "undefined") { | |
322 | this.fail(args[0] + 'expected not undefined but was undefined'); | |
323 | } | |
324 | return true; | |
325 | }; | |
326 | ||
327 | ||
328 | function assertNaN(msg, actual) { | |
329 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
330 | jstestdriver.assertCount++; | |
331 | ||
332 | if (!isNaN(args[1])) { | |
333 | this.fail(args[0] + "expected to be NaN but was " + args[1]); | |
334 | } | |
335 | ||
336 | return true; | |
337 | } | |
338 | ||
339 | ||
340 | function assertNotNaN(msg, actual) { | |
341 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
342 | jstestdriver.assertCount++; | |
343 | ||
344 | if (isNaN(args[1])) { | |
345 | this.fail(args[0] + "expected not to be NaN"); | |
346 | } | |
347 | ||
348 | return true; | |
349 | } | |
350 | ||
351 | ||
352 | function assertException(msg, callback, error) { | |
353 | if (arguments.length == 1) { | |
354 | // assertThrows(callback) | |
355 | callback = msg; | |
356 | msg = ""; | |
357 | } else if (arguments.length == 2) { | |
358 | if (typeof callback != "function") { | |
359 | // assertThrows(callback, type) | |
360 | error = callback; | |
361 | callback = msg; | |
362 | msg = ""; | |
363 | } else { | |
364 | // assertThrows(msg, callback) | |
365 | msg += " "; | |
366 | } | |
367 | } else { | |
368 | // assertThrows(msg, callback, type) | |
369 | msg += " "; | |
370 | } | |
371 | ||
372 | jstestdriver.assertCount++; | |
373 | ||
374 | try { | |
375 | callback(); | |
376 | } catch(e) { | |
377 | if (e.name == "AssertError") { | |
378 | throw e; | |
379 | } | |
380 | ||
381 | if (error && e.name != error) { | |
382 | this.fail(msg + "expected to throw " + | |
383 | error + " but threw " + e.name); | |
384 | } | |
385 | ||
386 | return true; | |
387 | } | |
388 | ||
389 | this.fail(msg + "expected to throw exception"); | |
390 | } | |
391 | ||
392 | ||
393 | function assertNoException(msg, callback) { | |
394 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
395 | jstestdriver.assertCount++; | |
396 | ||
397 | try { | |
398 | args[1](); | |
399 | } catch(e) { | |
400 | fail(args[0] + "expected not to throw exception, but threw " + | |
401 | e.name + " (" + e.message + ")"); | |
402 | } | |
403 | } | |
404 | ||
405 | ||
406 | function assertArray(msg, actual) { | |
407 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
408 | jstestdriver.assertCount++; | |
409 | ||
410 | if (!jstestdriver.jQuery.isArray(args[1])) { | |
411 | fail(args[0] + "expected to be array, but was " + | |
412 | this.prettyPrintEntity_(args[1])); | |
413 | } | |
414 | } | |
415 | ||
416 | ||
417 | function assertTypeOf(msg, expected, value) { | |
418 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
419 | jstestdriver.assertCount++; | |
420 | var actual = typeof args[2]; | |
421 | ||
422 | if (actual != args[1]) { | |
423 | this.fail(args[0] + "expected to be " + args[1] + " but was " + actual); | |
424 | } | |
425 | ||
426 | return true; | |
427 | } | |
428 | ||
429 | ||
430 | function assertBoolean(msg, actual) { | |
431 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
432 | return assertTypeOf(args[0], "boolean", args[1]); | |
433 | } | |
434 | ||
435 | ||
436 | function assertFunction(msg, actual) { | |
437 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
438 | return assertTypeOf(args[0], "function", args[1]); | |
439 | } | |
440 | ||
441 | ||
442 | function assertObject(msg, actual) { | |
443 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
444 | return assertTypeOf(args[0], "object", args[1]); | |
445 | } | |
446 | ||
447 | ||
448 | function assertNumber(msg, actual) { | |
449 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
450 | return assertTypeOf(args[0], "number", args[1]); | |
451 | } | |
452 | ||
453 | ||
454 | function assertString(msg, actual) { | |
455 | var args = this.argsWithOptionalMsg_(arguments, 2); | |
456 | return assertTypeOf(args[0], "string", args[1]); | |
457 | } | |
458 | ||
459 | ||
460 | function assertMatch(msg, regexp, actual) { | |
461 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
462 | var isUndef = typeof args[2] == "undefined"; | |
463 | jstestdriver.assertCount++; | |
464 | var _undef; | |
465 | ||
466 | if (isUndef || !args[1].test(args[2])) { | |
467 | actual = (isUndef ? _undef : this.prettyPrintEntity_(args[2])); | |
468 | this.fail(args[0] + "expected " + actual + " to match " + args[1]); | |
469 | } | |
470 | ||
471 | return true; | |
472 | } | |
473 | ||
474 | ||
475 | function assertNoMatch(msg, regexp, actual) { | |
476 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
477 | jstestdriver.assertCount++; | |
478 | ||
479 | if (args[1].test(args[2])) { | |
480 | this.fail(args[0] + "expected " + this.prettyPrintEntity_(args[2]) + | |
481 | " not to match " + args[1]); | |
482 | } | |
483 | ||
484 | return true; | |
485 | } | |
486 | ||
487 | ||
488 | function assertTagName(msg, tagName, element) { | |
489 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
490 | var actual = args[2] && args[2].tagName; | |
491 | ||
492 | if (String(actual).toUpperCase() != args[1].toUpperCase()) { | |
493 | this.fail(args[0] + "expected tagName to be " + args[1] + " but was " + | |
494 | actual); | |
495 | } | |
496 | return true; | |
497 | } | |
498 | ||
499 | ||
500 | function assertClassName(msg, className, element) { | |
501 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
502 | var actual = args[2] && args[2].className; | |
503 | var regexp = new RegExp("(^|\\s)" + args[1] + "(\\s|$)"); | |
504 | ||
505 | try { | |
506 | this.assertMatch(args[0], regexp, actual); | |
507 | } catch (e) { | |
508 | actual = this.prettyPrintEntity_(actual); | |
509 | this.fail(args[0] + "expected class name to include " + | |
510 | this.prettyPrintEntity_(args[1]) + " but was " + actual); | |
511 | } | |
512 | ||
513 | return true; | |
514 | } | |
515 | ||
516 | ||
517 | function assertElementId(msg, id, element) { | |
518 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
519 | var actual = args[2] && args[2].id; | |
520 | jstestdriver.assertCount++; | |
521 | ||
522 | if (actual !== args[1]) { | |
523 | this.fail(args[0] + "expected id to be " + args[1] + " but was " + | |
524 | actual); | |
525 | } | |
526 | ||
527 | return true; | |
528 | } | |
529 | ||
530 | ||
531 | function assertInstanceOf(msg, constructor, actual) { | |
532 | jstestdriver.assertCount++; | |
533 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
534 | var pretty = this.prettyPrintEntity_(args[2]); | |
535 | var expected = args[1] && args[1].name || args[1]; | |
536 | ||
537 | if (args[2] == null) { | |
538 | this.fail(args[0] + "expected " + pretty + " to be instance of " + | |
539 | expected); | |
540 | } | |
541 | ||
542 | if (!(Object(args[2]) instanceof args[1])) { | |
543 | this.fail(args[0] + "expected " + pretty + " to be instance of " + | |
544 | expected); | |
545 | } | |
546 | ||
547 | return true; | |
548 | } | |
549 | ||
550 | ||
551 | function assertNotInstanceOf(msg, constructor, actual) { | |
552 | var args = this.argsWithOptionalMsg_(arguments, 3); | |
553 | jstestdriver.assertCount++; | |
554 | ||
555 | if (Object(args[2]) instanceof args[1]) { | |
556 | var expected = args[1] && args[1].name || args[1]; | |
557 | var pretty = this.prettyPrintEntity_(args[2]); | |
558 | this.fail(args[0] + "expected " + pretty + " not to be instance of " + | |
559 | expected); | |
560 | } | |
561 | ||
562 | return true; | |
563 | } | |
564 | ||
565 | var assert = assertTrue; |