UNPKG

typescript-closure-tools

Version:

Command-line tools to convert closure-style JSDoc annotations to typescript, and to convert typescript sources to closure externs files

1,651 lines (1,375 loc) 51.2 kB
/// <reference path="qunit.d.ts" /> QUnit.test("deepEqual test", function () { var obj = { foo: "bar" }; QUnit.deepEqual(obj, { foo: "bar" }, "Two objects can be the same in value"); }); test("deepEqual test", function () { var obj = { foo: "bar" }; deepEqual(obj, { foo: "bar" }, "Two objects can be the same in value"); }); QUnit.test("a test", function () { QUnit.equal(1, "1", "String '1' and number 1 have the same value"); }); test("a test", function () { equal(1, "1", "String '1' and number 1 have the same value"); }); test("test Array 1", function () { equal([1,2,3], ["test", "foo"], "String '1' and number 1 have the same value"); }); test("test Array 2", function () { QUnit.equal([1,2,3], ["test", "foo"], "String '1' and number 1 have the same value"); }); QUnit.test("equal test", function () { QUnit.equal(0, 0, "Zero; equal succeeds"); QUnit.equal("", 0, "Empty, Zero; equal succeeds"); QUnit.equal("", "", "Empty, Empty; equal succeeds"); QUnit.equal(0, 0, "Zero, Zero; equal succeeds"); QUnit.equal("three", 3, "Three, 3; equal fails"); QUnit.equal(null, false, "null, false; equal fails"); }); test("equal test", function () { equal(0, 0, "Zero; equal succeeds"); equal("", 0, "Empty, Zero; equal succeeds"); equal("", "", "Empty, Empty; equal succeeds"); equal(0, 0, "Zero, Zero; equal succeeds"); equal("three", 3, "Three, 3; equal fails"); equal(null, false, "null, false; equal fails"); }); QUnit.test("notDeepEqual test", function () { var obj = { foo: "bar" }; QUnit.notDeepEqual(obj, { foo: "bla" }, "Different object, same key, different value, not equal"); }); test("notDeepEqual test", function () { var obj = { foo: "bar" }; notDeepEqual(obj, { foo: "bla" }, "Different object, same key, different value, not equal"); }); QUnit.test("a test", function () { QUnit.notEqual(1, "2", "String '2' and number 1 don't have the same value"); }); test("a test", function () { notEqual(1, "2", "String '2' and number 1 don't have the same value"); }); QUnit.test("a test", function () { QUnit.notStrictEqual(1, "1", "String '1' and number 1 don't have the same value"); }); test("a test", function () { notStrictEqual(1, "1", "String '1' and number 1 don't have the same value"); }); QUnit.test("ok test", function () { QUnit.ok(true, "true succeeds"); QUnit.ok("non-empty", "non-empty string succeeds"); QUnit.ok(false, "false fails"); QUnit.ok(0, "0 fails"); QUnit.ok(NaN, "NaN fails"); QUnit.ok("", "empty string fails"); QUnit.ok(null, "null fails"); QUnit.ok(undefined, "undefined fails"); }); test("ok test", function () { ok(true, "true succeeds"); ok("non-empty", "non-empty string succeeds"); ok(false, "false fails"); ok(0, "0 fails"); ok(NaN, "NaN fails"); ok("", "empty string fails"); ok(null, "null fails"); ok(undefined, "undefined fails"); }); QUnit.test("strictEqual test", function () { QUnit.strictEqual(1, 1, "1 and 1 are the same value and type"); }); test("strictEqual test", function () { strictEqual(1, 1, "1 and 1 are the same value and type"); }); QUnit.test("a test", function () { QUnit.stop(); QUnit.start(); }); test("a test", function () { stop(); start(); }); QUnit.config.autostart = false; QUnit.start(); QUnit.config.urlConfig.push(<any>{ id: "min", label: "Minified source", tooltip: "Load minified source files instead of the regular unminified ones." }); QUnit.asyncTest("asynchronous test: one second later!", function () { QUnit.expect(1); }); asyncTest("asynchronous test: one second later!", function () { expect(1); }); QUnit.module("group a"); QUnit.test("a basic test example", function () { QUnit.ok(true, "this test is fine"); }); QUnit.test("a basic test example 2", function () { QUnit.ok(true, "this test is fine"); }); QUnit.module("group b"); QUnit.test("a basic test example 3", function () { QUnit.ok(true, "this test is fine"); }); QUnit.test("a basic test example 4", function () { QUnit.ok(true, "this test is fine"); }); QUnit.module("module A", { setup: function () { // prepare something for all following tests }, teardown: function () { // clean up after each test } }); QUnit.test("a test", function (assert) { function square(x) { return x * x; } var result = square(2); assert.equal(result, 4, "square(2) equals 4"); }); test( "throws", function() { function CustomError( message ) { this.message = message; } CustomError.prototype.toString = function() { return this.message; }; throws( function() { throw "error" }, "throws with just a message, no expected" ); throws( function() { throw new Error(); }, Error, "raised error is an instance of CustomError" ); throws( function() { throw new Error("some error description"); }, /description/, "raised error message contains 'description'" ); QUnit.throws( function() { throw "error" }, "throws with just a message, no expected" ); QUnit.throws( function() { throw new Error(); }, Error, "raised error is an instance of CustomError" ); QUnit.throws( function() { throw new Error("some error description"); }, /description/, "raised error message contains 'description'" ); }); QUnit.module("equiv"); test("Primitive types and constants", function () { equal(QUnit.equiv(null, null), true, "null"); equal(QUnit.equiv(null, {}), false, "null"); equal(QUnit.equiv(null, undefined), false, "null"); equal(QUnit.equiv(null, 0), false, "null"); equal(QUnit.equiv(null, false), false, "null"); equal(QUnit.equiv(null, ''), false, "null"); equal(QUnit.equiv(null, []), false, "null"); equal(QUnit.equiv(undefined, undefined), true, "undefined"); equal(QUnit.equiv(undefined, null), false, "undefined"); equal(QUnit.equiv(undefined, 0), false, "undefined"); equal(QUnit.equiv(undefined, false), false, "undefined"); equal(QUnit.equiv(undefined, {}), false, "undefined"); equal(QUnit.equiv(undefined, []), false, "undefined"); equal(QUnit.equiv(undefined, ""), false, "undefined"); // Nan usually doest not equal to Nan using the '==' operator. // Only isNaN() is able to do it. equal(QUnit.equiv(0/0, 0/0), true, "NaN"); // NaN VS NaN equal(QUnit.equiv(1/0, 2/0), true, "Infinity"); // Infinity VS Infinity equal(QUnit.equiv(-1/0, 2/0), false, "-Infinity, Infinity"); // -Infinity VS Infinity equal(QUnit.equiv(-1/0, -2/0), true, "-Infinity, -Infinity"); // -Infinity VS -Infinity equal(QUnit.equiv(0/0, 1/0), false, "NaN, Infinity"); // Nan VS Infinity equal(QUnit.equiv(1/0, 0/0), false, "NaN, Infinity"); // Nan VS Infinity equal(QUnit.equiv(0/0, null), false, "NaN"); equal(QUnit.equiv(0/0, undefined), false, "NaN"); equal(QUnit.equiv(0/0, 0), false, "NaN"); equal(QUnit.equiv(0/0, false), false, "NaN"); equal(QUnit.equiv(0/0, function () {}), false, "NaN"); equal(QUnit.equiv(1/0, null), false, "NaN, Infinity"); equal(QUnit.equiv(1/0, undefined), false, "NaN, Infinity"); equal(QUnit.equiv(1/0, 0), false, "NaN, Infinity"); equal(QUnit.equiv(1/0, 1), false, "NaN, Infinity"); equal(QUnit.equiv(1/0, false), false, "NaN, Infinity"); equal(QUnit.equiv(1/0, true), false, "NaN, Infinity"); equal(QUnit.equiv(1/0, function () {}), false, "NaN, Infinity"); equal(QUnit.equiv(0, 0), true, "number"); equal(QUnit.equiv(0, 1), false, "number"); equal(QUnit.equiv(1, 0), false, "number"); equal(QUnit.equiv(1, 1), true, "number"); equal(QUnit.equiv(1.1, 1.1), true, "number"); equal(QUnit.equiv(0.0000005, 0.0000005), true, "number"); equal(QUnit.equiv(0, ''), false, "number"); equal(QUnit.equiv(0, '0'), false, "number"); equal(QUnit.equiv(1, '1'), false, "number"); equal(QUnit.equiv(0, false), false, "number"); equal(QUnit.equiv(1, true), false, "number"); equal(QUnit.equiv(true, true), true, "boolean"); equal(QUnit.equiv(true, false), false, "boolean"); equal(QUnit.equiv(false, true), false, "boolean"); equal(QUnit.equiv(false, 0), false, "boolean"); equal(QUnit.equiv(false, null), false, "boolean"); equal(QUnit.equiv(false, undefined), false, "boolean"); equal(QUnit.equiv(true, 1), false, "boolean"); equal(QUnit.equiv(true, null), false, "boolean"); equal(QUnit.equiv(true, undefined), false, "boolean"); equal(QUnit.equiv('', ''), true, "string"); equal(QUnit.equiv('a', 'a'), true, "string"); equal(QUnit.equiv("foobar", "foobar"), true, "string"); equal(QUnit.equiv("foobar", "foo"), false, "string"); equal(QUnit.equiv('', 0), false, "string"); equal(QUnit.equiv('', false), false, "string"); equal(QUnit.equiv('', null), false, "string"); equal(QUnit.equiv('', undefined), false, "string"); // Rename for lint validation. // We know this is bad, we are asserting whether we can coop with bad code like this. var SafeNumber = Number, SafeString = String, SafeBoolean = Boolean, SafeObject = Object; // primitives vs. objects equal(QUnit.equiv(0, new SafeNumber()), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeNumber(), 0), true, "primitives vs. objects"); equal(QUnit.equiv(1, new SafeNumber(1)), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeNumber(1), 1), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeNumber(0), 1), false, "primitives vs. objects"); equal(QUnit.equiv(0, new SafeNumber(1)), false, "primitives vs. objects"); equal(QUnit.equiv(new SafeString(), ""), true, "primitives vs. objects"); equal(QUnit.equiv("", new SafeString()), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeString("My String"), "My String"), true, "primitives vs. objects"); equal(QUnit.equiv("My String", new SafeString("My String")), true, "primitives vs. objects"); equal(QUnit.equiv("Bad String", new SafeString("My String")), false, "primitives vs. objects"); equal(QUnit.equiv(new SafeString("Bad String"), "My String"), false, "primitives vs. objects"); equal(QUnit.equiv(false, new SafeBoolean()), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeBoolean(), false), true, "primitives vs. objects"); equal(QUnit.equiv(true, new SafeBoolean(true)), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeBoolean(true), true), true, "primitives vs. objects"); equal(QUnit.equiv(true, new SafeBoolean(1)), true, "primitives vs. objects"); equal(QUnit.equiv(false, new SafeBoolean(false)), true, "primitives vs. objects"); equal(QUnit.equiv(new SafeBoolean(false), false), true, "primitives vs. objects"); equal(QUnit.equiv(false, new SafeBoolean(0)), true, "primitives vs. objects"); equal(QUnit.equiv(true, new SafeBoolean(false)), false, "primitives vs. objects"); equal(QUnit.equiv(new SafeBoolean(false), true), false, "primitives vs. objects"); equal(QUnit.equiv(new SafeObject(), {}), true, "object literal vs. instantiation"); equal(QUnit.equiv({}, new SafeObject()), true, "object literal vs. instantiation"); equal(QUnit.equiv(new SafeObject(), {a:1}), false, "object literal vs. instantiation"); equal(QUnit.equiv({a:1}, new SafeObject()), false, "object literal vs. instantiation"); equal(QUnit.equiv({a:undefined}, new SafeObject()), false, "object literal vs. instantiation"); equal(QUnit.equiv(new SafeObject(), {a:undefined}), false, "object literal vs. instantiation"); }); test("Objects Basics.", function() { equal(QUnit.equiv({}, {}), true); equal(QUnit.equiv({}, null), false); equal(QUnit.equiv({}, undefined), false); equal(QUnit.equiv({}, 0), false); equal(QUnit.equiv({}, false), false); // This test is a hard one, it is very important // REASONS: // 1) They are of the same type "object" // 2) [] instanceof Object is true // 3) Their properties are the same (doesn't exists) equal(QUnit.equiv({}, []), false); equal(QUnit.equiv({a:1}, {a:1}), true); equal(QUnit.equiv({a:1}, {a:"1"}), false); equal(QUnit.equiv({a:[]}, {a:[]}), true); equal(QUnit.equiv({a:{}}, {a:null}), false); equal(QUnit.equiv({a:1}, {}), false); equal(QUnit.equiv({}, {a:1}), false); // Hard ones equal(QUnit.equiv({a:undefined}, {}), false); equal(QUnit.equiv({}, {a:undefined}), false); equal(QUnit.equiv( { a: [{ bar: undefined }] }, { a: [{ bat: undefined }] } ), false); // Objects with no prototype, created via Object.create(null), are used e.g. as dictionaries. // Being able to test equivalence against object literals is quite useful. if (typeof Object.create === 'function') { equal(QUnit.equiv(Object.create(null), {}), true, "empty object without prototype VS empty object"); var nonEmptyWithNoProto = Object.create(null); nonEmptyWithNoProto.foo = "bar"; equal(QUnit.equiv(nonEmptyWithNoProto, { foo: "bar" }), true, "object without prototype VS object"); } }); test("Arrays Basics.", function() { equal(QUnit.equiv([], []), true); // May be a hard one, can invoke a crash at execution. // because their types are both "object" but null isn't // like a true object, it doesn't have any property at all. equal(QUnit.equiv([], null), false); equal(QUnit.equiv([], undefined), false); equal(QUnit.equiv([], false), false); equal(QUnit.equiv([], 0), false); equal(QUnit.equiv([], ""), false); // May be a hard one, but less hard // than {} with [] (note the order) equal(QUnit.equiv([], {}), false); equal(QUnit.equiv([null],[]), false); equal(QUnit.equiv([undefined],[]), false); equal(QUnit.equiv([],[null]), false); equal(QUnit.equiv([],[undefined]), false); equal(QUnit.equiv([null],[undefined]), false); equal(QUnit.equiv([[]],[[]]), true); equal(QUnit.equiv([[],[],[]],[[],[],[]]), true); equal(QUnit.equiv( [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]], [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), true); equal(QUnit.equiv( [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]], [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // shorter false); equal(QUnit.equiv( [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[{}]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]], [[],[],[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]), // deepest element not an array false); }); test("Prototypal inheritance", function() { function Gizmo(id?) { this.id = id; } function Hoozit(id?) { this.id = id; } Hoozit.prototype = new Gizmo(); var gizmo = new Gizmo("ok"); var hoozit = new Hoozit("ok"); // Try this test many times after test on instances that hold function // to make sure that our code does not mess with last object constructor memoization. equal(QUnit.equiv(function () {}, function () {}), false); // Hoozit inherit from Gizmo // hoozit instanceof Hoozit; // true // hoozit instanceof Gizmo; // true equal(QUnit.equiv(hoozit, gizmo), true); Gizmo.prototype.bar = true; // not a function just in case we skip them // Hoozit inherit from Gizmo // They are equivalent equal(QUnit.equiv(hoozit, gizmo), true); // Make sure this is still true !important // The reason for this is that I forgot to reset the last // caller to where it were called from. equal(QUnit.equiv(function () {}, function () {}), false); // Make sure this is still true !important equal(QUnit.equiv(hoozit, gizmo), true); Hoozit.prototype.foo = true; // not a function just in case we skip them // Gizmo does not inherit from Hoozit // gizmo instanceof Gizmo; // true // gizmo instanceof Hoozit; // false // They are not equivalent equal(QUnit.equiv(hoozit, gizmo), false); // Make sure this is still true !important equal(QUnit.equiv(function () {}, function () {}), false); }); test("Instances", function() { function A() {} var a1 = new A(); var a2 = new A(); function B() { this.fn = function () {}; } var b1 = new B(); var b2 = new B(); equal(QUnit.equiv(a1, a2), true, "Same property, same constructor"); // b1.fn and b2.fn are functions but they are different references // But we decided to skip function for instances. equal(QUnit.equiv(b1, b2), true, "Same property, same constructor"); equal(QUnit.equiv(a1, b1), false, "Same properties but different constructor"); // failed function Car(year) { var privateVar = 0; this.year = year; this.isOld = function() { return year > 10; }; } function Human(year) { var privateVar = 1; this.year = year; this.isOld = function() { return year > 80; }; } var car = new Car(30); var carSame = new Car(30); var carDiff = new Car(10); var human = new Human(30); var diff = { year: 30 }; var same = { year: 30, isOld: function () {} }; equal(QUnit.equiv(car, car), true); equal(QUnit.equiv(car, carDiff), false); equal(QUnit.equiv(car, carSame), true); equal(QUnit.equiv(car, human), false); }); test("Complex Instances Nesting (with function value in literals and/or in nested instances)", function() { function A(fn) { this.a = {}; this.fn = fn; this.b = {a: []}; this.o = {}; this.fn1 = fn; } function B(fn) { this.fn = fn; this.fn1 = function () {}; this.a = new A(function () {}); } function fnOutside() { } function C(fn) { function fnInside() { } this.x = 10; this.fn = fn; this.fn1 = function () {}; this.fn2 = fnInside; this.fn3 = { a: true, b: fnOutside // ok make reference to a function in all instances scope }; this.o1 = {}; // This function will be ignored. // Even if it is not visible for all instances (e.g. locked in a closures), // it is from a property that makes part of an instance (e.g. from the C constructor) this.b1 = new B(function () {}); this.b2 = new B({ x: { b2: new B(function() {}) } }); } function D(fn) { function fnInside() { } this.x = 10; this.fn = fn; this.fn1 = function () {}; this.fn2 = fnInside; this.fn3 = { a: true, b: fnOutside, // ok make reference to a function in all instances scope // This function won't be ingored. // It isn't visible for all C insances // and it is not in a property of an instance. (in an Object instances e.g. the object literal) c: fnInside }; this.o1 = {}; // This function will be ignored. // Even if it is not visible for all instances (e.g. locked in a closures), // it is from a property that makes part of an instance (e.g. from the C constructor) this.b1 = new B(function () {}); this.b2 = new B({ x: { b2: new B(function() {}) } }); } function E(fn) { function fnInside() { } this.x = 10; this.fn = fn; this.fn1 = function () {}; this.fn2 = fnInside; this.fn3 = { a: true, b: fnOutside // ok make reference to a function in all instances scope }; this.o1 = {}; // This function will be ignored. // Even if it is not visible for all instances (e.g. locked in a closures), // it is from a property that makes part of an instance (e.g. from the C constructor) this.b1 = new B(function () {}); this.b2 = new B({ x: { b1: new B({a: function() {}}), b2: new B(function() {}) } }); } var a1 = new A(function () {}); var a2 = new A(function () {}); equal(QUnit.equiv(a1, a2), true); equal(QUnit.equiv(a1, a2), true); // different instances var b1 = new B(function () {}); var b2 = new B(function () {}); equal(QUnit.equiv(b1, b2), true); var c1 = new C(function () {}); var c2 = new C(function () {}); equal(QUnit.equiv(c1, c2), true); var d1 = new D(function () {}); var d2 = new D(function () {}); equal(QUnit.equiv(d1, d2), false); var e1 = new E(function () {}); var e2 = new E(function () {}); equal(QUnit.equiv(e1, e2), false); }); test('object with references to self wont loop', function() { var circularA = <any>{ abc:null }, circularB = <any>{ abc:null }; circularA.abc = circularA; circularB.abc = circularB; equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)"); circularA.def = 1; circularB.def = 1; equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object (ambigous test)"); circularA.def = 1; circularB.def = 0; equal(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object (unambigous test)"); }); test('array with references to self wont loop', function() { var circularA = [], circularB = []; circularA.push(circularA); circularB.push(circularB); equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)"); circularA.push( 'abc' ); circularB.push( 'abc' ); equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on array (ambigous test)"); circularA.push( 'hello' ); circularB.push( 'goodbye' ); equal(QUnit.equiv(circularA, circularB), false, "Should not repeat test on array (unambigous test)"); }); test('mixed object/array with references to self wont loop', function() { var circularA = <any>[{abc:null}], circularB = <any>[{abc:null}]; circularA[0].abc = circularA; circularB[0].abc = circularB; circularA.push(circularA); circularB.push(circularB); equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)"); circularA[0].def = 1; circularB[0].def = 1; equal(QUnit.equiv(circularA, circularB), true, "Should not repeat test on object/array (ambigous test)"); circularA[0].def = 1; circularB[0].def = 0; equal(QUnit.equiv(circularA, circularB), false, "Should not repeat test on object/array (unambigous test)"); }); test("Test that must be done at the end because they extend some primitive's prototype", function() { // Try that a function looks like our regular expression. // This tests if we check that a and b are really both instance of RegExp //Function.prototype.global = true; //Function.prototype.multiline = true; //Function.prototype.ignoreCase = false; //Function.prototype.source = "my regex"; var re = /my regex/gm; equal(QUnit.equiv(re, function () {}), false, "A function that looks that a regex isn't a regex"); // This test will ensures it works in both ways, and ALSO especially that we can make differences // between RegExp and Function constructor because typeof on a RegExpt instance is "function" equal(QUnit.equiv(function () {}, re), false, "Same conversely, but ensures that function and regexp are distinct because their constructor are different"); }); QUnit.start(); test("just a test", function() { expect(1); ok(true); }); // ************** BUG ? ****************** // TODO disable reordering for this suite! var moduleContext, moduleDoneContext, testContext, testDoneContext, logContext; /* QUnit.begin(function() { //begin++; }); QUnit.done(function() { }); QUnit.moduleStart(function(context) { //moduleStart++; //moduleContext = context; }); QUnit.moduleDone(function(context) { //moduleDone++; //moduleDoneContext = context; }); QUnit.testStart(function(context) { //testStart++; //testContext = context; }); QUnit.testDone(function(context) { //testDone++; //testDoneContext = context; }); QUnit.log(function(context) { //log++; //logContext = context; }); */ QUnit.module("logs1"); QUnit.test("test1", 15, function() { equal( begin, 1, "QUnit.begin calls" ); equal( moduleStart, 1, "QUnit.moduleStart calls" ); equal( testStart, 1, "QUnit.testStart calls" ); equal( testDone, 0, "QUnit.testDone calls" ); equal( moduleDone, 0, "QUnit.moduleDone calls" ); deepEqual( logContext, { name: "test1", module: "logs1", result: true, message: "QUnit.moduleDone calls", actual: 0, expected: 0 }, "log context after equal(actual, expected, message)" ); equal( "foo", "foo" ); deepEqual(logContext, { name: "test1", module: "logs1", result: true, message: undefined, actual: "foo", expected: "foo" }, "log context after equal(actual, expected)" ); ok( true, "ok(true, message)" ); deepEqual( logContext, { module: "logs1", name: "test1", result: true, message: "ok(true, message)" }, "log context after ok(true, message)" ); strictEqual( testDoneContext, undefined, "testDone context" ); deepEqual( testContext, { module: "logs1", name: "test1" }, "test context" ); strictEqual( moduleDoneContext, undefined, "moduleDone context" ); deepEqual( moduleContext, { name: "logs1" }, "module context" ); equal( log, 14, "QUnit.log calls" ); }); QUnit.test("test2", 11, function() { equal( begin, 1, "QUnit.begin calls" ); equal( moduleStart, 1, "QUnit.moduleStart calls" ); equal( testStart, 2, "QUnit.testStart calls" ); equal( testDone, 1, "QUnit.testDone calls" ); equal( moduleDone, 0, "QUnit.moduleDone calls" ); ok( typeof testDoneContext.duration === "number" , "testDone context: duration" ); delete testDoneContext.duration; deepEqual( testDoneContext, { module: "logs1", name: "test1", failed: 0, passed: 15, total: 15 }, "testDone context" ); deepEqual( testContext, { module: "logs1", name: "test2" }, "test context" ); strictEqual( moduleDoneContext, undefined, "moduleDone context" ); deepEqual( moduleContext, { name: "logs1" }, "module context" ); equal( log, 25, "QUnit.log calls" ); }); QUnit.module("logs2"); QUnit.test( "test1", 9, function() { equal( begin, 1, "QUnit.begin calls" ); equal( moduleStart, 2, "QUnit.moduleStart calls" ); equal( testStart, 3, "QUnit.testStart calls" ); equal( testDone, 2, "QUnit.testDone calls" ); equal( moduleDone, 1, "QUnit.moduleDone calls" ); deepEqual( testContext, { module: "logs2", name: "test1" }, "test context" ); deepEqual( moduleDoneContext, { name: "logs1", failed: 0, passed: 26, total: 26 }, "moduleDone context" ); deepEqual( moduleContext, { name: "logs2" }, "module context" ); equal( log, 34, "QUnit.log calls" ); }); QUnit.test( "test2", 8, function() { equal( begin, 1, "QUnit.begin calls" ); equal( moduleStart, 2, "QUnit.moduleStart calls" ); equal( testStart, 4, "QUnit.testStart calls" ); equal( testDone, 3, "QUnit.testDone calls" ); equal( moduleDone, 1, "QUnit.moduleDone calls" ); deepEqual( testContext, { module: "logs2", name: "test2" }, "test context" ); deepEqual( moduleContext, { name: "logs2" }, "module context" ); equal( log, 42, "QUnit.log calls" ); }); var testAutorun = true; QUnit.done(function() { if (!testAutorun) { return; } testAutorun = false; QUnit.module("autorun"); QUnit.test("reset", 0, function() {}); //moduleStart = moduleDone = 0; test("first", function() { equal(moduleStart, 1, "test started"); equal(moduleDone, 0, "test in progress"); }); test("second", function() { equal(moduleStart, 2, "test started"); equal(moduleDone, 1, "test in progress"); }); }); QUnit.log(function(details: any) { if (!details.result) { var output = "FAILED: " + (details.message ? details.message + ", " : ""); if (details.actual) { output += "expected: " + details.expected + ", actual: " + details.actual; } if (details.source) { output += ", " + details.source; } } }); QUnit.test("fail twice with stacktrace", function(assert) { /*jshint expr:true */ assert.equal(true, false); assert.equal(true, false, "gotta fail"); }); test("module without setup/teardown (default)", function() { expect(1); ok(true); }); QUnit.test("expect in test", 3, function() { ok(true); ok(true); ok(true); }); QUnit.test("expect in test", 5, function() { ok(true); }); test("expect query and multiple issue", function() { expect(2); ok(true); var expected = expect(null); 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*/null, QUnit.assert, "Assert does not get exposed as a global variable" ); }); QUnit.module("setup test", { setup: function() { ok(true); } }); test("module with setup", function() { expect(2); ok(true); }); QUnit.test("module with setup, expect in test call", 2, function() { ok(true); }); QUnit.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'); } } }); QUnit.test("<script id='qunit-unescaped-test'>'test';</script>", 1, function() { ok(true, "<script id='qunit-unescaped-asassertionsert'>'assertion';</script>"); }); var state; QUnit.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); }); QUnit.module("setup/teardown test 2"); test("module without setup/teardown", function() { expect(1); ok(true); }); var orgDate; QUnit.module("Date test", { setup: function() { orgDate = Date; var Date = function () { ok( false, 'QUnit should internally be independant from Date-related manipulation and testing' ); return new orgDate(); }; }, teardown: function() { var date = orgDate; } }); test("sample test for Date test", function () { expect(1); ok(true); }); if (typeof setTimeout !== 'undefined') { state = 'fail'; QUnit.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); }); QUnit.module("async setup test", { setup: function() { stop(); setTimeout(function() { ok(true); start(); }, 500); } }); asyncTest("module with async setup", function() { expect(2); ok(true); start(); }); QUnit.module("async teardown test", { teardown: function() { stop(); setTimeout(function() { ok(true); start(); }, 500); } }); asyncTest("module with async teardown", function() { expect(2); ok(true); start(); }); QUnit.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); }); QUnit.test("sync", 2, function() { stop(); setTimeout(function() { ok(true); start(); }, 13); stop(); setTimeout(function() { ok(true); start(); }, 125); }); QUnit.test("test synchronous calls to stop", 2, function() { stop(); setTimeout(function() { ok(true, 'first'); start(); stop(); setTimeout(function() { ok(true, 'second'); start(); }, 150); }, 150); }); } QUnit.module("save scope", { setup: function() { this.foo = "bar"; }, teardown: function() { deepEqual(this.foo, "bar"); } }); test("scope check", function() { expect(2); deepEqual(this.foo, "bar"); }); QUnit.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"); }); QUnit.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") ; }); QUnit.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'); }); QUnit.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'); }); QUnit.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]" ); } }); QUnit.module("assertions"); QUnit.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' ); }); QUnit.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 Error(); }, Error, 'thrown error is an instance of CustomError' ); throws( function() { throw new Error("some error description"); }, /description/, "use a regex to match against the stringified error" ); throws( function() { throw new Error("some error description"); }, function( err ) { if ( (err instanceof Error) && /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 = {}; 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") { QUnit.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 ); }; QUnit.module("timing", { setup: function() { if ( delayNextSetup ) { delayNextSetup = false; sleep( 250 ); } } }); QUnit.test("setup", 0, function() { delayNextSetup = true; }); var getPreviousTests: (...args: any[]) => any; QUnit.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" ); }); QUnit.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" ); }); })(); } QUnit.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"); }); })(); QUnit.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: any = {}; 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; QUnit.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 coun