diff --git a/src/registry.js b/src/registry.js index ed28ded..e7c69ea 100644 --- a/src/registry.js +++ b/src/registry.js @@ -10,22 +10,30 @@ module.exports = function createRegistry() { _types: new Map(), _traits: new Map(), createType: function (name, schema, options = {}) { - let combinedOptions = Object.assign({ - _registry: this - }, options); + if (!this._types.has(name)) { + let combinedOptions = Object.assign({ + _registry: this + }, options); - let type = moduleAPI.createType(name, schema, combinedOptions); - this._types.set(name, type); - return type; + let type = moduleAPI.createType(name, schema, combinedOptions); + this._types.set(name, type); + return type; + } else { + throw new Error(`A type named ${name} already exists in this registry`); + } }, createTrait: function (name, schema, options = {}) { - let combinedOptions = Object.assign({ - _registry: this - }, options); + if (!this._traits.has(name)) { + let combinedOptions = Object.assign({ + _registry: this + }, options); - let trait = moduleAPI.createTrait(name, schema, combinedOptions); - this._traits.set(name, trait); - return trait; + let trait = moduleAPI.createTrait(name, schema, combinedOptions); + this._traits.set(name, trait); + return trait; + } else { + throw new Error(`A trait named ${name} already exists in this registry`); + } }, guardFunction: function (args, returnType, func) { return moduleAPI.guardFunction(args, returnType, func, this); diff --git a/test/registry.js b/test/registry.js index e7bd790..d43f461 100644 --- a/test/registry.js +++ b/test/registry.js @@ -77,31 +77,31 @@ describe("registry", () => { it("should work correctly for traits", () => { let Givable = registry.createTrait("Givable", { - from: registry.type("Person"), - to: registry.type("Person") + from: registry.type("AlsoPerson"), + to: registry.type("AlsoPerson") }); - let Person = registry.createType("Person", { + let AlsoPerson = registry.createType("AlsoPerson", { name: dm.string(), favouriteGift: registry.trait("Givable").optional() }); - let Gift = registry.createType("Gift", { + let AlsoGift = registry.createType("AlsoGift", { description: dm.string() }).implements(Givable, { from: dm.slot(), to: dm.slot() }); - let joe = Person({ + let joe = AlsoPerson({ name: "Joe" }); - let jane = Person({ + let jane = AlsoPerson({ name: "Jane" }); - let flowers = Gift({ + let flowers = AlsoGift({ description: "Flowers", from: jane, to: joe @@ -119,11 +119,11 @@ describe("registry", () => { expect(() => { flowers.to = "not a person"; - }).to.throw("Expected an instance of Person, got a string instead"); + }).to.throw("Expected an instance of AlsoPerson, got a string instead"); expect(() => { flowers.to = flowers; - }).to.throw("Expected an instance of Person, got an instance of Gift instead"); + }).to.throw("Expected an instance of AlsoPerson, got an instance of AlsoGift instead"); }); it("should work correctly for type aliases", () => { @@ -147,20 +147,20 @@ describe("registry", () => { }); it("should work correctly for guarded maps and sets", () => { - let SomeType = registry.createType("SomeType", { + let SomeNewType = registry.createType("SomeNewType", { value: dm.string() }); let SomeOtherType = registry.createType("SomeOtherType", { - things: dm.setOf(registry.type("SomeType")), - thingsMap: dm.mapOf(dm.string(), registry.type("SomeType")) + things: dm.setOf(registry.type("SomeNewType")), + thingsMap: dm.mapOf(dm.string(), registry.type("SomeNewType")) }); - let thingOne = SomeType({ + let thingOne = SomeNewType({ value: "one" }); - let thingTwo = SomeType({ + let thingTwo = SomeNewType({ value: "two" }); @@ -186,7 +186,7 @@ describe("registry", () => { ["two", thingTwo] ]) }); - }).to.throw("Expected an instance of SomeType, got a string instead"); + }).to.throw("Expected an instance of SomeNewType, got a string instead"); expect(() => { SomeOtherType({ @@ -199,7 +199,23 @@ describe("registry", () => { ["two", "things"] ]) }); - }).to.throw("Expected an instance of SomeType, got a string instead"); + }).to.throw("Expected an instance of SomeNewType, got a string instead"); + }); + + it("should reject duplicate type registrations", () => { + registry.createType("DuplicateType", {}); + + expect(() => { + registry.createType("DuplicateType", {}); + }).to.throw("A type named DuplicateType already exists in this registry"); + }); + + it("should reject duplicate trait registrations", () => { + registry.createTrait("DuplicateTrait", {}); + + expect(() => { + registry.createTrait("DuplicateTrait", {}); + }).to.throw("A trait named DuplicateTrait already exists in this registry"); }); }); });