Add initial code, tests don't work yet.

This commit is contained in:
Aaron Jensen 2015-07-31 09:16:19 -07:00
parent 6a6daaacbe
commit 35fe73e080
7 changed files with 192 additions and 12 deletions

View File

@ -1,2 +1,6 @@
'use strict'; const update = require('app/utils/update/update');
export default {}; update.omit = require('app/utils/update/omit');
update.reject = require('app/utils/update/reject');
update.withDefault = require('app/utils/update/with_default');
module.exports = update;

4
lib/omit.js Normal file
View File

@ -0,0 +1,4 @@
const omit = require('lodash/object/omit');
const curry = require('lodash/function/curry');
module.exports = curry((predicate, collection) => omit(collection, predicate));

4
lib/reject.js Normal file
View File

@ -0,0 +1,4 @@
const reject = require('lodash/collection/reject');
const curry = require('lodash/function/curry');
module.exports = curry((predicate, collection) => reject(collection, predicate));

59
lib/update.js Normal file
View File

@ -0,0 +1,59 @@
const reduce = require('lodash/collection/reduce');
const isEmpty = require('lodash/lang/isEmpty');
const curry = require('lodash/function/curry');
function resolveUpdates(updates, obj = {}) {
return reduce(updates, (acc, value, key) => {
if (!Array.isArray(value) && typeof value === 'object') {
value = update(value, obj[key]);
} else if (typeof value === 'function') {
value = value(obj[key]);
}
if (obj[key] !== value) {
acc[key] = value;
}
return acc;
}, {});
}
function updateArray(updates, obj) {
const newObj = [...obj];
return reduce(updates, (acc, value, index) => {
acc[index] = value;
return acc;
}, newObj);
}
/**
* Recursively update an object or array.
*
* Can update with values:
* update({ foo: 3 }, { foo: 1, bar: 2 });
* // => { foo: 3, bar: 2 }
*
* Or with a function:
* update({ foo: x => (x + 1) }, { foo: 2 });
* // => { foo: 3 }
*/
function update(updates, obj) {
if (typeof updates === 'function') {
return updates(obj);
}
const resolvedUpdates = resolveUpdates(updates, obj);
if (isEmpty(resolvedUpdates)) {
return obj;
}
if (Array.isArray(obj)) {
return updateArray(resolvedUpdates, obj);
}
return Object.assign({}, obj, resolvedUpdates);
}
module.exports = curry(update);

11
lib/with_default.js Normal file
View File

@ -0,0 +1,11 @@
const update = require('app/utils/update/update');
module.exports = function withDefault(defaultValue, updates) {
return (value) => {
if (typeof value === "undefined") {
return update(updates, defaultValue);
}
return update(updates, value);
};
};

View File

@ -26,16 +26,20 @@
"bugs": { "bugs": {
"url": "https://github.com/aaronjensen/updeep/issues" "url": "https://github.com/aaronjensen/updeep/issues"
}, },
"peerDependencies": {
"lodash": "^3.10.0"
},
"devDependencies": { "devDependencies": {
"babel-core": "^5.5.0",
"chai": "^3.2.0",
"gulp": "^3.6.0", "gulp": "^3.6.0",
"gulp-babel": "^5.1.0",
"gulp-coveralls": "^0.1.0",
"gulp-eslint": "^0.15.0",
"gulp-exclude-gitignore": "^1.0.0", "gulp-exclude-gitignore": "^1.0.0",
"gulp-istanbul": "^0.9.0", "gulp-istanbul": "^0.9.0",
"gulp-eslint": "^0.15.0",
"gulp-mocha": "^2.0.0", "gulp-mocha": "^2.0.0",
"gulp-plumber": "^1.0.0",
"gulp-nsp": "^0.4.5", "gulp-nsp": "^0.4.5",
"gulp-coveralls": "^0.1.0", "gulp-plumber": "^1.0.0"
"gulp-babel": "^5.1.0",
"babel-core": "^5.5.0"
} }
} }

View File

@ -1,9 +1,103 @@
'use strict'; import { expect } from 'chai';
import assert from 'assert';
import updeep from '../lib'; import updeep from '../lib';
describe('updeep', function () { console.log("testing");
it('should have unit test!', function () { describe("updeep", () => {
assert(false, 'we expected this package author to add actual unit tests.'); it("does not change anything if no updates are specified", () => {
console.log("testing2");
const obj = { foo: 3, bar: [7, 5] };
const result = updeep({}, obj);
expect(result).to.equal(obj);
});
it("can update with fixed values", () => {
const obj = { foo: 3, bar: [7, 5] };
const result = updeep({ foo: 4 }, obj);
expect(result).to.deep.equal({ foo: 4, bar: [7, 5] });
});
it("returns the same instance if an update doesn't make changes", () => {
const obj = { foo: 3 };
const result = updeep({ foo: 3 }, obj);
expect(result).to.equal(obj);
});
it("can update a nested structure", () => {
const obj = { foo: { bar: 7, bam: 3 }, baz: 32 };
const result = updeep({ foo: { bar: 8 } }, obj);
expect(result).to.deep.equal({ foo: { bar: 8, bam: 3 }, baz: 32 });
});
it("can update arrays", () => {
const obj = [1, 2, 3];
const result = updeep({ 1: 7 }, obj);
expect(result).to.deep.equal([1, 7, 3]);
});
it("can add an element to an array", () => {
const obj = [];
const result = updeep({ 0: 3 }, obj);
expect(result).to.eql([3]);
});
it("can update nested arrays", () => {
const obj = { foo: [1, 2, 3], bar: 9 };
const result = updeep({ foo: { 1: 7 } }, obj);
expect(result).to.deep.equal({ foo: [1, 7, 3], bar: 9 });
});
it("can use functions to update values", () => {
const inc = (i) => i + 1;
const obj = { foo: 3, bar: 4, baz: 7 };
const result = updeep({ foo: inc, bar: inc }, obj);
expect(result).to.deep.equal({ foo: 4, bar: 5, baz: 7 });
});
it("is curryable", () => {
const inc = (i) => i + 1;
const obj = { foo: 3 };
const incFoo = updeep({ foo: inc });
const result = incFoo(obj);
expect(result).to.deep.equal({ foo: 4 });
});
it("can update if the value is an array", () => {
const obj = {};
const result = updeep({ foo: [0, 1] }, obj);
expect(result).to.deep.equal({ foo: [0, 1] });
});
it("can use withDefault to default things", () => {
const obj = {};
const result = updeep({
foo: update.withDefault([], {
0: 'bar'
})
}, obj);
expect(result).to.eql({ foo: ['bar'] });
});
it('can update when original object is undefined', () => {
const result = updeep({ foo: [0, 1] }, undefined);
expect(result).to.deep.equal({ foo: [0, 1] });
});
it('can take a function as the updater', () => {
const result = updeep(i => i + 1, 7);
expect(result).to.eql(8);
}); });
}); });