Skip to content

Commit 38589fa

Browse files
committed
Added tests for serialiser module
1 parent 68d8b53 commit 38589fa

File tree

3 files changed

+205
-42
lines changed

3 files changed

+205
-42
lines changed

src/node.js

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export default class Node {
3030
return this
3131
}
3232

33+
self = () => this
34+
3335
children = []
3436

3537
options = {

src/serialiser.js

+23-23
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ export default class Serialiser {
2323
* @returns {void}
2424
*/
2525
yank (root, data, parent) {
26-
const node = root.filter(data)
27-
const value = this.get(data, node.key.path, node.options)
28-
const set = this.set.bind(this, node, parent)
26+
const { children, options, key } = root.filter(data)
27+
const value = this.get(data, key.path, options)
28+
const set = child => this.set(parent, key, child)
2929

30-
if (node.children.length) {
31-
if (value || node.options.nullable) {
32-
const children = this.dig(node, value)
30+
if (children.length) {
31+
if (value || options.nullable) {
32+
const items = this.dig(value, children)
3333

34-
if (node.options.extract) {
35-
assign(parent, children)
34+
if (options.extract) {
35+
assign(parent, items)
3636
} else {
37-
set(children)
37+
set(items)
3838
}
3939
}
4040
} else {
@@ -46,19 +46,19 @@ export default class Serialiser {
4646
* Digs into the next level of hierarchy and yanks all properties from the
4747
* data source via the AST schema node at that level.
4848
*
49-
* @param {Node} node - Current level node.
50-
* @param {object} data - Data to extract properties from.
49+
* @param {object} value - Data to extract properties from.
50+
* @param {Array.<Node>} children - Child nodes.
5151
*
5252
* @returns {object} - Yanked properties.
5353
*/
54-
dig (node, data) {
54+
dig (value, children) {
55+
const nullable = children.every(n => !n.options.nullable)
5556
const result = {}
56-
const nullable = node.children.every(n => !n.options.nullable)
5757

58-
if (!data && nullable) return null
58+
if (!value && nullable) return null
5959

60-
for (const child of node.children) {
61-
this.yank(child, data, result)
60+
for (const child of children) {
61+
this.yank(child, value, result)
6262
}
6363

6464
return result
@@ -81,14 +81,14 @@ export default class Serialiser {
8181
/**
8282
* Similar to Lodash.get, this retrieves properties at the given path.
8383
*
84-
* @param {object} data - Data to obtain the value from.
84+
* @param {object} item - Data to obtain the value from.
8585
* @param {Array.<string>} path - Segments of a path to the value.
86-
* @param {object} options - Configuration for retrieving the value.
86+
* @param {object} [options] - Configuration for retrieving the value.
8787
*
8888
* @returns {any | null} - Value at the given path, if it exists.
8989
*/
90-
get (data, path, options) {
91-
const value = path.reduce((acc, curr) => acc?.[curr], data)
90+
get (item, path, options = {}) {
91+
const value = path.reduce((acc, curr) => acc?.[curr], item)
9292
const result = options.exec
9393
? options.exec(value)
9494
: value
@@ -101,14 +101,14 @@ export default class Serialiser {
101101
/**
102102
* Sets a vaLue on the given parent value.
103103
*
104-
* @param {Node} node - Current level node.
105104
* @param {Node} parent - Parent node value.
105+
* @param {Key} key - Key instance on the current Node.
106106
* @param {any} value - Value to set onto the parent node.
107107
*
108108
* @returns {void}
109109
*/
110-
set (node, parent, value) {
111-
parent[node.key.name] = value
110+
set (parent, key, value) {
111+
parent[key.name] = value
112112
}
113113

114114
result = {}

tests/serialiser.spec.js

+180-19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const data = () => ({
66
...original
77
})
88
const node = () => ({
9+
filter: jest.fn(),
910
children: [],
1011
filters: [],
1112
options: {},
@@ -35,54 +36,214 @@ describe('src/serialiser', () => {
3536
})
3637
})
3738

38-
describe.skip('yank', () => {
39-
it('should apply filters by running filter method', () => {
39+
describe('yank', () => {
40+
const setup = ({ options = {}, children = [] } = {}) => {
4041
const serialiser = new Serialiser(data(), ast())
41-
const value = data()
42-
const parent = 'test-parent'
43-
const curr = {
44-
...node()
42+
const value = 'test-value'
43+
const set = 'test-set'
44+
const child = {
45+
value: true
46+
}
47+
const root = {
48+
options,
49+
children,
50+
filter () {
51+
return this
52+
},
53+
key: {
54+
path: []
55+
}
4556
}
4657

47-
serialiser.filter = jest
58+
serialiser.get = jest
59+
.fn()
60+
.mockReturnValue(value)
61+
serialiser.set = jest
4862
.fn()
49-
.mockReturnValue(curr)
63+
.mockReturnValue(set)
64+
serialiser.dig = jest
65+
.fn()
66+
.mockReturnValue(child)
5067

51-
serialiser.yank(curr, value, parent)
68+
return {
69+
serialiser,
70+
value,
71+
child,
72+
root
73+
}
74+
}
75+
76+
it('should assign to parent if extract is truthy', () => {
77+
const { serialiser, root } = setup({
78+
options: {
79+
extract: true
80+
},
81+
children: [
82+
'test-child'
83+
]
84+
})
85+
const parent = {}
86+
87+
serialiser.yank(root, data, parent)
5288

53-
expect(serialiser.filter).toBeCalledWith({
54-
data: value,
55-
node: curr,
56-
parent: {}
89+
expect(parent.value).toEqual(true)
90+
expect(serialiser.set).not.toBeCalled()
91+
})
92+
93+
it('should set all children to the parent', () => {
94+
const { serialiser, root, child } = setup({
95+
children: [
96+
'test-child'
97+
]
5798
})
99+
const parent = {}
100+
101+
serialiser.yank(root, data, parent)
102+
103+
const { length } = Object.keys(parent)
104+
105+
expect(serialiser.set).toBeCalledWith(parent, root.key, child)
106+
expect(length).toEqual(0)
58107
})
59108

60-
it('should descend through all children', () => {
61-
const serialiser = new Serialiser(data(), ast())
109+
it('should set value on the parent', () => {
110+
const { serialiser, root, value } = setup()
111+
const parent = {}
62112

63-
serialiser.filter = jest.fn()
113+
serialiser.yank(root, data, parent)
64114

65-
serialiser.yank()
115+
expect(serialiser.set).toBeCalledWith(parent, root.key, value)
66116
})
67117
})
68118

69119
describe('dig', () => {
120+
it('should return null if data is falsey and is nullable', () => {
121+
const serialiser = new Serialiser(data(), ast())
122+
const result = serialiser.dig(undefined, [])
70123

71-
})
124+
expect(result).toBeNull()
125+
})
126+
127+
it('should return result', () => {
128+
const serialiser = new Serialiser(data(), ast())
129+
const value = 'test-value'
72130

73-
describe('filter', () => {
131+
serialiser.yank = jest.fn()
132+
133+
const result = serialiser.dig(value, [])
134+
135+
expect(result).toEqual({})
136+
})
74137

138+
it('should call yank for each child', () => {
139+
const serialiser = new Serialiser(data(), ast())
140+
const value = 'test-value'
141+
const children = [
142+
{
143+
options: {}
144+
},
145+
{
146+
options: {}
147+
}
148+
]
149+
150+
serialiser.yank = jest.fn()
151+
serialiser.dig(value, children)
152+
153+
expect(serialiser.yank).toBeCalledTimes(children.length)
154+
expect(serialiser.yank).toBeCalledWith(children[0], value, {})
155+
})
75156
})
76157

77158
describe('serialise', () => {
159+
it('should call yank for each item in the AST', () => {
160+
const value = 'test-value'
161+
const ast = [
162+
'test-1',
163+
'test-2'
164+
]
165+
const data = {
166+
value
167+
}
168+
const serialiser = new Serialiser(data, ast)
169+
170+
serialiser.yank = jest.fn()
171+
serialiser.serialise()
78172

173+
expect(serialiser.yank).toBeCalledTimes(ast.length)
174+
})
175+
176+
it('should return result', () => {
177+
const serialiser = new Serialiser(data(), ast())
178+
const value = 'test-result'
179+
180+
serialiser.result = value
181+
serialiser.yank = jest.fn()
182+
183+
const result = serialiser.serialise()
184+
185+
expect(result).toEqual(value)
186+
})
79187
})
80188

81189
describe('get', () => {
190+
const path = [
191+
'nested',
192+
'data',
193+
'items',
194+
'one'
195+
]
196+
197+
it('should retrieve a value from a given path', () => {
198+
const source = data()
199+
const serialiser = new Serialiser(source, ast())
200+
const result = serialiser.get(source, path)
82201

202+
expect(result).toEqual('one')
203+
})
204+
205+
it('should run exec() if available in options', () => {
206+
const source = data()
207+
const serialiser = new Serialiser(source, ast())
208+
const value = 'test-value'
209+
const options = {
210+
exec: jest
211+
.fn()
212+
.mockReturnValue(value)
213+
}
214+
const result = serialiser.get(source, path, options)
215+
216+
expect(result).toEqual(value)
217+
})
218+
219+
it('should return null if options.nullable is truthy and result is not', () => {
220+
const source = data()
221+
const serialiser = new Serialiser(source, ast())
222+
const path = [
223+
'foo',
224+
'bar'
225+
]
226+
const options = {
227+
nullable: true
228+
}
229+
const result = serialiser.get(source, path, options)
230+
231+
expect(result).toBeNull()
232+
})
83233
})
84234

85235
describe('set', () => {
236+
it('should set the value at the given key location', () => {
237+
const serialiser = new Serialiser(data(), ast())
238+
const parent = {}
239+
const key = {
240+
name: 'foo'
241+
}
242+
const value = 'test-value'
243+
244+
serialiser.set(parent, key, value)
86245

246+
expect(parent.foo).toEqual(value)
247+
})
87248
})
88249
})

0 commit comments

Comments
 (0)