1 test("module without setup/teardown (default)", function() {
6 test("expect in test", 3, function() {
12 test("expect in test", 1, function() {
16 test("expect query and multiple issue", function() {
19 var expected = expect();
25 QUnit.module("assertion helpers");
27 QUnit.test( "QUnit.assert compatibility", function( assert ) {
30 assert.ok( true, "Calling method on `assert` argument to test() callback" );
32 // Should also work, although not documented
33 QUnit.assert.ok( true, "Calling method on QUnit.assert object" );
35 // Test compatibility aliases
36 QUnit.ok( true, "Calling aliased method in QUnit root object" );
37 ok( true, "Calling aliased function in global namespace" );
40 module("setup test", {
46 test("module with setup", function() {
51 test("module with setup, expect in test call", 2, function() {
57 module("setup/teardown test", {
63 teardown: function() {
65 // can introduce and delete globals in setup/teardown
66 // without noglobals sounding the alarm
71 test("module with setup/teardown", function() {
76 module("setup/teardown test 2");
78 test("module without setup/teardown", function() {
91 ok( false, 'QUnit should internally be independant from Date-related manipulation and testing' );
95 teardown: function() {
100 test("sample test for Date test", function () {
105 if (typeof setTimeout !== 'undefined') {
108 module("teardown and stop", {
109 teardown: function() {
110 equal(state, "done", "Test teardown.");
114 test("teardown must be called after test ended", function() {
117 setTimeout(function() {
123 test("parameter passed to stop increments semaphore n times", function() {
126 setTimeout(function() {
127 state = "not enough starts";
130 setTimeout(function() {
136 test("parameter passed to start decrements semaphore n times", function() {
138 stop(), stop(), stop();
139 setTimeout(function() {
145 module("async setup test", {
148 setTimeout(function() {
155 asyncTest("module with async setup", function() {
161 module("async teardown test", {
162 teardown: function() {
164 setTimeout(function() {
171 asyncTest("module with async teardown", function() {
179 asyncTest("asyncTest", function() {
182 setTimeout(function() {
189 asyncTest("asyncTest", 2, function() {
191 setTimeout(function() {
198 test("sync", 2, function() {
200 setTimeout(function() {
205 setTimeout(function() {
211 test("test synchronous calls to stop", 2, function() {
213 setTimeout(function() {
217 setTimeout(function() {
225 module("save scope", {
229 teardown: function() {
230 deepEqual(this.foo, "bar");
233 test("scope check", function() {
235 deepEqual(this.foo, "bar");
238 module("simple testEnvironment setup", {
240 // example of meta-data
243 test("scope check", function() {
244 deepEqual(this.foo, "bar");
246 test("modify testEnvironment",function() {
250 test("testEnvironment reset for next test",function() {
251 deepEqual(this.foo, "bar");
254 module("testEnvironment with object", {
257 ingredients:["hamster","onions"]
260 test("scope check", function() {
261 deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions"]}) ;
263 test("modify testEnvironment",function() {
265 // since we do a shallow copy, the testEnvironment can be modified
266 this.options.ingredients.push("carrots");
268 test("testEnvironment reset for next test",function() {
269 deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions","carrots"]}, "Is this a bug or a feature? Could do a deep copy") ;
273 module("testEnvironment tests");
276 var testEnv = QUnit.current_testEnvironment;
277 var url = testEnv.url || 'http://example.com/search';
278 var q = testEnv.q || 'a search test';
279 return url + '?q='+encodeURIComponent(q);
282 test("makeurl working",function() {
283 equal( QUnit.current_testEnvironment, this, 'The current testEnvironment is global');
284 equal( makeurl(), 'http://example.com/search?q=a%20search%20test', 'makeurl returns a default url if nothing specified in the testEnvironment');
287 module("testEnvironment with makeurl settings", {
288 url: 'http://google.com/',
289 q: 'another_search_test'
291 test("makeurl working with settings from testEnvironment", function() {
292 equal( makeurl(), 'http://google.com/?q=another_search_test', 'rather than passing arguments, we use test metadata to from the url');
296 test("jsDump output", function() {
297 equal( QUnit.jsDump.parse([1, 2]), "[\n 1,\n 2\n]" );
298 equal( QUnit.jsDump.parse({top: 5, left: 0}), "{\n \"left\": 0,\n \"top\": 5\n}" );
299 if (typeof document !== 'undefined' && document.getElementById("qunit-header")) {
300 equal( QUnit.jsDump.parse(document.getElementById("qunit-header")), "<h1 id=\"qunit-header\"></h1>" );
301 equal( QUnit.jsDump.parse(document.getElementsByTagName("h1")), "[\n <h1 id=\"qunit-header\"></h1>\n]" );
305 module("assertions");
306 test("raises",function() {
307 function CustomError( message ) {
308 this.message = message;
311 CustomError.prototype.toString = function() {
325 "simple string throw, no 'expected' value given"
330 throw new CustomError();
333 'thrown error is an instance of CustomError'
338 throw new CustomError("some error description");
341 "use a regex to match against the stringified error"
346 throw new CustomError("some error description");
349 if ( (err instanceof CustomError) && /description/.test(err) ) {
353 "custom validation function"
358 /*jshint evil:true */
359 ( window.execScript || function( data ) {
360 window["eval"].call( window, data );
361 })( "throw 'error';" );
363 'globally-executed errors caught'
366 this.CustomError = CustomError;
370 throw new this.CustomError("some error description");
373 "throw error from property of 'this' context"
380 "simple throw, asserting with deprecated raises() function"
385 if (typeof document !== "undefined") {
388 test("setup", function() {
390 document.getElementById("qunit-fixture").innerHTML = "foobar";
392 test("basics", function() {
393 equal( document.getElementById("qunit-fixture").innerHTML, "test markup", "automatically reset" );
396 test("running test name displayed", function() {
399 var displaying = document.getElementById("qunit-testresult");
401 ok( /running test name displayed/.test(displaying.innerHTML), "Expect test name to be found in displayed text" );
402 ok( /fixture/.test(displaying.innerHTML), "Expect module name to be found in displayed text" );
407 module("custom assertions");
409 function mod2(value, expected, message) {
410 var actual = value % 2;
411 QUnit.push(actual == expected, actual, expected, message);
413 test("mod2", function() {
414 mod2(2, 0, "2 % 2 == 0");
415 mod2(3, 1, "3 % 2 == 1");
420 module("recursions");
424 if (x === undefined) {
429 function chainwrap(depth, first, prev) {
431 var last = prev || new Wrap();
432 first = first || last;
438 last = chainwrap(depth-1, first, new Wrap(last));
444 test("check jsDump recursion", function() {
447 var noref = chainwrap(0);
448 var nodump = QUnit.jsDump.parse(noref);
449 equal(nodump, '{\n "first": true,\n "wrap": undefined\n}');
451 var selfref = chainwrap(1);
452 var selfdump = QUnit.jsDump.parse(selfref);
453 equal(selfdump, '{\n "first": true,\n "wrap": recursion(-1)\n}');
455 var parentref = chainwrap(2);
456 var parentdump = QUnit.jsDump.parse(parentref);
457 equal(parentdump, '{\n "wrap": {\n "first": true,\n "wrap": recursion(-2)\n }\n}');
459 var circref = chainwrap(10);
460 var circdump = QUnit.jsDump.parse(circref);
461 ok(new RegExp("recursion\\(-10\\)").test(circdump), "(" +circdump + ") should show -10 recursion level");
464 test("check (deep-)equal recursion", function() {
465 var noRecursion = chainwrap(0);
466 equal(noRecursion, noRecursion, "I should be equal to me.");
467 deepEqual(noRecursion, noRecursion, "... and so in depth.");
469 var selfref = chainwrap(1);
470 equal(selfref, selfref, "Even so if I nest myself.");
471 deepEqual(selfref, selfref, "... into the depth.");
473 var circref = chainwrap(10);
474 equal(circref, circref, "Or hide that through some levels of indirection.");
475 deepEqual(circref, circref, "... and checked on all levels!");
479 test('Circular reference with arrays', function() {
481 // pure array self-ref
485 var arrdump = QUnit.jsDump.parse(arr);
487 equal(arrdump, '[\n recursion(-1)\n]');
488 equal(arr, arr[0], 'no endless stack when trying to dump arrays with circular ref');
491 // mix obj-arr circular ref
493 var childarr = [obj];
494 obj.childarr = childarr;
496 var objdump = QUnit.jsDump.parse(obj);
497 var childarrdump = QUnit.jsDump.parse(childarr);
499 equal(objdump, '{\n "childarr": [\n recursion(-2)\n ]\n}');
500 equal(childarrdump, '[\n {\n "childarr": recursion(-2)\n }\n]');
502 equal(obj.childarr, childarr, 'no endless stack when trying to dump array/object mix with circular ref');
503 equal(childarr[0], obj, 'no endless stack when trying to dump array/object mix with circular ref');
508 test('Circular reference - test reported by soniciq in #105', function() {
509 var MyObject = function() {};
510 MyObject.prototype.parent = function(obj) {
511 if (obj === undefined) { return this._parent; }
514 MyObject.prototype.children = function(obj) {
515 if (obj === undefined) { return this._children; }
516 this._children = obj;
519 var a = new MyObject(),
526 equal(a.children(), barr);
527 deepEqual(a.children(), [b]);
531 var reset = QUnit.reset;
533 test("reset runs assertions", function() {
535 QUnit.reset = function() {
536 ok( false, "reset should not modify test status" );
537 reset.apply( this, arguments );
540 test("reset runs assertions, cleanup", function() {
546 function testAfterDone() {
547 var testName = "ensure has correct number of assertions";
549 function secondAfterDoneTest() {
550 QUnit.config.done = [];
551 // Because when this does happen, the assertion count parameter doesn't actually
552 // work we use this test to check the assertion count.
553 module("check previous test's assertion counts");
554 test('count previous two test\'s assertions', function () {
556 spans = document.getElementsByTagName('span'),
559 // Find these two tests
560 for (i = 0; i < spans.length; i++) {
561 if (spans[i].innerHTML.indexOf(testName) !== -1) {
562 tests.push(spans[i]);
566 // Walk dom to counts.
567 countNodes = tests[0].nextSibling.nextSibling.getElementsByTagName('b');
568 equal(countNodes[1].innerHTML, "99");
569 countNodes = tests[1].nextSibling.nextSibling.getElementsByTagName('b');
570 equal(countNodes[1].innerHTML, "99");
573 QUnit.config.done = [];
574 QUnit.done(secondAfterDoneTest);
576 module("Synchronous test after load of page");
578 asyncTest('Async test', function() {
580 for (var i = 1; i < 100; i++) {
585 test(testName, 99, function() {
586 for (var i = 1; i < 100; i++) {
591 // We need two of these types of tests in order to ensure that assertions
592 // don't move between tests.
593 test(testName + ' 2', 99, function() {
594 for (var i = 1; i < 100; i++) {
602 if (typeof setTimeout !== 'undefined') {
603 QUnit.done(testAfterDone);