move unset into its own module, include tests

also fixes issue with recursive removal of properties
This commit is contained in:
Joe Fleming 2016-03-22 15:24:51 -07:00
parent 21520477cf
commit b126e35e4e
2 changed files with 109 additions and 0 deletions

View file

@ -0,0 +1,83 @@
import unset from '../unset';
import expect from 'expect.js';
describe('unset(obj, key)', function () {
describe('invalid input', function () {
it('should do nothing if not given an object', function () {
const obj = 'hello';
unset(obj, 'e');
expect(obj).to.equal('hello');
});
it('should do nothing if not given a key', function () {
const obj = { one: 1 };
unset(obj);
expect(obj).to.eql({ one: 1 });
});
it('should do nothing if given an empty string as a key', function () {
const obj = { one: 1 };
unset(obj, '');
expect(obj).to.eql({ one: 1 });
});
});
describe('shallow removal', function () {
let obj;
beforeEach(function () {
obj = { one: 1, two: 2, deep: { three: 3, four: 4 } };
});
it('should remove the param using a string key', function () {
unset(obj, 'two');
expect(obj).to.eql({ one: 1, deep: { three: 3, four: 4 } });
});
it('should remove the param using an array key', function () {
unset(obj, ['two']);
expect(obj).to.eql({ one: 1, deep: { three: 3, four: 4 } });
});
});
describe('deep removal', function () {
let obj;
beforeEach(function () {
obj = { one: 1, two: 2, deep: { three: 3, four: 4 } };
});
it('should remove the param using a string key', function () {
unset(obj, 'deep.three');
expect(obj).to.eql({ one: 1, two: 2, deep: { four: 4 } });
});
it('should remove the param using an array key', function () {
unset(obj, ['deep', 'three']);
expect(obj).to.eql({ one: 1, two: 2, deep: { four: 4 } });
});
});
describe('recursive removal', function () {
it('should clear object if only value is removed', function () {
const obj = { one: { two: { three: 3 } } };
unset(obj, 'one.two.three');
expect(obj).to.eql({});
});
it('should clear object if no props are left', function () {
const obj = { one: { two: { three: 3 } } };
unset(obj, 'one.two');
expect(obj).to.eql({});
});
it('should remove deep property, then clear the object', function () {
const obj = { one: { two: { three: 3, four: 4 } } };
unset(obj, 'one.two.three');
expect(obj).to.eql({ one: { two: { four: 4 } } });
unset(obj, 'one.two.four');
expect(obj).to.eql({});
});
});
});

View file

@ -0,0 +1,26 @@
import _ from 'lodash';
import toPath from 'lodash/internal/toPath';
module.exports = function unset(object, rawPath) {
if (!object) return;
const path = toPath(rawPath);
switch (path.length) {
case 0:
return;
case 1:
delete object[rawPath];
break;
default:
const leaf = path.pop();
const parentPath = path.slice();
const parent = _.get(object, parentPath);
unset(parent, leaf);
if (!_.size(parent)) {
unset(object, parentPath);
}
break;
}
};