Skip to content

Commit 50d5f07

Browse files
committed
Completed tests for stringify
1 parent d02db70 commit 50d5f07

File tree

2 files changed

+131
-14
lines changed

2 files changed

+131
-14
lines changed

src/stringify.ts

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,35 @@
11
import clonedeep from 'lodash.clonedeep';
22
import { PropertyMap } from './models';
33

4-
const getProperty = (obj: object, key: string) => {
5-
return key.split('.').filter((s) => s.length > 0)
6-
.reduce((o: object, x: string) => o && o.hasOwnProperty(x) && o[x], obj);
4+
interface GetResult {
5+
exists: boolean;
6+
value: object;
7+
}
8+
9+
const getProperty = (obj: object, key: string): GetResult => {
10+
let exists = true;
11+
12+
const value = key.split('.')
13+
.filter((s) => s.length > 0)
14+
.reduce((o: object, x: string) => {
15+
exists = o && o.hasOwnProperty(x);
16+
17+
if (!exists) {
18+
return undefined;
19+
}
20+
21+
return o[x];
22+
}, obj);
23+
24+
return { exists, value };
725
};
826

927
const setProperty = (obj: object, key: string, value: object) => {
1028
key.split('.')
1129
.filter((s) => s.length > 0)
1230
.reduce((o: object, x: string, idx: number, src: Array<string>): object => {
1331
if (idx === src.length - 1) {
14-
const valueToSet = Array.isArray(value) ? clonedeep(value) : value;
32+
const valueToSet = Array.isArray(value) ? clonedeep(value).map((p) => typeof (p) === 'object' ? {} : p) : value;
1533
o[x] = valueToSet;
1634
}
1735

@@ -20,8 +38,10 @@ const setProperty = (obj: object, key: string, value: object) => {
2038
};
2139

2240
const copyProperty = (sourceObject: object, resultObject: object, propertyPath: string) => {
23-
const value = getProperty(sourceObject, propertyPath);
24-
setProperty(resultObject, propertyPath, value);
41+
const result = getProperty(sourceObject, propertyPath);
42+
if (result.exists) {
43+
setProperty(resultObject, propertyPath, result.value);
44+
}
2545
};
2646

2747
const stringify = (sourceObject: object, map: PropertyMap): string => {
@@ -36,11 +56,15 @@ const stringify = (sourceObject: object, map: PropertyMap): string => {
3656

3757
const parent = getProperty(sourceObject, parentKey);
3858

39-
// Set a default value for the property
40-
setProperty(resultObject, parentKey, Array.isArray(parent) ? parent : {});
59+
if (parent.exists) {
60+
// Set a default value for the property
61+
const defaultValue = Array.isArray(parent.value) ? parent.value : {};
62+
63+
setProperty(resultObject, parentKey, defaultValue);
4164

42-
// Fetch value from source and set on output
43-
childKeys.forEach((key) => copyProperty(sourceObject, resultObject, `${parentKey}.${key}`));
65+
// Fetch value from source and set on output
66+
childKeys.forEach((key) => copyProperty(sourceObject, resultObject, `${parentKey}.${key}`));
67+
}
4468
});
4569

4670
return JSON.stringify(resultObject);

test/stringify.test.ts

Lines changed: 97 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,102 @@
1+
import { PropertyMap } from '../dist/models';
12
import stringify from '../src/stringify';
23

34
describe('stringify ', () => {
4-
it('returns nothing for a blank JSON string', () => {
5-
const result = stringify({}, {});
5+
const expectString = (obj: object, map: PropertyMap, str: string) =>
6+
expect(stringify(obj, map).replace(/\s/g, '')).toEqual(str);
67

7-
expect(result).toEqual('{}');
8-
});
8+
it('returns nothing for a blank JSON string',
9+
() => expectString(
10+
{},
11+
{},
12+
'{}'));
13+
14+
it('ignores properties not found in source',
15+
() => expectString(
16+
{},
17+
{ $: ['a'] },
18+
'{}'));
19+
20+
it('ignores properties not found in map',
21+
() => expectString(
22+
{ a: '1', b: '2' },
23+
{ $: ['b'] },
24+
'{"b":"2"}'));
25+
26+
it('returns first level object properties in order',
27+
() => expectString(
28+
{ a: 2, b: 1 },
29+
{ $: ['b', 'a'] },
30+
'{"b":1,"a":2}'));
31+
32+
it('returns first level array value in order',
33+
() => expectString(
34+
{ a: ['2', 1, true] },
35+
{ $: ['a'] },
36+
'{"a":["2",1,true]}'));
37+
38+
it('returns nested [array] > [object] properties in expected order',
39+
() => expectString(
40+
{ a: [1, { c: '3', d: '2' }] },
41+
{ '$': ['a'], '$.a.1': ['d', 'c'] },
42+
'{"a":[1,{"d":"2","c":"3"}]}'));
43+
44+
it('ignores nested [array] > [object] properties not found in map',
45+
() => expectString(
46+
{ a: [1, { b: 2, c: 3 }, 4] },
47+
{ '$': ['a'], '$.a.1': ['c'] },
48+
'{"a":[1,{"c":3},4]}'));
49+
50+
it('ignores nested [array] > [object] properties not found in map',
51+
() => expectString(
52+
{ a: [1, { b: 2, c: 3 }, 4] },
53+
{ $: ['a'] },
54+
'{"a":[1,{},4]}'));
55+
56+
it('returns nested [object] > [object] properties in expected order',
57+
() => expectString(
58+
{
59+
a: {
60+
b: {
61+
c: 3, d: 4
62+
},
63+
e: {
64+
f: 4, g: 5
65+
},
66+
h: 6
67+
},
68+
i: 7
69+
},
70+
{
71+
'$': ['i', 'a'],
72+
'$.a': ['e', 'h', 'b'],
73+
'$.a.e': ['g', 'f'],
74+
'$.a.b': ['d', 'c']
75+
},
76+
'{"i":7,"a":{"e":{"g":5,"f":4},"h":6,"b":{"d":4,"c":3}}}'));
77+
78+
it('returns nested [object] > [array] > [object] > [array] > [object] properties in expected order',
79+
() => expectString(
80+
{
81+
a: {
82+
b: [8, {
83+
c: 9,
84+
d: [{
85+
e: 12,
86+
f: {
87+
g: true, h: 'h'
88+
}
89+
}, 10]
90+
}, 11]
91+
},
92+
i: 7
93+
},
94+
{
95+
'$': ['i', 'a'],
96+
'$.a': ['b'],
97+
'$.a.b.1': ['d', 'c'],
98+
'$.a.b.1.d.0': ['f', 'e'],
99+
'$.a.b.1.d.0.f': ['h', 'g']
100+
},
101+
'{"i":7,"a":{"b":[8,{"d":[{"f":{"h":"h","g":true},"e":12},10],"c":9},11]}}'));
9102
});

0 commit comments

Comments
 (0)