From 437beae64e072dbbb3b2df26831a39d684783c63 Mon Sep 17 00:00:00 2001 From: Jaap Rood Date: Wed, 2 May 2018 15:30:04 +1000 Subject: [PATCH] Define tests for how mergeDeep would work for Model --- test/model.js | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/test/model.js b/test/model.js index a00e6fd..39358b3 100644 --- a/test/model.js +++ b/test/model.js @@ -419,3 +419,115 @@ Test('model.merge', function(t) { }, 'accepts a base and source instance with a different state type') }) +Test('model.mergeDeep', function(t) { + t.plan(3 + 8) + + const OtherModel = Model.create({ + typeName: 'woo' + }) + + + const existingA = 'a' + const existingB = 'b' + const existingC = 'c' + + const inputA = '1'; + const inputB = '2'; + + const outputA = 'a1'; + const outputB = 'b2'; + const outputC = 'c3'; + + const schema = { + a: { + mergeDeep(existing, value, options) { + t.equal(existing, existingA, 'mergeDeep of type is called with the current value as first argument') + t.equal(value, inputA, 'mergeDeep of type is called with the to be merged value as the second argument') + t.ok(_.isPlainObject(options), 'mergeDeep of type is valled with the options passed to serialize') + + return outputA + } + }, + nested: { + b: { + mergeDeep: () => outputB + } + }, + multiple: [{ + mergeDeep: () => outputC + }], + nestedModel: OtherModel, + notInstance: { + mergeDeep() { return 'never seen' }, + instanceOf() { return false } + }, + notIncluded: { + mergeDeep() { + t.fail('not included properties should not be called') + } + }, + + nestedList: Schema.listOf({ + factory: (val) => val + }), + + nestedSet: Schema.setOf({ + factory: (val) => val + }), + + nestedOrderedSet: Schema.orderedSetOf({ + factory: (val) => val + }) + } + + const TestModel = Model.create({ + typeName: 'test-model', + schema: schema + }) + + const existing = TestModel.factory({ + a: existingA, + nested: { + b: existingB + }, + nestedModel: { + 'a': existingA, + 'b': existingB + }, + notInstance: 'not-what-we-expect-it-to-be', + notTouched: existingA, + + multiple: ['values', 'array'], + + nestedList: [existingA, existingB], + nestedSet: [existingA, existingB], + nestedOrderedSet: [existingC, existingB, existingA] + }) + + t.doesNotThrow(function() { + const merged = TestModel.mergeDeep(existing, { + a: inputA, + nested: { + b: inputB + }, + nestedModel: { + 'a': 'aaa', + 'b': 'bbb' + }, + notInstance: 'wicked', + nestedList: [outputA, outputB], + nestedSet: [outputA, outputB], + nestedOrderedSet: [outputC, outputB, outputA] + }) + + t.equal(merged.get('a'), outputA, 'value returned by mergeDeep of schema is used as value') + t.equal(merged.getIn(['nested', 'b']), outputB, 'nested schema is applied to nested attributes') + t.ok(OtherModel.instanceOf(merged.get('nestedModel')), 'Model definitions are valid type definitions for merging deep') + t.equal(merged.get('notInstance'), existing.get('notInstance'), 'mergeDeep of schema definition not applied when schema has instanceOf method that returns falsey') + + t.ok(Immutable.List([outputA, outputB]).equals(merged.get('nestedList')), 'schema generated with `Schema.listOf` return only the new values as Lists merging is ambiguous') + t.ok(Immutable.Set([outputA, outputB]).equals(merged.get('nestedSet')), 'schema generated with `Schema.setOf` return only then new values as Sets merging is ambiguous') + t.ok(Immutable.OrderedSet([outputC, outputB, outputA]).equals(merged.get('nestedOrderedSet')), 'schema generated with `Schema.orderedSetOf` return only then ew value as OrderedSets merging is ambiguous') + }, 'accepts a Model instance and a mergable data') +}) +