From 7819656e2a20409175af59c095ae75174c7b5d54 Mon Sep 17 00:00:00 2001 From: Sylvain Pollet-Villard Date: Fri, 15 Jun 2018 20:50:00 +0200 Subject: [PATCH] check if instance of object in objectmodel constructor, fixes #74 --- src/object-model.js | 4 ++++ test/object-model.spec.js | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/object-model.js b/src/object-model.js index e923aa1..2064e46 100644 --- a/src/object-model.js +++ b/src/object-model.js @@ -381,6 +381,10 @@ export function ObjectModel(def, params) { if (!is(model, instance)) return new model(obj) if (is(model, obj)) return obj + if(!is(Object, obj) && obj !== undefined){ + stackError(model.errors, Object, obj); + } + merge(instance, model[_constructor](obj), true) if (!model.validate(instance)) return return getProxy(model, instance, model.definition) diff --git a/test/object-model.spec.js b/test/object-model.spec.js index 19b4a48..928c254 100644 --- a/test/object-model.spec.js +++ b/test/object-model.spec.js @@ -169,6 +169,23 @@ QUnit.test("behaviour for properties", function (assert) { QUnit.test("edge cases of constructors", function (assert) { assert.ok(ObjectModel({}) instanceof ObjectModel, "ObjectModel can receive empty object as argument"); + const M = ObjectModel({}) + assert.strictEqual(M.test(undefined), true, "undefined is valid for empty objectmodels, due to null-safe object traversal") + assert.strictEqual(M.test(null), false, "null is invalid for empty objectmodels") + assert.strictEqual(M.test(1), false, "number is invalid for empty objectmodels") + assert.strictEqual(M.test(new Number(1)), true, "Numbers through constructor are valid for empty objectmodels") + assert.strictEqual(M.test("string"), false, "string is invalid for empty objectmodels") + assert.strictEqual(M.test(function(){}), true, "function is valid for empty objectmodels") + + const O = ObjectModel({ x: [ Number ]}) + assert.strictEqual(O.test(undefined), true, "undefined is valid for optional objectmodels, due to null-safe object traversal") + assert.strictEqual(O.test(null), false, "null is invalid for optional objectmodels") + assert.strictEqual(O.test(1), false, "number is invalid for optional objectmodels") + assert.strictEqual(O.test(new Number(1)), true, "Numbers through constructor are valid for optional objectmodels") + assert.strictEqual(O.test("string"), false, "string is invalid for optional objectmodels") + assert.strictEqual(O.test(function(){}), true, "function is valid for optional objectmodels") + + /* //TODO: use FunctionModel for ObjectModel API ? assert.throws(function () { ObjectModel(undefined) @@ -303,6 +320,21 @@ QUnit.test("default values", function (assert) { assert.strictEqual(model2.name, "jim", "defaults values not applied if provided"); assert.strictEqual(model2.foo.bar.buz, 1, "defaults nested props values not applied if provided"); + const Person = Model({ + name: String, + age: [Number] + }).defaults({ + name: "new-name" + }); + + const Team = Model({ + lead: Person, + members: ArrayModel(Person) + }); + + assert.strictEqual((new Team({ lead: new Person(), members:[] })).lead.name, "new-name", "default value through composition") + assert.throws(() => { new Team({ lead: 1, members:[] })}, "invalid value through composition with default") + }); QUnit.test("defaultTo with defaults", function (assert) { @@ -1255,7 +1287,7 @@ QUnit.test("Null-safe object traversal", function (assert) { const config = Config({ local: undefined }); // object duck typed - assert.equal(config.local.time.format, undefined, "null-safe object traversal getter") + assert.strictEqual(config.local.time.format, undefined, "null-safe object traversal getter") config.local.time.format = "12h"; - assert.equal(config.local.time.format, "12h", "null-safe object traversal setter") + assert.strictEqual(config.local.time.format, "12h", "null-safe object traversal setter") }) \ No newline at end of file