diff options
Diffstat (limited to 'tools/addon-sdk-1.7/packages/api-utils/tests/traits/descriptor-tests.js')
-rw-r--r-- | tools/addon-sdk-1.7/packages/api-utils/tests/traits/descriptor-tests.js | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.7/packages/api-utils/tests/traits/descriptor-tests.js b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/descriptor-tests.js new file mode 100644 index 0000000..b775ff4 --- /dev/null +++ b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/descriptor-tests.js @@ -0,0 +1,335 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +var Trait = require("light-traits").Trait; +var utils = require("./utils"); +var Data = utils.Data; +var Method = utils.Method; +var Accessor = utils.Accessor; +var Required = utils.Required; +var Conflict = utils.Conflict; + +function method() {} + +exports.Assert = require("./assert").Assert +exports["test simple composition"] = function(assert) { + var actual = Trait.compose( + Trait({ a: 0, b: 1 }), + { c: { value: 2 }, d: { value: method, enumerable: true } } + ); + + var expected = { + a: Data(0), + b: Data(1), + c: Data(2, false, false, false), + d: Method(method, true, false, false) + }; + + assert.equalTraits(actual, expected); +}; + +exports["test composition with conflict"] = function(assert) { + var actual = Trait.compose( + Trait({ a: 0, b: 1 }), + { + a: { + value: 2, + writable: true, + configurable: true, + enumerable: true + }, + c: { + value: method, + configurable: true + } + } + ); + + var expected = { + a: Conflict("a"), + b: Data(1), + c: Method(method, false, true, false) + }; + + assert.equalTraits(actual, expected); +}; + +exports["test identical props does not cause conflict"] = function(assert) { + var actual = Trait.compose( + { + a: { + value: 0, + writable: true, + configurable: true, + enumerable: true + }, + b: { + value: 1 + } + }, + Trait({ + a: 0, + c: method + }) + ); + + var expected = { + a: Data(0), + b: Data(1, false, false, false), + c: Method(method) + } + + assert.equalTraits(actual, expected); +}; + +exports["test composition with identical required props"] = function(assert) { + var actual = Trait.compose( + Trait({ a: Trait.required, b: 1 }), + { a: { required: true }, c: { value: method } } + ); + + var expected = { + a: Required(), + b: Data(1), + c: Method(method, false, false, false) + }; + + assert.equalTraits(actual, expected); +}; + +exports["test composition satisfying a required prop"] = function(assert) { + var actual = Trait.compose( + Trait({ a: Trait.required, b: 1 }), + { a: { value: method, enumerable: true } } + ); + + var expected = { + a: Method(method, true, false, false), + b: Data(1) + }; + + assert.equalTraits(actual, expected); +}; + +exports["test compose is neutral wrt conflicts"] = function(assert) { + var actual = Trait.compose( + Trait({ a: { value: 1 } }, Trait({ a: 2 })), + { b: { value: 0, writable: true, configurable: true, enumerable: false } } + ); + + var expected = { a: Conflict("a"), b: Data(0, false) }; + + assert.equalTraits(actual, expected); +}; + +exports["test conflicting prop overrides Trait.required"] = function(assert) { + var actual = Trait.compose( + Trait.compose( + Trait({ a: 1 }), + { a: { value: 2 } } + ), + { a: { value: Trait.required } } + ); + + var expected = { a: Conflict("a") }; + + assert.equalTraits(actual, expected); +}; + +exports["test compose is commutative"] = function(assert) { + var actual = Trait.compose( + Trait({ a: 0, b: 1 }), + { c: { value: 2 }, d: { value: method } } + ); + + var expected = Trait.compose( + { c: { value: 2 }, d: { value: method } }, + Trait({ a: 0, b: 1 }) + ); + + assert.equalTraits(actual, expected); +} + +exports["test compose is commutative, also for required/conflicting props"] = function(assert) { + var actual = Trait.compose( + { + a: { value: 0 }, + b: { value: 1 }, + c: { value: 3 }, + e: { value: Trait.required } + }, + { + c: { value: 2 }, + d: { get: method } + } + ); + + var expected = Trait.compose( + Trait({ c: 3 }), + { + c: { value: 2 }, + d: { get: method }, + a: { value: 0 }, + b: { value: 1 }, + e: { value: Trait.required }, + } + ); + + assert.equalTraits(actual, expected); +}; + +exports["test compose is associative"] = function(assert) { + var actual = Trait.compose( + { + a: { value: 0 }, + b: { value: 1 }, + c: { value: 3 }, + d: { value: Trait.required } + }, + Trait.compose( + { c: { value: 3 }, d: { value: Trait.required } }, + { c: { value: 2 }, d: { value: method }, e: { value: "foo" } } + ) + ); + + var expected = Trait.compose( + Trait.compose( + { + a: { value: 0 }, + b: { value: 1 }, + c: { value: 3 }, + d: { value: Trait.required } + }, + { + c: { value: 3 }, + d: { value: Trait.required } + } + ), + { + c: { value: 2 }, + d: { value: method }, + e: { value: "foo" } + } + ); + + assert.equalTraits(actual, expected); +}; + +exports["test diamond import of same prop do not conflict"] = function(assert) { + var actual = Trait.compose( + Trait.compose( + { b: { value: 2 } }, + { a: { value: 1, enumerable: true, configurable: true, writable: true } } + ), + Trait.compose( + { c: { value: 3 } }, + Trait({ a: 1 }) + ), + Trait({ d: 4 }) + ); + + var expected = { + a: Data(1), + b: Data(2, false, false, false), + c: Data(3, false, false, false), + d: Data(4) + }; + + assert.equalTraits(actual, expected); +}; + +exports["test create simple"] = function(assert) { + var o1 = Trait.compose( + Trait({ a: 1 }), + { + b: { + value: function() { + return this.a; + } + } + } + ).create(Object.prototype); + + assert.equal(Object.getPrototypeOf(o1), Object.prototype, "o1 prototype"); + assert.equal(1, o1.a, "o1.a"); + assert.equal(1, o1.b(), "o1.b()"); + assert.equal(Object.keys(o1).length, 1, "Object.keys(o1).length === 2"); +}; + +exports["test create with Array.prototype"] = function(assert) { + var o2 = Trait.compose({}, {}).create(Array.prototype); + assert.equal(Object.getPrototypeOf(o2), Array.prototype, "o2 prototype"); +}; + +exports["test exception for incomplete required properties"] = function(assert) { + assert.throws(function() { + Trait({ foo: Trait.required }).create(Object.prototype) + }, /Missing required property: `foo`/, "required prop error"); +} + +exports["test exception for unresolved conflicts"] = function(assert) { + assert.throws(function() { + Trait(Trait({ a: 0 }), Trait({ a: 1 })).create({}) + }, /Remaining conflicting property: `a`/, "conflicting prop error"); +} + +exports["test conflicting properties are present"] = function(assert) { + var o5 = Object.create(Object.prototype, Trait.compose( + { a: { value: 0 } }, + { a: { value: 1 } } + )); + + assert.ok("a" in o5, "conflicting property present"); + assert.throws(function() { + o5.a + }, /Remaining conflicting property: `a`/, "conflicting prop access error"); +}; + +exports["test diamond with conflicts"] = function(assert) { + function makeT1(x) { + return { + m: { + value: function() { + return x + } + } + }; + }; + + function makeT2(x) { + return Trait.compose( + Trait({ t2: "foo" }), + makeT1(x) + ); + }; + + function makeT3(x) { + return Trait.compose( + { + t3: { value: "bar" } + }, + makeT1(x) + ); + }; + + var T4 = Trait.compose(makeT2(5), makeT3(5)); + + assert.throws(function() { + T4.create(Object.prototype); + }, /Remaining conflicting property: `m`/, "diamond prop conflict"); +}; + +exports["test providing requirements through proto"] = function(assert) { + var t = Trait.compose( + {}, + { required: { required: true } } + ).create({ required: "test" }); + + assert.equal(t.required, "test", "property from proto is inherited"); +}; + +if (module == require.main) + require("test").run(exports); |