123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- function getPreviousTests( rTestName, rModuleName ) {
- var testSpan, moduleSpan,
- matches = [],
- i = 0,
- rModule = /(^| )module-name( |$)/,
- testNames = typeof document.getElementsByClassName !== "undefined" ?
- document.getElementsByClassName("test-name") :
- (function( spans ) {
- var span,
- tests = [],
- i = 0,
- rTest = /(^| )test-name( |$)/;
- for ( ; (span = spans[i]); i++ ) {
- if ( rTest.test( span.className ) ) {
- tests.push( span );
- }
- }
- return tests;
- })( document.getElementsByTagName("span") );
- for ( ; (testSpan = testNames[i]); i++ ) {
- moduleSpan = testSpan;
- while ( (moduleSpan = moduleSpan.previousSibling) ) {
- if ( rModule.test( moduleSpan.className ) ) {
- break;
- }
- }
- if ( (!rTestName || rTestName.test( testSpan.innerHTML )) &&
- (!rModuleName || moduleSpan && rModuleName.test( moduleSpan.innerHTML )) ) {
- while ( (testSpan = testSpan.parentNode) ) {
- if ( testSpan.nodeName.toLowerCase() === "li" ) {
- matches.push( testSpan );
- }
- }
- }
- }
- return matches;
- }
- test("module without setup/teardown (default)", function() {
- expect(1);
- ok(true);
- });
- test("expect in test", 3, function() {
- ok(true);
- ok(true);
- ok(true);
- });
- test("expect in test", 1, function() {
- ok(true);
- });
- test("expect query and multiple issue", function() {
- expect(2);
- ok(true);
- var expected = expect();
- equal(expected, 2);
- expect(expected + 1);
- ok(true);
- });
- QUnit.module("assertion helpers");
- QUnit.test( "QUnit.assert compatibility", 5, function( assert ) {
- assert.ok( true, "Calling method on `assert` argument to test() callback" );
- // Should also work, although discouraged and not documented
- QUnit.assert.ok( true, "Calling method on QUnit.assert object" );
- // Test compatibility aliases
- QUnit.ok( true, "Calling aliased method in QUnit root object" );
- ok( true, "Calling aliased function in global namespace" );
- // Regression fix for #341
- // The assert-context way of testing discouraged global variables,
- // it doesn't make sense of it itself to be a global variable.
- // Only allows for mistakes (e.g. forgetting to list 'assert' as parameter)
- assert.notStrictEqual( window.assert, QUnit.assert, "Assert does not get exposed as a global variable" );
- });
- module("setup test", {
- setup: function() {
- ok(true);
- }
- });
- test("module with setup", function() {
- expect(2);
- ok(true);
- });
- test("module with setup, expect in test call", 2, function() {
- ok(true);
- });
- module("<script id='qunit-unescaped-module'>'module';</script>", {
- setup: function() {
- },
- teardown: function() {
- // We can't use ok(false) inside script tags since some browsers
- // don't evaluate script tags inserted through innerHTML after domready.
- // Counting them before/after doesn't cover everything either as qunit-modulefilter
- // is created before any test is ran. So use ids instead.
- if (document.getElementById('qunit-unescaped-module')) {
- // This can either be from in #qunit-modulefilter or #qunit-testresult
- ok(false, 'Unscaped module name');
- }
- if (document.getElementById('qunit-unescaped-test')) {
- ok(false, 'Unscaped test name');
- }
- if (document.getElementById('qunit-unescaped-assertion')) {
- ok(false, 'Unscaped test name');
- }
- }
- });
- test("<script id='qunit-unescaped-test'>'test';</script>", 1, function() {
- ok(true, "<script id='qunit-unescaped-asassertionsert'>'assertion';</script>");
- });
- var state;
- module("setup/teardown test", {
- setup: function() {
- state = true;
- ok(true);
- // Assert that we can introduce and delete globals in setup/teardown
- // without noglobals sounding any alarm.
- // Using an implied global variable instead of explicit window property
- // because there is no way to delete a window.property in IE6-8
- // `delete x` only works for `x = 1, and `delete window.x` throws exception.
- // No one-code fits all solution possible afaic. Resort to @cc.
- /*@cc_on
- @if (@_jscript_version < 9)
- x = 1;
- @else @*/
- window.x = 1;
- /*@end
- @*/
- },
- teardown: function() {
- ok(true);
- /*@cc_on
- @if (@_jscript_version < 9)
- delete x;
- @else @*/
- delete window.x;
- /*@end
- @*/
- }
- });
- test("module with setup/teardown", function() {
- expect(3);
- ok(true);
- });
- module("setup/teardown test 2");
- test("module without setup/teardown", function() {
- expect(1);
- ok(true);
- });
- var orgDate;
- module("Date test", {
- setup: function() {
- orgDate = Date;
- window.Date = function () {
- ok( false, 'QUnit should internally be independant from Date-related manipulation and testing' );
- return new orgDate();
- };
- },
- teardown: function() {
- window.Date = orgDate;
- }
- });
- test("sample test for Date test", function () {
- expect(1);
- ok(true);
- });
- if (typeof setTimeout !== 'undefined') {
- state = 'fail';
- module("teardown and stop", {
- teardown: function() {
- equal(state, "done", "Test teardown.");
- }
- });
- test("teardown must be called after test ended", function() {
- expect(1);
- stop();
- setTimeout(function() {
- state = "done";
- start();
- }, 13);
- });
- test("parameter passed to stop increments semaphore n times", function() {
- expect(1);
- stop(3);
- setTimeout(function() {
- state = "not enough starts";
- start();
- start();
- }, 13);
- setTimeout(function() {
- state = "done";
- start();
- }, 15);
- });
- test("parameter passed to start decrements semaphore n times", function() {
- expect(1);
- stop();
- stop();
- stop();
- setTimeout(function() {
- state = "done";
- start(3);
- }, 18);
- });
- module("async setup test", {
- setup: function() {
- stop();
- setTimeout(function() {
- ok(true);
- start();
- }, 500);
- }
- });
- asyncTest("module with async setup", function() {
- expect(2);
- ok(true);
- start();
- });
- module("async teardown test", {
- teardown: function() {
- stop();
- setTimeout(function() {
- ok(true);
- start();
- }, 500);
- }
- });
- asyncTest("module with async teardown", function() {
- expect(2);
- ok(true);
- start();
- });
- module("asyncTest");
- asyncTest("asyncTest", function() {
- expect(2);
- ok(true);
- setTimeout(function() {
- state = "done";
- ok(true);
- start();
- }, 13);
- });
- asyncTest("asyncTest", 2, function() {
- ok(true);
- setTimeout(function() {
- state = "done";
- ok(true);
- start();
- }, 13);
- });
- test("sync", 2, function() {
- stop();
- setTimeout(function() {
- ok(true);
- start();
- }, 13);
- stop();
- setTimeout(function() {
- ok(true);
- start();
- }, 125);
- });
- test("test synchronous calls to stop", 2, function() {
- stop();
- setTimeout(function() {
- ok(true, 'first');
- start();
- stop();
- setTimeout(function() {
- ok(true, 'second');
- start();
- }, 150);
- }, 150);
- });
- }
- module("save scope", {
- setup: function() {
- this.foo = "bar";
- },
- teardown: function() {
- deepEqual(this.foo, "bar");
- }
- });
- test("scope check", function() {
- expect(2);
- deepEqual(this.foo, "bar");
- });
- module("simple testEnvironment setup", {
- foo: "bar",
- // example of meta-data
- bugid: "#5311"
- });
- test("scope check", function() {
- deepEqual(this.foo, "bar");
- });
- test("modify testEnvironment",function() {
- expect(0);
- this.foo="hamster";
- });
- test("testEnvironment reset for next test",function() {
- deepEqual(this.foo, "bar");
- });
- module("testEnvironment with object", {
- options:{
- recipe:"soup",
- ingredients:["hamster","onions"]
- }
- });
- test("scope check", function() {
- deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions"]}) ;
- });
- test("modify testEnvironment",function() {
- expect(0);
- // since we do a shallow copy, the testEnvironment can be modified
- this.options.ingredients.push("carrots");
- });
- test("testEnvironment reset for next test",function() {
- deepEqual(this.options, {recipe:"soup",ingredients:["hamster","onions","carrots"]}, "Is this a bug or a feature? Could do a deep copy") ;
- });
- module("testEnvironment tests");
- function makeurl() {
- var testEnv = QUnit.current_testEnvironment;
- var url = testEnv.url || 'http://example.com/search';
- var q = testEnv.q || 'a search test';
- return url + '?q='+encodeURIComponent(q);
- }
- test("makeurl working",function() {
- equal( QUnit.current_testEnvironment, this, 'The current testEnvironment is global');
- equal( makeurl(), 'http://example.com/search?q=a%20search%20test', 'makeurl returns a default url if nothing specified in the testEnvironment');
- });
- module("testEnvironment with makeurl settings", {
- url: 'http://google.com/',
- q: 'another_search_test'
- });
- test("makeurl working with settings from testEnvironment", function() {
- equal( makeurl(), 'http://google.com/?q=another_search_test', 'rather than passing arguments, we use test metadata to from the url');
- });
- module("jsDump");
- test("jsDump output", function() {
- equal( QUnit.jsDump.parse([1, 2]), "[\n 1,\n 2\n]" );
- equal( QUnit.jsDump.parse({top: 5, left: 0}), "{\n \"left\": 0,\n \"top\": 5\n}" );
- if (typeof document !== 'undefined' && document.getElementById("qunit-header")) {
- equal( QUnit.jsDump.parse(document.getElementById("qunit-header")), "<h1 id=\"qunit-header\"></h1>" );
- equal( QUnit.jsDump.parse(document.getElementsByTagName("h1")), "[\n <h1 id=\"qunit-header\"></h1>\n]" );
- }
- });
- module("assertions");
- test("propEqual", 5, function( assert ) {
- var objectCreate = Object.create || function ( origin ) {
- function O() {}
- O.prototype = origin;
- var r = new O();
- return r;
- };
- function Foo( x, y, z ) {
- this.x = x;
- this.y = y;
- this.z = z;
- }
- Foo.prototype.doA = function () {};
- Foo.prototype.doB = function () {};
- Foo.prototype.bar = 'prototype';
- function Bar() {
- }
- Bar.prototype = objectCreate( Foo.prototype );
- Bar.prototype.constructor = Bar;
- assert.propEqual(
- new Foo( 1, '2', [] ),
- {
- x: 1,
- y: '2',
- z: []
- }
- );
- assert.notPropEqual(
- new Foo( '1', 2, 3 ),
- {
- x: 1,
- y: '2',
- z: 3
- },
- 'Primitive values are strictly compared'
- );
- assert.notPropEqual(
- new Foo( 1, '2', [] ),
- {
- x: 1,
- y: '2',
- z: {}
- },
- 'Array type is preserved'
- );
- assert.notPropEqual(
- new Foo( 1, '2', {} ),
- {
- x: 1,
- y: '2',
- z: []
- },
- 'Empty array is not the same as empty object'
- );
- assert.propEqual(
- new Foo( 1, '2', new Foo( [ 3 ], new Bar(), null ) ),
- {
- x: 1,
- y: '2',
- z: {
- x: [ 3 ],
- y: {},
- z: null
- }
- },
- 'Complex nesting of different types, inheritance and constructors'
- );
- });
- test("raises", 9, function() {
- function CustomError( message ) {
- this.message = message;
- }
- CustomError.prototype.toString = function() {
- return this.message;
- };
- throws(
- function() {
- throw "my error";
- }
- );
- throws(
- function() {
- throw "my error";
- },
- "simple string throw, no 'expected' value given"
- );
- // This test is for IE 7 and prior which does not properly
- // implement Error.prototype.toString
- throws(
- function() {
- throw new Error("error message");
- },
- /error message/,
- "use regexp against instance of Error"
- );
- throws(
- function() {
- throw new CustomError();
- },
- CustomError,
- 'thrown error is an instance of CustomError'
- );
- throws(
- function() {
- throw new CustomError("some error description");
- },
- /description/,
- "use a regex to match against the stringified error"
- );
- throws(
- function() {
- throw new CustomError("some error description");
- },
- function( err ) {
- if ( (err instanceof CustomError) && /description/.test(err) ) {
- return true;
- }
- },
- "custom validation function"
- );
- throws(
- function() {
- /*jshint evil:true */
- ( window.execScript || function( data ) {
- window["eval"].call( window, data );
- })( "throw 'error';" );
- },
- 'globally-executed errors caught'
- );
- this.CustomError = CustomError;
- throws(
- function() {
- throw new this.CustomError("some error description");
- },
- /description/,
- "throw error from property of 'this' context"
- );
- raises(
- function() {
- throw "error";
- },
- "simple throw, asserting with deprecated raises() function"
- );
- });
- if (typeof document !== "undefined") {
- module("fixture");
- test("setup", function() {
- expect(0);
- document.getElementById("qunit-fixture").innerHTML = "foobar";
- });
- test("basics", function() {
- equal( document.getElementById("qunit-fixture").innerHTML, "test markup", "automatically reset" );
- });
- test("running test name displayed", function() {
- expect(2);
- var displaying = document.getElementById("qunit-testresult");
- ok( /running test name displayed/.test(displaying.innerHTML), "Expect test name to be found in displayed text" );
- ok( /fixture/.test(displaying.innerHTML), "Expect module name to be found in displayed text" );
- });
- (function() {
- var delayNextSetup,
- sleep = function( n ) {
- stop();
- setTimeout( function() { start(); }, n );
- };
- module("timing", {
- setup: function() {
- if ( delayNextSetup ) {
- delayNextSetup = false;
- sleep( 250 );
- }
- }
- });
- test("setup", 0, function() {
- delayNextSetup = true;
- });
- test("basics", 2, function() {
- var previous = getPreviousTests(/^setup$/, /^timing$/)[0],
- runtime = previous.lastChild.previousSibling;
- ok( /(^| )runtime( |$)/.test( runtime.className ), "Runtime element exists" );
- ok( /^\d+ ms$/.test( runtime.innerHTML ), "Runtime reported in ms" );
- });
- test("values", 2, function() {
- var basics = getPreviousTests(/^setup$/, /^timing$/)[0],
- slow = getPreviousTests(/^basics$/, /^timing$/)[0];
- ok( parseInt( basics.lastChild.previousSibling.innerHTML, 10 ) < 50, "Fast runtime for trivial test" );
- ok( parseInt( slow.lastChild.previousSibling.innerHTML, 10 ) > 250, "Runtime includes setup" );
- });
- })();
- }
- module("custom assertions");
- (function() {
- function mod2(value, expected, message) {
- var actual = value % 2;
- QUnit.push(actual == expected, actual, expected, message);
- }
- test("mod2", function() {
- mod2(2, 0, "2 % 2 == 0");
- mod2(3, 1, "3 % 2 == 1");
- });
- })();
- module("recursions");
- function Wrap(x) {
- this.wrap = x;
- if (x === undefined) {
- this.first = true;
- }
- }
- function chainwrap(depth, first, prev) {
- depth = depth || 0;
- var last = prev || new Wrap();
- first = first || last;
- if (depth == 1) {
- first.wrap = last;
- }
- if (depth > 1) {
- last = chainwrap(depth-1, first, new Wrap(last));
- }
- return last;
- }
- test("check jsDump recursion", function() {
- expect(4);
- var noref = chainwrap(0);
- var nodump = QUnit.jsDump.parse(noref);
- equal(nodump, '{\n "first": true,\n "wrap": undefined\n}');
- var selfref = chainwrap(1);
- var selfdump = QUnit.jsDump.parse(selfref);
- equal(selfdump, '{\n "first": true,\n "wrap": recursion(-1)\n}');
- var parentref = chainwrap(2);
- var parentdump = QUnit.jsDump.parse(parentref);
- equal(parentdump, '{\n "wrap": {\n "first": true,\n "wrap": recursion(-2)\n }\n}');
- var circref = chainwrap(10);
- var circdump = QUnit.jsDump.parse(circref);
- ok(new RegExp("recursion\\(-10\\)").test(circdump), "(" +circdump + ") should show -10 recursion level");
- });
- test("check (deep-)equal recursion", function() {
- var noRecursion = chainwrap(0);
- equal(noRecursion, noRecursion, "I should be equal to me.");
- deepEqual(noRecursion, noRecursion, "... and so in depth.");
- var selfref = chainwrap(1);
- equal(selfref, selfref, "Even so if I nest myself.");
- deepEqual(selfref, selfref, "... into the depth.");
- var circref = chainwrap(10);
- equal(circref, circref, "Or hide that through some levels of indirection.");
- deepEqual(circref, circref, "... and checked on all levels!");
- });
- test('Circular reference with arrays', function() {
- // pure array self-ref
- var arr = [];
- arr.push(arr);
- var arrdump = QUnit.jsDump.parse(arr);
- equal(arrdump, '[\n recursion(-1)\n]');
- equal(arr, arr[0], 'no endless stack when trying to dump arrays with circular ref');
- // mix obj-arr circular ref
- var obj = {};
- var childarr = [obj];
- obj.childarr = childarr;
- var objdump = QUnit.jsDump.parse(obj);
- var childarrdump = QUnit.jsDump.parse(childarr);
- equal(objdump, '{\n "childarr": [\n recursion(-2)\n ]\n}');
- equal(childarrdump, '[\n {\n "childarr": recursion(-2)\n }\n]');
- equal(obj.childarr, childarr, 'no endless stack when trying to dump array/object mix with circular ref');
- equal(childarr[0], obj, 'no endless stack when trying to dump array/object mix with circular ref');
- });
- test('Circular reference - test reported by soniciq in #105', function() {
- var MyObject = function() {};
- MyObject.prototype.parent = function(obj) {
- if (obj === undefined) { return this._parent; }
- this._parent = obj;
- };
- MyObject.prototype.children = function(obj) {
- if (obj === undefined) { return this._children; }
- this._children = obj;
- };
- var a = new MyObject(),
- b = new MyObject();
- var barr = [b];
- a.children(barr);
- b.parent(a);
- equal(a.children(), barr);
- deepEqual(a.children(), [b]);
- });
- (function() {
- var reset = QUnit.reset;
- module("reset");
- test("reset runs assertions", function() {
- expect(0);
- QUnit.reset = function() {
- ok( false, "reset should not modify test status" );
- reset.apply( this, arguments );
- };
- });
- test("reset runs assertions, cleanup", function() {
- expect(0);
- QUnit.reset = reset;
- });
- })();
- function testAfterDone() {
- var testName = "ensure has correct number of assertions";
- function secondAfterDoneTest() {
- QUnit.config.done = [];
- // Because when this does happen, the assertion count parameter doesn't actually
- // work we use this test to check the assertion count.
- module("check previous test's assertion counts");
- test('count previous two test\'s assertions', function () {
- var tests = getPreviousTests(/^ensure has correct number of assertions/, /^Synchronous test after load of page$/);
- equal(tests[0].firstChild.lastChild.getElementsByTagName("b")[1].innerHTML, "99");
- equal(tests[1].firstChild.lastChild.getElementsByTagName("b")[1].innerHTML, "99");
- });
- }
- QUnit.config.done = [];
- QUnit.done(secondAfterDoneTest);
- module("Synchronous test after load of page");
- asyncTest('Async test', function() {
- start();
- for (var i = 1; i < 100; i++) {
- ok(i);
- }
- });
- test(testName, 99, function() {
- for (var i = 1; i < 100; i++) {
- ok(i);
- }
- });
- // We need two of these types of tests in order to ensure that assertions
- // don't move between tests.
- test(testName + ' 2', 99, function() {
- for (var i = 1; i < 100; i++) {
- ok(i);
- }
- });
- }
- if (typeof setTimeout !== 'undefined') {
- QUnit.done(testAfterDone);
- }
|