Repository: js-data/js-data (js)

Issue:
deepMixIn merges in source properties that resolve to undefined into dest
## Description

`deepMixIn` merges in `src` properties that resolve to `undefined` into `dest` even if they have a value in `dest`

## Steps to reproduce
```js
const dest = { name: 'John', age: 90 }
const src = { name: 'John', age: undefined }
const expected = { name: 'John', age: 90 }
utils.deepMixIn(dest, src) // results to { name: 'John' }
```

Thanks!


Pull request description:
fix(utils): deepMixIn to properly merge undefined values of source
Fixes #501

- [x] - `npm test` succeeds
- [x] - Code coverage does not decrease (if any source code was changed)
- [ ] - If applicable, appropriate JSDoc comments were updated in source code (if applicable)
- [ ] - If applicable, approprate changes to js-data.io docs have been suggested ("Suggest Edits" button)


Patch:
diff --git a/src/utils.js b/src/utils.js
index d340df5..eef2840 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -409,7 +409,7 @@ const utils = {
         const existing = dest[key]
         if (isPlainObject(value) && isPlainObject(existing)) {
           utils.deepMixIn(existing, value)
-        } else {
+        } else if (existing === undefined || value !== undefined) {
           dest[key] = value
         }
       }


Test patch:
diff --git a/test/unit/utils/extendUtils.test.js b/test/unit/utils/extendUtils.test.js
index 6d4c878..432edfa 100644
--- a/test/unit/utils/extendUtils.test.js
+++ b/test/unit/utils/extendUtils.test.js
@@ -54,6 +54,15 @@ describe('utils.deepMixIn', function () {
     assert.deepEqual(expected, actual, 'sorce own properties recursivly copied and overriden into dest')
     assert.equal(dest, utils.deepMixIn(dest), 'empty source argument returns dest')
   })
+
+  it('skips source properties that resolve to undefined if a destination value exists', function () {
+    const dest = { name: 'John', age: 90 }
+    const src = { name: 'John', age: undefined }
+    const expected = { name: 'John', age: 90 }
+    const actual = utils.deepMixIn(dest, src)
+
+    assert.deepEqual(expected, actual)
+  })
 })
 
 describe('utils.extend', function () {