michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: // Test cases borrowed and adapted from: michael@0: // https://github.com/joyent/node/blob/6101eb184db77d0b11eb96e48744e57ecce4b73d/test/simple/test-assert.js michael@0: // MIT license: http://opensource.org/licenses/MIT michael@0: michael@0: function run_test() { michael@0: let ns = {}; michael@0: Components.utils.import("resource://testing-common/Assert.jsm", ns); michael@0: let assert = new ns.Assert(); michael@0: michael@0: function makeBlock(f, ...args) { michael@0: return function() { michael@0: return f.apply(assert, args); michael@0: }; michael@0: } michael@0: michael@0: function protoCtrChain(o) { michael@0: let result = []; michael@0: while (o = o.__proto__) { michael@0: result.push(o.constructor); michael@0: } michael@0: return result.join(); michael@0: } michael@0: michael@0: function indirectInstanceOf(obj, cls) { michael@0: if (obj instanceof cls) { michael@0: return true; michael@0: } michael@0: let clsChain = protoCtrChain(cls.prototype); michael@0: let objChain = protoCtrChain(obj); michael@0: return objChain.slice(-clsChain.length) === clsChain; michael@0: }; michael@0: michael@0: assert.ok(indirectInstanceOf(ns.Assert.AssertionError.prototype, Error), michael@0: "Assert.AssertionError instanceof Error"); michael@0: michael@0: assert.throws(makeBlock(assert.ok, false), michael@0: ns.Assert.AssertionError, "ok(false)"); michael@0: michael@0: assert.ok(true, "ok(true)"); michael@0: michael@0: assert.ok("test", "ok('test')"); michael@0: michael@0: assert.throws(makeBlock(assert.equal, true, false), ns.Assert.AssertionError, "equal"); michael@0: michael@0: assert.equal(null, null, "equal"); michael@0: michael@0: assert.equal(undefined, undefined, "equal"); michael@0: michael@0: assert.equal(null, undefined, "equal"); michael@0: michael@0: assert.equal(true, true, "equal"); michael@0: michael@0: assert.notEqual(true, false, "notEqual"); michael@0: michael@0: assert.throws(makeBlock(assert.notEqual, true, true), michael@0: ns.Assert.AssertionError, "notEqual"); michael@0: michael@0: assert.throws(makeBlock(assert.strictEqual, 2, "2"), michael@0: ns.Assert.AssertionError, "strictEqual"); michael@0: michael@0: assert.throws(makeBlock(assert.strictEqual, null, undefined), michael@0: ns.Assert.AssertionError, "strictEqual"); michael@0: michael@0: assert.notStrictEqual(2, "2", "notStrictEqual"); michael@0: michael@0: // deepEquals joy! michael@0: // 7.2 michael@0: assert.deepEqual(new Date(2000, 3, 14), new Date(2000, 3, 14), "deepEqual date"); michael@0: michael@0: assert.throws(makeBlock(assert.deepEqual, new Date(), new Date(2000, 3, 14)), michael@0: ns.Assert.AssertionError, michael@0: "deepEqual date"); michael@0: michael@0: // 7.3 michael@0: assert.deepEqual(/a/, /a/); michael@0: assert.deepEqual(/a/g, /a/g); michael@0: assert.deepEqual(/a/i, /a/i); michael@0: assert.deepEqual(/a/m, /a/m); michael@0: assert.deepEqual(/a/igm, /a/igm); michael@0: assert.throws(makeBlock(assert.deepEqual, /ab/, /a/)); michael@0: assert.throws(makeBlock(assert.deepEqual, /a/g, /a/)); michael@0: assert.throws(makeBlock(assert.deepEqual, /a/i, /a/)); michael@0: assert.throws(makeBlock(assert.deepEqual, /a/m, /a/)); michael@0: assert.throws(makeBlock(assert.deepEqual, /a/igm, /a/im)); michael@0: michael@0: let re1 = /a/; michael@0: re1.lastIndex = 3; michael@0: assert.throws(makeBlock(assert.deepEqual, re1, /a/)); michael@0: michael@0: // 7.4 michael@0: assert.deepEqual(4, "4", "deepEqual == check"); michael@0: assert.deepEqual(true, 1, "deepEqual == check"); michael@0: assert.throws(makeBlock(assert.deepEqual, 4, "5"), michael@0: ns.Assert.AssertionError, michael@0: "deepEqual == check"); michael@0: michael@0: // 7.5 michael@0: // having the same number of owned properties && the same set of keys michael@0: assert.deepEqual({a: 4}, {a: 4}); michael@0: assert.deepEqual({a: 4, b: "2"}, {a: 4, b: "2"}); michael@0: assert.deepEqual([4], ["4"]); michael@0: assert.throws(makeBlock(assert.deepEqual, {a: 4}, {a: 4, b: true}), michael@0: ns.Assert.AssertionError); michael@0: assert.deepEqual(["a"], {0: "a"}); michael@0: michael@0: let a1 = [1, 2, 3]; michael@0: let a2 = [1, 2, 3]; michael@0: a1.a = "test"; michael@0: a1.b = true; michael@0: a2.b = true; michael@0: a2.a = "test"; michael@0: assert.throws(makeBlock(assert.deepEqual, Object.keys(a1), Object.keys(a2)), michael@0: ns.Assert.AssertionError); michael@0: assert.deepEqual(a1, a2); michael@0: michael@0: let nbRoot = { michael@0: toString: function() { return this.first + " " + this.last; } michael@0: }; michael@0: michael@0: function nameBuilder(first, last) { michael@0: this.first = first; michael@0: this.last = last; michael@0: return this; michael@0: } michael@0: nameBuilder.prototype = nbRoot; michael@0: michael@0: function nameBuilder2(first, last) { michael@0: this.first = first; michael@0: this.last = last; michael@0: return this; michael@0: } michael@0: nameBuilder2.prototype = nbRoot; michael@0: michael@0: let nb1 = new nameBuilder("Ryan", "Dahl"); michael@0: let nb2 = new nameBuilder2("Ryan", "Dahl"); michael@0: michael@0: assert.deepEqual(nb1, nb2); michael@0: michael@0: nameBuilder2.prototype = Object; michael@0: nb2 = new nameBuilder2("Ryan", "Dahl"); michael@0: assert.throws(makeBlock(assert.deepEqual, nb1, nb2), ns.Assert.AssertionError); michael@0: michael@0: // String literal + object michael@0: assert.throws(makeBlock(assert.deepEqual, "a", {}), ns.Assert.AssertionError); michael@0: michael@0: // Testing the throwing michael@0: function thrower(errorConstructor) { michael@0: throw new errorConstructor("test"); michael@0: } michael@0: let aethrow = makeBlock(thrower, ns.Assert.AssertionError); michael@0: aethrow = makeBlock(thrower, ns.Assert.AssertionError); michael@0: michael@0: // the basic calls work michael@0: assert.throws(makeBlock(thrower, ns.Assert.AssertionError), michael@0: ns.Assert.AssertionError, "message"); michael@0: assert.throws(makeBlock(thrower, ns.Assert.AssertionError), ns.Assert.AssertionError); michael@0: assert.throws(makeBlock(thrower, ns.Assert.AssertionError)); michael@0: michael@0: // if not passing an error, catch all. michael@0: assert.throws(makeBlock(thrower, TypeError)); michael@0: michael@0: // when passing a type, only catch errors of the appropriate type michael@0: let threw = false; michael@0: try { michael@0: assert.throws(makeBlock(thrower, TypeError), ns.Assert.AssertionError); michael@0: } catch (e) { michael@0: threw = true; michael@0: assert.ok(e instanceof TypeError, "type"); michael@0: } michael@0: assert.equal(true, threw, michael@0: "Assert.throws with an explicit error is eating extra errors", michael@0: ns.Assert.AssertionError); michael@0: threw = false; michael@0: michael@0: function ifError(err) { michael@0: if (err) { michael@0: throw err; michael@0: } michael@0: } michael@0: assert.throws(function() { michael@0: ifError(new Error("test error")); michael@0: }); michael@0: michael@0: // make sure that validating using constructor really works michael@0: threw = false; michael@0: try { michael@0: assert.throws( michael@0: function() { michael@0: throw ({}); michael@0: }, michael@0: Array michael@0: ); michael@0: } catch (e) { michael@0: threw = true; michael@0: } michael@0: assert.ok(threw, "wrong constructor validation"); michael@0: michael@0: // use a RegExp to validate error message michael@0: assert.throws(makeBlock(thrower, TypeError), /test/); michael@0: michael@0: // use a fn to validate error object michael@0: assert.throws(makeBlock(thrower, TypeError), function(err) { michael@0: if ((err instanceof TypeError) && /test/.test(err)) { michael@0: return true; michael@0: } michael@0: }); michael@0: michael@0: // Make sure deepEqual doesn't loop forever on circular refs michael@0: michael@0: let b = {}; michael@0: b.b = b; michael@0: michael@0: let c = {}; michael@0: c.b = c; michael@0: michael@0: let gotError = false; michael@0: try { michael@0: assert.deepEqual(b, c); michael@0: } catch (e) { michael@0: gotError = true; michael@0: } michael@0: michael@0: dump("All OK\n"); michael@0: assert.ok(gotError); michael@0: michael@0: function testAssertionMessage(actual, expected) { michael@0: try { michael@0: assert.equal(actual, ""); michael@0: } catch (e) { michael@0: assert.equal(e.toString(), michael@0: ["AssertionError:", expected, "==", '""'].join(" ")); michael@0: } michael@0: } michael@0: testAssertionMessage(undefined, '"undefined"'); michael@0: testAssertionMessage(null, "null"); michael@0: testAssertionMessage(true, "true"); michael@0: testAssertionMessage(false, "false"); michael@0: testAssertionMessage(0, "0"); michael@0: testAssertionMessage(100, "100"); michael@0: testAssertionMessage(NaN, '"NaN"'); michael@0: testAssertionMessage(Infinity, '"Infinity"'); michael@0: testAssertionMessage(-Infinity, '"-Infinity"'); michael@0: testAssertionMessage("", '""'); michael@0: testAssertionMessage("foo", '"foo"'); michael@0: testAssertionMessage([], "[]"); michael@0: testAssertionMessage([1, 2, 3], "[1,2,3]"); michael@0: testAssertionMessage(/a/, '"/a/"'); michael@0: testAssertionMessage(/abc/gim, '"/abc/gim"'); michael@0: testAssertionMessage(function f() {}, '"function f() {}"'); michael@0: testAssertionMessage({}, "{}"); michael@0: testAssertionMessage({a: undefined, b: null}, '{"a":"undefined","b":null}'); michael@0: testAssertionMessage({a: NaN, b: Infinity, c: -Infinity}, michael@0: '{"a":"NaN","b":"Infinity","c":"-Infinity"}'); michael@0: michael@0: // https://github.com/joyent/node/issues/2893 michael@0: try { michael@0: assert.throws(function () { michael@0: ifError(null); michael@0: }); michael@0: } catch (e) { michael@0: threw = true; michael@0: assert.equal(e.message, "Missing expected exception.."); michael@0: } michael@0: assert.ok(threw); michael@0: michael@0: // https://github.com/joyent/node/issues/5292 michael@0: try { michael@0: assert.equal(1, 2); michael@0: } catch (e) { michael@0: assert.equal(e.toString().split("\n")[0], "AssertionError: 1 == 2") michael@0: } michael@0: michael@0: try { michael@0: assert.equal(1, 2, "oh no"); michael@0: } catch (e) { michael@0: assert.equal(e.toString().split("\n")[0], "AssertionError: oh no - 1 == 2") michael@0: } michael@0: michael@0: // Export Assert.jsm methods to become globally accessible. michael@0: export_assertions(); michael@0: michael@0: // Test XPCShell-test integration: michael@0: ok(true, "OK, this went well"); michael@0: deepEqual(/a/g, /a/g, "deep equal should work on RegExp"); michael@0: deepEqual(/a/igm, /a/igm, "deep equal should work on RegExp"); michael@0: deepEqual({a: 4, b: "1"}, {b: "1", a: 4}, "deep equal should work on regular Object"); michael@0: deepEqual(a1, a2, "deep equal should work on Array with Object properties"); michael@0: michael@0: // Test robustness of reporting: michael@0: equal(new ns.Assert.AssertionError({ michael@0: actual: { michael@0: toJSON: function() { michael@0: throw "bam!"; michael@0: } michael@0: }, michael@0: expected: "foo", michael@0: operator: "=" michael@0: }).message, "[object Object] = \"foo\""); michael@0: }