@tdb/util
Version:
Shared helpers and utilities.
196 lines (170 loc) • 5.96 kB
text/typescript
import { expect } from 'chai';
import { value } from '.';
const { object } = value;
describe('object.build', () => {
it('return default root object (no keyPath)', () => {
expect(object.build('', {})).to.eql({});
expect(object.build(' ', {})).to.eql({});
});
it('returns clone of the given root object', () => {
const obj = {};
expect(object.build('', obj)).to.not.equal(obj);
});
it('adds single level', () => {
expect(object.build('foo', {})).to.eql({ foo: {} });
expect(object.build(' foo ', {})).to.eql({ foo: {} });
});
it('adds multi-levels (path)', () => {
const res = object.build('foo.bar', {});
expect(res).to.eql({ foo: { bar: {} } });
});
it('adds multi-levels with custom value', () => {
const test = (value: any) => {
const res = object.build<any>('foo.bar.baz', {}, value);
expect(res.foo.bar.baz).to.eql(value);
};
test(0);
test(123);
test('hello');
test('');
test(' ');
test({});
});
it('does not replace existing object/value (cloned, single-level)', () => {
const obj = { foo: { bar: 123 } };
const res = object.build<any>('foo', obj);
expect(res).to.eql(obj);
expect(res).to.not.equal(obj);
expect(res.foo).to.not.equal(obj.foo);
});
it('throws if path overwrites value', () => {
const test = (keyPath: string, obj: object) => {
const fn = () => object.build(keyPath, obj);
expect(fn).to.throw();
};
test('foo.bar', { foo: { bar: 123 } });
test('foo.bar', { foo: { bar: 0 } });
test('foo.bar', { foo: { bar: null } });
test('foo.bar', { foo: { bar: '' } });
});
it('throws if starts/ends with period (.)', () => {
const test = (keyPath: string) => {
const fn = () => object.build(keyPath, {});
expect(fn).to.throw();
};
test('foo.bar.');
test('foo.bar. ');
test('.foo.bar');
test(' .foo.bar ');
test('.foo.bar.');
});
it('appends existing object', () => {
const obj = { foo: { bar: 123 } };
const res = object.build('foo.baz', obj);
expect(res).to.eql({ foo: { bar: 123, baz: {} } });
});
});
describe('object.pluck', () => {
it('returns [undefined] when no match', () => {
expect(object.pluck('foo', {})).to.eql(undefined);
expect(object.pluck('foo.bar', {})).to.eql(undefined);
expect(object.pluck('foo.bar', { baz: 123 })).to.eql(undefined);
});
it('gets value', () => {
const test = (keyPath: string, root: any, value: any) => {
const res = object.pluck(keyPath, root);
expect(res).to.eql(
value,
`The key-path "${keyPath}" should be [${value}]`,
);
};
test('foo', { foo: 123 }, 123);
test('foo.bar', { foo: { bar: 123 } }, 123);
test(' foo.bar ', { foo: { bar: 123 } }, 123);
test(' foo. bar ', { foo: { bar: 123 } }, 123);
});
it('throws if starts/ends with period (.)', () => {
const test = (key: string) => {
const fn = () => object.pluck(key, {});
expect(fn).to.throw();
};
test('foo.bar.');
test('foo.bar. ');
test('.foo.bar');
test(' .foo.bar ');
test('.foo.bar.');
});
});
describe('object.remove', () => {
const test = (keyPath: string, root: any, expected: any) => {
const result = object.remove(keyPath, root);
const msg = `keyPath: "${keyPath}"`;
expect(result).to.eql(expected, msg);
expect(result).to.not.equal(root, msg);
};
it('removes nothing (no match)', () => {
test('', {}, {});
test('', { foo: 123 }, { foo: 123 });
test('foo', {}, {});
test('foo', { bar: 456 }, { bar: 456 });
test('foo.bar', {}, {});
test('foo.bar', { foo: 123 }, { foo: 123 });
test('foo.bar.baz', { foo: 123 }, { foo: 123 });
});
it('removes shallow path', () => {
test('foo', { foo: 123 }, {});
test('foo', { foo: 123, bar: 'hi' }, { bar: 'hi' });
});
it('removes deep path', () => {
test('foo.bar', { foo: { bar: 123 } }, { foo: {} });
test('foo.bar.baz', { foo: { bar: { baz: 456 } } }, { foo: { bar: {} } });
test('foo.bar', { foo: { bar: 123, baz: 456 } }, { foo: { baz: 456 } });
test('foo.bar', { foo: { bar: 123 }, baz: 456 }, { baz: 456, foo: {} });
});
it('removes wildcard (*)', () => {
test('foo.*', { foo: { bar: 123 } }, { foo: {} });
test('foo.*', { foo: { bar: 123 }, baz: 456 }, { baz: 456, foo: {} });
test('*', { foo: { bar: 123 }, baz: 456 }, {});
});
});
describe('object.prune', () => {
const test = (keyPath: string, root: any, expected: any) => {
const result = object.prune(keyPath, root);
const msg = `keyPath: "${keyPath}"`;
expect(result).to.eql(expected, msg);
expect(result).to.not.equal(root, msg);
};
it('prunes nothing (no match)', () => {
test('', {}, {});
test('', { foo: 123 }, { foo: 123 });
test('foo', {}, {});
test('foo', { bar: 456 }, { bar: 456 });
test('foo.bar', {}, {});
test('foo.bar', { foo: 123 }, { foo: 123 });
test('foo.bar.baz', { foo: 123 }, { foo: 123 });
});
it('prunes nothing (child not empty)', () => {
test('foo', { foo: { bar: {} } }, { foo: { bar: {} } });
});
it('throws if wild card not at end of path', () => {
const fn = () => object.prune('*.bar', {});
expect(fn).to.throw();
});
it('prunes wildcard (*)', () => {
test('foo.*', { foo: { bar: {}, baz: 123 } }, {});
test('foo.*', { foo: 123 }, {});
test('foo.*', {}, {});
test('*', {}, {});
test('*', { foo: 123, bar: {} }, {});
});
it('prunes shallow path', () => {
test('foo', { foo: 123 }, {});
test('foo', { foo: 123, bar: 'hi' }, { bar: 'hi' });
});
it('prunes deep path', () => {
test('foo.bar', { foo: { bar: 123 } }, {});
test('foo.bar.baz', { foo: { bar: { baz: 456 } } }, {});
test('foo.bar', { foo: { bar: 123, baz: 456 } }, { foo: { baz: 456 } });
test('foo.bar', { foo: { bar: 123 }, baz: 456 }, { baz: 456 });
});
});