This commit is contained in:
Aaron Jensen 2015-08-04 23:36:40 -07:00
parent c5ab11e176
commit 750200df76
9 changed files with 89 additions and 17 deletions

View File

@ -1,6 +1,7 @@
# Change Log
## [unreleased]
* Add `u.if` to conditionally update objects.
## [0.3.1]
* Actually expose `u.in`.

View File

@ -128,6 +128,22 @@ u({
// => { x: { a: { b: 3 } } };
```
### `u.if(predicate(, updates)(, object))`
Apply updates only if `predicate` is truthy or, if `predicate` is a function,
if it evaluates to truthy when called with `object`.
```js
var obj = { a: 2 };
function isEven(x) { return x % 2 === 0; }
function inc(x) { return x + 1; }
u({
a: u.if(isEven, inc),
}, obj);
// => { a: 3 }
```
### `u.omit(predicate(, object))`
Remove properties. See [`_.omit`](https://lodash.com/docs#omit).

16
lib/if.js Normal file
View File

@ -0,0 +1,16 @@
import curry from 'lodash/function/curry';
import update from './update';
function updateIf(predicate, updates, object) {
const test = typeof predicate === 'function' ?
predicate(object) :
predicate;
if (!test) {
return object;
}
return update(updates, object);
}
export default curry(updateIf);

View File

@ -1,5 +1,6 @@
import update from './update';
import updateIn from './updateIn';
import _in from './in';
import _if from './if';
import omit from './omit';
import reject from './reject';
import withDefault from './withDefault';
@ -12,7 +13,8 @@ function updateAndFreeze(updates, obj) {
const updeep = curry(updateAndFreeze);
updeep.in = updateIn;
updeep.if = _if;
updeep.in = _in;
updeep.freeze = freeze;
updeep.omit = omit;
updeep.reject = reject;

View File

@ -1,5 +1,5 @@
import { expect } from 'chai';
import freeze from '../lib/freeze';
import u from '../lib';
describe('u.freeze', () => {
afterEach(() => {
@ -8,21 +8,21 @@ describe('u.freeze', () => {
it('freezes objects', () => {
const obj = {};
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj)).to.be.true;
});
it('freezes nested objects', () => {
const obj = { foo: { bar: 3 } };
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj.foo)).to.be.true;
});
it('freezes nested arrays', () => {
const obj = [[0]];
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj)).to.be.true;
expect(Object.isFrozen(obj[0])).to.be.true;
@ -30,7 +30,7 @@ describe('u.freeze', () => {
it('ignores functions', () => {
const obj = { foo: () => 1 };
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj.foo)).to.be.false;
});
@ -38,7 +38,7 @@ describe('u.freeze', () => {
it('does not freeze children if the parent is already frozen', () => {
const obj = { foo: {} };
Object.freeze(obj);
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj.foo)).to.be.false;
});
@ -46,20 +46,20 @@ describe('u.freeze', () => {
it('does not freeze in production', () => {
process.env.NODE_ENV = 'production';
const obj = {};
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj)).to.be.false;
});
it('handles null objects', () => {
const obj = { foo: null };
freeze(obj);
u.freeze(obj);
expect(Object.isFrozen(obj)).to.be.true;
});
it('returns the same object', () => {
const obj = {};
const result = freeze(obj);
const result = u.freeze(obj);
expect(result).to.equal(obj);
});
});

36
test/if-spec.js Normal file
View File

@ -0,0 +1,36 @@
import { expect } from 'chai';
import u from '../lib';
describe('u.if', () => {
it('does not update if the predicate is false', () => {
const obj = { a: 0 };
const result = u.if(false, { b: 1 }, obj);
expect(result).to.eql(obj);
});
it('does update if the predicate is true', () => {
const obj = { a: 0 };
const result = u.if(true, { b: 1 }, obj);
expect(result).to.eql({ a: 0, b: 1 });
});
it('will use the result of a function passed as a predicate', () => {
const obj = { a: 0 };
const aIsThree = x => x.a === 3;
const result = u.if(aIsThree, { b: 1 }, obj);
expect(result).to.eql({ a: 0 });
});
it('can be partially applied', () => {
const obj = { a: 2 };
const isEven = x => x % 2 === 0;
const inc = x => x + 1;
const result = u({
a: u.if(isEven, inc),
}, obj);
expect(result).to.eql({ a: 3 });
});
});

View File

@ -1,35 +1,35 @@
import { expect } from 'chai';
import updateIn from '../lib/updateIn';
import u from '../lib';
describe('u.in', () => {
it('can update a single path described with a string', () => {
const obj = { a: { b: 0 } };
const result = updateIn('a.b', 3, obj);
const result = u.in('a.b', 3, obj);
expect(result).to.eql({ a: { b: 3 } });
});
it('can update a single path described with a string with a function', () => {
const inc = x => x + 1;
const obj = { a: { b: 0 } };
const result = updateIn('a.b', inc, obj);
const result = u.in('a.b', inc, obj);
expect(result).to.eql({ a: { b: 1 } });
});
it('can update a single path described with an array', () => {
const obj = { a: { b: 0 } };
const result = updateIn(['a', 'b'], 3, obj);
const result = u.in(['a', 'b'], 3, obj);
expect(result).to.eql({ a: { b: 3 } });
});
it('can update arrays', () => {
const obj = { a: [0, 0, 0] };
const result = updateIn('a.1', 3, obj);
const result = u.in('a.1', 3, obj);
expect(result).to.eql({ a: [0, 3, 0] });
});
it('can be partially applied', () => {
const obj = { a: { b: 0 } };
const result = updateIn('a.b')(3)(obj);
const result = u.in('a.b')(3)(obj);
expect(result).to.eql({ a: { b: 3 } });
});
});

View File

@ -116,6 +116,7 @@ describe('updeep', () => {
it('has additional functions', () => {
expect(u.freeze).to.be.a('function');
expect(u.if).to.be.a('function');
expect(u.in).to.be.a('function');
expect(u.omit).to.be.a('function');
expect(u.withDefault).to.be.a('function');