aboutsummaryrefslogtreecommitdiff
path: root/tools/addon-sdk-1.7/packages/api-utils/tests/traits
diff options
context:
space:
mode:
Diffstat (limited to 'tools/addon-sdk-1.7/packages/api-utils/tests/traits')
-rw-r--r--tools/addon-sdk-1.7/packages/api-utils/tests/traits/assert.js98
-rw-r--r--tools/addon-sdk-1.7/packages/api-utils/tests/traits/descriptor-tests.js335
-rw-r--r--tools/addon-sdk-1.7/packages/api-utils/tests/traits/inheritance-tests.js104
-rw-r--r--tools/addon-sdk-1.7/packages/api-utils/tests/traits/object-tests.js321
-rw-r--r--tools/addon-sdk-1.7/packages/api-utils/tests/traits/utils.js56
5 files changed, 914 insertions, 0 deletions
diff --git a/tools/addon-sdk-1.7/packages/api-utils/tests/traits/assert.js b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/assert.js
new file mode 100644
index 0000000..7c385e4
--- /dev/null
+++ b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/assert.js
@@ -0,0 +1,98 @@
+/* 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 BaseAssert = require("test/assert").Assert;
+
+/**
+ * Whether or not given property descriptors are equivalent. They are
+ * equivalent either if both are marked as "conflict" or "required" property
+ * or if all the properties of descriptors are equal.
+ * @param {Object} actual
+ * @param {Object} expected
+ */
+function equivalentDescriptors(actual, expected) {
+ return (actual.conflict && expected.conflict) ||
+ (actual.required && expected.required) ||
+ equalDescriptors(actual, expected);
+}
+
+function equalDescriptors(actual, expected) {
+ return actual.get === expected.get &&
+ actual.set === expected.set &&
+ actual.value === expected.value &&
+ !!actual.enumerable === !!expected.enumerable &&
+ !!actual.configurable === !!expected.configurable &&
+ !!actual.writable === !!expected.writable;
+}
+
+/**
+ * Whether or not given `target` array contains all the element
+ * from a given `source` array.
+ */
+function containsSet(source, target) {
+ return source.some(function(element) {
+ return 0 > target.indexOf(element);
+ });
+}
+
+/**
+ * Whether or not given two arrays contain all elements from another.
+ */
+function equivalentSets(source, target) {
+ return containsSet(source, target) && containsSet(target, source);
+}
+
+/**
+ * Finds name of the property from `source` property descriptor map, that
+ * is not equivalent of the name named property in the `target` property
+ * descriptor map. If not found `null` is returned instead.
+ */
+function findNonEquivalentPropertyName(source, target) {
+ var value = null;
+ Object.getOwnPropertyNames(source).some(function(key) {
+ var areEquivalent = false;
+ if (!equivalentDescriptors(source[key], target[key])) {
+ value = key;
+ areEquivalent = true;
+ }
+ return areEquivalent;
+ });
+ return value;
+}
+
+var AssertDescriptor = {
+ equalTraits: {
+ value: function equivalentTraits(actual, expected, message) {
+ var difference;
+ var actualKeys = Object.getOwnPropertyNames(actual);
+ var expectedKeys = Object.getOwnPropertyNames(expected);
+
+ if (equivalentSets(actualKeys, expectedKeys)) {
+ this.fail({
+ operator: "equalTraits",
+ message: "Traits define different properties",
+ actual: actualKeys.sort().join(","),
+ expected: expectedKeys.sort().join(","),
+ });
+ }
+ else if ((difference = findNonEquivalentPropertyName(actual, expected))) {
+ this.fail({
+ operator: "equalTraits",
+ message: "Traits define non-equivalent property `" + difference + "`",
+ actual: actual[difference],
+ expected: expected[difference]
+ });
+ }
+ else {
+ this.pass(message || "Traits are equivalent.");
+ }
+ }
+ }
+};
+
+exports.Assert = function Assert() {
+ return Object.create(BaseAssert.apply(null, arguments), AssertDescriptor);
+};
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);
diff --git a/tools/addon-sdk-1.7/packages/api-utils/tests/traits/inheritance-tests.js b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/inheritance-tests.js
new file mode 100644
index 0000000..3b311f9
--- /dev/null
+++ b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/inheritance-tests.js
@@ -0,0 +1,104 @@
+/* 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;
+
+exports["test custom constructor and inherited toString"] = function(assert) {
+ function Type() {
+ return Object.create(Type.prototype);
+ }
+ Type.prototype = Trait({
+ method: function method() {
+ return 2;
+ }
+ }).create(Object.freeze(Type.prototype));
+
+ var fixture = Type();
+
+ assert.equal(fixture.constructor, Type, "must override constructor");
+ assert.equal(fixture.toString(), "[object Type]", "must inherit toString");
+};
+
+exports["test custom toString and inherited constructor"] = function(assert) {
+ function Type() {
+ return Object.create(Type.prototype);
+ }
+ Type.prototype = Trait({
+ toString: function toString() {
+ return "<toString>";
+ }
+ }).create();
+
+ var fixture = Type();
+
+ assert.equal(fixture.constructor, Trait, "must inherit constructor Trait");
+ assert.equal(fixture.toString(), "<toString>", "Must override toString");
+};
+
+exports["test custom toString and constructor"] = function(assert) {
+ function Type() {
+ return TypeTrait.create(Type.prototype);
+ }
+ Object.freeze(Type.prototype);
+ var TypeTrait = Trait({
+ toString: function toString() {
+ return "<toString>";
+ }
+ });
+
+ var fixture = Type();
+
+ assert.equal(fixture.constructor, Type, "constructor is provided to create");
+ assert.equal(fixture.toString(), "<toString>", "toString was overridden");
+};
+
+exports["test resolve constructor"] = function (assert) {
+ function Type() {}
+ var T1 = Trait({ constructor: Type }).resolve({ constructor: '_foo' });
+ var f1 = T1.create();
+
+ assert.equal(f1._foo, Type, "constructor was resolved");
+ assert.equal(f1.constructor, Trait, "constructor of prototype is inherited");
+ assert.equal(f1.toString(), "[object Trait]", "toString is inherited");
+};
+
+exports["test compose read-only"] = function (assert) {
+ function Type() {}
+ Type.prototype = Trait.compose(Trait({}), {
+ constructor: { value: Type },
+ a: { value: "b", enumerable: true }
+ }).resolve({ a: "b" }).create({ a: "a" });
+
+ var f1 = new Type();
+
+ assert.equal(Object.getPrototypeOf(f1), Type.prototype, "inherits correctly");
+ assert.equal(f1.constructor, Type, "constructor was overridden");
+ assert.equal(f1.toString(), "[object Type]", "toString was inherited");
+ assert.equal(f1.a, "a", "property a was resolved");
+ assert.equal(f1.b, "b", "property a was renamed to b");
+ assert.ok(!Object.getOwnPropertyDescriptor(Type.prototype, "a"),
+ "a is not on the prototype of the instance");
+
+ var proto = Object.getPrototypeOf(Type.prototype);
+ var dc = Object.getOwnPropertyDescriptor(Type.prototype, "constructor");
+ var db = Object.getOwnPropertyDescriptor(Type.prototype, "b");
+ var da = Object.getOwnPropertyDescriptor(proto, "a");
+
+ assert.ok(!dc.writable, "constructor is not writable");
+ assert.ok(!dc.enumerable, "constructor is not enumerable");
+ assert.ok(dc.configurable, "constructor inherits configurability");
+
+ assert.ok(!db.writable, "a -> b is not writable");
+ assert.ok(db.enumerable, "a -> b is enumerable");
+ assert.ok(!db.configurable, "a -> b is not configurable");
+
+ assert.ok(da.writable, "a is writable");
+ assert.ok(da.enumerable, "a is enumerable");
+ assert.ok(da.configurable, "a is configurable");
+};
+
+if (require.main == module)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.7/packages/api-utils/tests/traits/object-tests.js b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/object-tests.js
new file mode 100644
index 0000000..6a94ff3
--- /dev/null
+++ b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/object-tests.js
@@ -0,0 +1,321 @@
+/* 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 empty trait"] = function (assert) {
+ assert.equalTraits(Trait({}), {});
+};
+
+exports["test simple trait"] = function (assert) {
+ var expected = {
+ a: Data(0, true, true, true),
+ b: Method(method, true, true, true)
+ };
+
+ assert.equalTraits(Trait({ a: 0, b: method }), expected);
+};
+
+exports["test simple trait with Trait.required property"] = function (assert) {
+ var actual = Trait({ a: Trait.required, b: 1 });
+ var expected = { a: Required("a"), b: Data(1) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test ordering of trait properties is irrelevant"] = function (assert) {
+ var actual = Trait({ a: 0, b: 1, c: Trait.required });
+ var expected = Trait({ b: 1, c: Trait.required, a: 0 });
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test trait with accessor property"] = function (assert) {
+ var record = { get a() {}, set a(v) {} };
+ var get = Object.getOwnPropertyDescriptor(record, "a").get;
+ var set = Object.getOwnPropertyDescriptor(record, "a").set;
+
+ assert.equalTraits(Trait(record), { a: Accessor(get, set) });
+};
+
+exports["test simple composition"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method }));
+ var expected = { a: Data(0), b: Data(1), c: Data(2), d: Method(method) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition with conflict"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 2, c: method }));
+ var expected = { a: Conflict("a"), b: Data(1), c: Method(method) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test composition of identical props does not cause conflict"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ a: 0, c: method }));
+
+ assert.equalTraits(actual, { a: Data(0), b: Data(1), c: Method(method) });
+};
+
+exports["test composition with identical Trait.required props"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }),
+ Trait({ a: Trait.required, c: method }));
+
+ assert.equalTraits(actual, { a: Required(), b: Data(1), c: Method(method) });
+};
+
+exports["test composition satisfying a Trait.required prop"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: Trait.required, b: 1 }),
+ Trait({ a: method }));
+
+ assert.equalTraits(actual, { a: Method(method), b: Data(1) });
+};
+
+exports["test compose is neutral wrt conflicts"] = function (assert) {
+ var actual = Trait.compose(Trait.compose(Trait({ a: 1 }), Trait({ a: 2 })),
+ Trait({ b: 0 }));
+
+ assert.equalTraits(actual, { a: Conflict("a"), b: Data(0) });
+};
+
+exports["test conflicting prop overrides Trait.required prop"] = function (assert) {
+ var actual = Trait.compose(Trait.compose(Trait({ a: 1 }),
+ Trait({ a: 2 })),
+ Trait({ a: Trait.required }));
+
+ assert.equalTraits(actual, { a: Conflict("a") });
+};
+
+exports["test compose is commutative"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1 }), Trait({ c: 2, d: method }));
+ var expected = Trait.compose(Trait({ c: 2, d: method }),
+ Trait({ a: 0, b: 1 }));
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is commutative, also for Trait.required/conflicting props"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, e: Trait.required }),
+ Trait({ c: 2, d: method }));
+
+ var expected = Trait.compose(Trait({ c: 2, d: method }),
+ Trait({ a: 0, b: 1, c: 3, e: Trait.required }));
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test compose is associative"] = function (assert) {
+ var actual = Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }),
+ Trait.compose(Trait({ c: 3, d: Trait.required }),
+ Trait({ c: 2, d: method,
+ e: "foo" })));
+
+ var expected = Trait.compose(
+ Trait.compose(Trait({ a: 0, b: 1, c: 3, d: Trait.required }),
+ Trait({ c: 3, d: Trait.required })),
+ Trait({ c: 2, d: method, e: "foo" }));
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test diamond import of same prop does not generate conflict"] = function (assert) {
+ var actual = Trait.compose(Trait.compose(Trait({ b: 2 }), Trait({ a: 1 })),
+ Trait.compose(Trait({ c: 3 }), Trait({ a: 1 })),
+ Trait({ d: 4 }));
+ var expected = { a: Data(1), b: Data(2), c: Data(3), d: Data(4) };
+
+ assert.equalTraits(actual, expected);
+};
+
+exports["test resolve with empty resolutions has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: Trait.required, c: method }).resolve({}),
+ { a: Data(1), b: Required(), c: Method(method) });
+};
+
+exports["test resolve: renaming"] = function (assert) {
+ var actual = Trait({ a: 1, b: Trait.required, c: method });
+
+ assert.equalTraits(actual.resolve({ a: "A", c: "C" }),
+ { A: Data(1), b: Required(), C: Method(method),
+ a: Required(), c: Required() });
+};
+
+exports["test resolve: renaming to conflicting name causes conflict, order 1"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b" }),
+ { b: Conflict("b"), a: Required() });
+};
+
+exports["test resolve: renaming to conflicting name causes conflict, order 2"] = function (assert) {
+ assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b" }),
+ { b: Conflict("b"), a: Required() });
+};
+
+exports["test resolve: simple exclusion"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined }),
+ { a: Required(), b: Data(2) });
+};
+
+exports["test resolve: exclusion to empty trait"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: null, b: undefined }),
+ { a: Required(), b: Required() });
+};
+
+exports["test resolve: exclusion and renaming of disjoint props"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "c" }),
+ { a: Required(), c: Data(2), b: Required() });
+};
+
+exports["test resolve: exclusion and renaming of overlapping props"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: undefined, b: "a" }),
+ { a: Data(2), b: Required() });
+};
+
+exports["test resolve: renaming to a common alias causes conflict"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", b: "c" }),
+ { c: Conflict("c"), a: Required(), b: Required() });
+};
+
+exports["test resolve: renaming overrides Trait.required target"] = function (assert) {
+ assert.equalTraits(Trait({ a: Trait.required, b: 2 }).resolve({ b: "a" }),
+ { a: Data(2), b: Required() });
+};
+
+exports["test resolve: renaming Trait.required properties has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 2, b: Trait.required }).resolve({ b: "a" }),
+ { a: Data(2), b: Required() });
+};
+
+exports["test resolve: renaming of non-existent props has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "c", d: "c" }),
+ { c: Data(1), b: Data(2), a: Required() });
+};
+
+exports["test resolve: exclusion of non-existent props has no effect"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1 }).resolve({ b: undefined }), { a: Data(1) });
+};
+
+exports["test resolve is neutral w.r.t. Trait.required properties"] = function (assert) {
+ var actual = Trait({ a: Trait.required, b: Trait.required, c: "foo", d: 1 });
+ var expected = { a: Required(), b: Required(), c: Data("foo"), d: Data(1) };
+ assert.equalTraits(actual.resolve({ a: "c", b: undefined }), expected);
+};
+
+exports["test resolve supports swapping of property names, ordering 1"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ a: "b", b: "a" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test resolve supports swapping of property names, ordering 2"] = function (assert) {
+ assert.equalTraits(Trait({ a: 1, b: 2 }).resolve({ b: "a", a: "b" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test resolve supports swapping of property names, ordering 3"] = function (assert) {
+ assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ b: "a", a: "b" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test resolve supports swapping of property names, ordering 4"] = function (assert) {
+ assert.equalTraits(Trait({ b: 2, a: 1 }).resolve({ a: "b", b: "a" }),
+ { a: Data(2), b: Data(1) });
+};
+
+exports["test create simple"] = function (assert) {
+ var o1 = Trait({
+ a: 1,
+ b: 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, 2, "Object.keys(o1).length === 2");
+};
+
+exports["test create with Array.prototype"] = function (assert) {
+ var o2 = Trait({}).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.compose(Trait({ a: 0 }), Trait({ a: 1 })).create({});
+ }, /Remaining conflicting property: `a`/, "conflicting prop error");
+};
+
+exports["test verify that required properties are present but undefined"] = function (assert) {
+ var o4 = Object.create(Object.prototype, Trait({ foo: Trait.required }));
+
+ assert.ok("foo" in o4, "required property present");
+ assert.throws(function () {
+ o4.foo;
+ }, /Missing required property: `foo`/, "required prop error");
+};
+
+exports["test verify that conflicting properties are present"] = function (assert) {
+ var o5 = Object.create(Object.prototype, Trait.compose(Trait({ a: 0 }),
+ Trait({ a: 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 Trait({
+ m: function () {
+ return x
+ }
+ })
+ };
+
+ function makeT2(x) {
+ return Trait.compose(Trait({
+ t2: "foo"
+ }), makeT1(x));
+ };
+
+ function makeT3(x) {
+ return Trait.compose(Trait({
+ t3: "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({ required: Trait.required }).create({ required: "test" });
+ assert.equal(t.required, "test", "property from proto is inherited");
+};
+
+if (module == require.main)
+ require("test").run(exports);
diff --git a/tools/addon-sdk-1.7/packages/api-utils/tests/traits/utils.js b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/utils.js
new file mode 100644
index 0000000..8426af7
--- /dev/null
+++ b/tools/addon-sdk-1.7/packages/api-utils/tests/traits/utils.js
@@ -0,0 +1,56 @@
+/* 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 ERR_CONFLICT = "Remaining conflicting property: ";
+var ERR_REQUIRED = "Missing required property: ";
+
+exports.Data = function Data(value, enumerable, configurable, writable) {
+ return ({
+ value: value,
+ enumerable: enumerable !== false,
+ configurable: configurable !== false,
+ writable: writable !== false
+ });
+};
+
+exports.Method = function Method(method, enumerable, configurable, writable) {
+ return ({
+ value: method,
+ enumerable: enumerable !== false,
+ configurable: configurable !== false,
+ writable: writable !== false
+ });
+};
+
+exports.Accessor = function Accessor(get, set, enumerable, configurable) {
+ return ({
+ get: get,
+ set: set,
+ enumerable: enumerable !== false,
+ configurable: configurable !== false
+ });
+};
+
+exports.Required = function Required(name) {
+ function required() { throw new Error(ERR_REQUIRED + name) }
+
+ return ({
+ get: required,
+ set: required,
+ required: true
+ });
+};
+
+exports.Conflict = function Conflict(name) {
+ function conflict() { throw new Error(ERR_CONFLICT + name) }
+
+ return ({
+ get: conflict,
+ set: conflict,
+ conflict: true
+ });
+};
+