1 | 'use strict';
|
2 | var ObjectManage = require('../lib/ObjectManage')
|
3 | , expect = require('chai').expect
|
4 | describe('ObjectManage',function(){
|
5 | var data1 = {test1: 'val1', test2: 'val2'}
|
6 | , data2 = {test3: 'val3', test4: 'val4'}
|
7 | , data3 = {test5: {test6: 'val6'}}
|
8 |
|
9 | describe('Construction',function(){
|
10 | it('should accept data to the constructor',function(){
|
11 | var obj = new ObjectManage(data1)
|
12 | expect(obj.data.test1).to.equal('val1')
|
13 | expect(obj.data.test2).to.equal('val2')
|
14 | })
|
15 | it('should be able to merge in data after constructing',function(){
|
16 | var obj = new ObjectManage([data1,data2])
|
17 | expect(obj.data.test3).to.equal('val3')
|
18 | expect(obj.data.test4).to.equal('val4')
|
19 | })
|
20 | })
|
21 |
|
22 | describe('Setters and Getters',function(){
|
23 | it('should be able to get a nested key',function(){
|
24 | var obj = new ObjectManage([data1,data3])
|
25 | expect(obj.get('test5.test6')).to.equal('val6')
|
26 | })
|
27 | it('should be able to set a nested key',function(){
|
28 | var obj = new ObjectManage([data1,data3])
|
29 | obj.set('test5.test7','val7')
|
30 | expect(obj.data.test5.test7).to.equal('val7')
|
31 | })
|
32 | it('should overwrite a key to object if nested below',function(){
|
33 | var obj = new ObjectManage([data1,data2,data3])
|
34 | obj.set('test5.test6.new','val8')
|
35 | expect(obj.data.test5.test6.new).to.equal('val8')
|
36 | })
|
37 | it('should returned undefined on a missing key',function(){
|
38 | var obj = new ObjectManage(data1)
|
39 | expect(obj.get('test5.test6')).to.equal(undefined)
|
40 | })
|
41 | })
|
42 |
|
43 | describe('Removal and Existence',function(){
|
44 | it('should return true if the property exists',function(){
|
45 | var obj = new ObjectManage(data1)
|
46 | expect(obj.exists('test1')).to.equal(true)
|
47 | })
|
48 | it('should return false if the property does not exist',function(){
|
49 | var obj = new ObjectManage()
|
50 | expect(obj.exists('test1')).to.equal(false)
|
51 | })
|
52 | it('should remove a property and all its children',function(){
|
53 | var obj = new ObjectManage([data1,data2,data3])
|
54 | obj.remove('test5')
|
55 | expect(obj.data.hasOwnProperty('test5')).to.equal(false)
|
56 | })
|
57 | })
|
58 |
|
59 | describe('Merging',function(){
|
60 | it('should always have an object at .data',function(){
|
61 | var obj = new ObjectManage()
|
62 | obj.load(undefined)
|
63 | expect(obj.data).to.be.an('object')
|
64 | })
|
65 | it('should return the whole object if no argument if passed to get',function(){
|
66 | var obj = new ObjectManage([data1,data2,data3])
|
67 | expect(Object.keys(obj.get()).length).to.equal(5)
|
68 | })
|
69 | it('should merge recursively',function(){
|
70 | var obj = new ObjectManage(data3)
|
71 | obj.load({test5: {test7: 'val7'}})
|
72 | expect(obj.get('test5.test6')).to.equal('val6')
|
73 | expect(obj.get('test5.test7')).to.equal('val7')
|
74 | })
|
75 | })
|
76 |
|
77 | describe('Events',function(){
|
78 | it('should be able to watch the data object',function(done){
|
79 | var obj = new ObjectManage()
|
80 | obj.once('load',function(data){
|
81 | expect(data.test5.test6).to.equal('val6')
|
82 | done()
|
83 | })
|
84 | obj.load(data3)
|
85 | })
|
86 | it('should emit a set event',function(done){
|
87 | var obj = new ObjectManage()
|
88 | obj.once('set',function(path,value){
|
89 | expect(path).to.equal('foo')
|
90 | expect(value).to.equal('baz')
|
91 | done()
|
92 | })
|
93 | obj.set('foo','baz')
|
94 | })
|
95 | it('should emit a get event',function(done){
|
96 | var obj = new ObjectManage(data1)
|
97 | obj.once('get',function(path,value){
|
98 | expect(path).to.equal('test1')
|
99 | expect(value).to.equal('val1')
|
100 | done()
|
101 | })
|
102 | obj.get('test1')
|
103 | })
|
104 | it('should emit an exists event',function(done){
|
105 | var obj = new ObjectManage(data1)
|
106 | obj.once('exists',function(path,exists){
|
107 | expect(path).to.equal('foo')
|
108 | expect(exists).to.equal(false)
|
109 | done()
|
110 | })
|
111 | obj.exists('foo')
|
112 | })
|
113 | it('should emit a remove event',function(done){
|
114 | var obj = new ObjectManage(data1)
|
115 | obj.once('remove',function(path,removed){
|
116 | expect(path).to.equal('test1')
|
117 | expect(removed).to.equal(true)
|
118 | done()
|
119 | })
|
120 | obj.remove('test1')
|
121 | })
|
122 | it('should emit a load event',function(done){
|
123 | var obj = new ObjectManage()
|
124 | obj.once('load',function(data){
|
125 | expect(data.test1).to.equal('val1')
|
126 | done()
|
127 | })
|
128 | obj.load(data1)
|
129 | })
|
130 | })
|
131 |
|
132 | describe('Set with Validation',function(){
|
133 | it('should validate using drop',function(done){
|
134 | var obj = new ObjectManage()
|
135 | obj.validateSet = function(path){
|
136 | expect(path).to.equal('test1')
|
137 | this.drop(path + ' must be set to val2')
|
138 | }
|
139 | obj.once('drop',function(verb,message,path,value){
|
140 | expect(verb).to.equal('set')
|
141 | expect(message).to.equal('test1 must be set to val2')
|
142 | expect(path).to.equal('test1')
|
143 | expect(value).to.equal('val3')
|
144 | done()
|
145 | })
|
146 | obj.set('test1','val3')
|
147 | })
|
148 | it('should validate using reject',function(done){
|
149 | var obj = new ObjectManage()
|
150 | obj.validateSet = function(path){
|
151 | expect(path).to.equal('test1')
|
152 | this.reject(path + ' must be set to val2')
|
153 | }
|
154 | obj.once('reject',function(verb,message,path,value){
|
155 | expect(verb).to.equal('set')
|
156 | expect(message).to.equal('test1 must be set to val2')
|
157 | expect(path).to.equal('test1')
|
158 | expect(value).to.equal('val3')
|
159 | done()
|
160 | })
|
161 | obj.set('test1','val3')
|
162 | })
|
163 | it('should validate using warn',function(done){
|
164 | var obj = new ObjectManage()
|
165 | obj.validateSet = function(path,value){
|
166 | expect(path).to.equal('test1')
|
167 | this.warn(path + ' must be set to val2',value)
|
168 | }
|
169 | obj.once('warn',function(verb,message,path,value){
|
170 | expect(verb).to.equal('set')
|
171 | expect(message).to.equal('test1 must be set to val2')
|
172 | expect(path).to.equal('test1')
|
173 | expect(value).to.equal('val3')
|
174 | expect(obj.get('test1')).to.equal('val3')
|
175 | done()
|
176 | })
|
177 | obj.set('test1','val3')
|
178 | })
|
179 | it('should validate using error',function(done){
|
180 | var obj = new ObjectManage()
|
181 | obj.validateSet = function(path){
|
182 | expect(path).to.equal('test1')
|
183 | this.error(path + ' must be set to val2')
|
184 | }
|
185 | obj.once('error',function(verb,message,path,value){
|
186 | expect(verb).to.equal('set')
|
187 | expect(message).to.equal('test1 must be set to val2')
|
188 | expect(path).to.equal('test1')
|
189 | expect(value).to.equal('val3')
|
190 | done()
|
191 | })
|
192 | expect(function(){obj.set('test1','val3')}).to.throw('test1 must be set to val2')
|
193 | })
|
194 | it('should validate using ok',function(done){
|
195 | var obj = new ObjectManage()
|
196 | obj.validateSet = function(path,value){
|
197 | expect(path).to.equal('test1')
|
198 | this.ok(value)
|
199 | }
|
200 | obj.once('set',function(path,value){
|
201 | expect(path).to.equal('test1')
|
202 | expect(value).to.equal('val3')
|
203 | expect(obj.get('test1')).to.equal('val3')
|
204 | done()
|
205 | })
|
206 | obj.set('test1','val3')
|
207 | })
|
208 | it('should validate using return',function(done){
|
209 | var obj = new ObjectManage()
|
210 | obj.validateSet = function(path,value){
|
211 | expect(path).to.equal('test1')
|
212 | return value
|
213 | }
|
214 | obj.once('set',function(path,value){
|
215 | expect(path).to.equal('test1')
|
216 | expect(value).to.equal('val3')
|
217 | expect(obj.get('test1')).to.equal('val3')
|
218 | done()
|
219 | })
|
220 | obj.set('test1','val3')
|
221 | })
|
222 | })
|
223 |
|
224 | describe('Get with Validation',function(){
|
225 | it('should validate using drop',function(done){
|
226 | var obj = new ObjectManage()
|
227 | obj.validateGet = function(path){
|
228 | expect(path).to.equal('test1')
|
229 | this.drop(path + ' must be set to val2')
|
230 | }
|
231 | obj.once('drop',function(verb,message,path,value){
|
232 | expect(verb).to.equal('get')
|
233 | expect(message).to.equal('test1 must be set to val2')
|
234 | expect(path).to.equal('test1')
|
235 | expect(value).to.equal('val3')
|
236 | done()
|
237 | })
|
238 | obj.set('test1','val3')
|
239 | obj.get('test1')
|
240 | })
|
241 | it('should validate using reject',function(done){
|
242 | var obj = new ObjectManage()
|
243 | obj.validateGet = function(path){
|
244 | expect(path).to.equal('test1')
|
245 | this.reject(path + ' must be set to val2')
|
246 | }
|
247 | obj.once('reject',function(verb,message,path,value){
|
248 | expect(verb).to.equal('get')
|
249 | expect(message).to.equal('test1 must be set to val2')
|
250 | expect(path).to.equal('test1')
|
251 | expect(value).to.equal('val3')
|
252 | done()
|
253 | })
|
254 | obj.set('test1','val3')
|
255 | obj.get('test1')
|
256 | })
|
257 | it('should validate using warn',function(done){
|
258 | var obj = new ObjectManage()
|
259 | obj.validateGet = function(path,value){
|
260 | expect(path).to.equal('test1')
|
261 | this.warn(path + ' must be set to val2',value)
|
262 | }
|
263 | obj.once('warn',function(verb,message,path,value){
|
264 | expect(verb).to.equal('get')
|
265 | expect(message).to.equal('test1 must be set to val2')
|
266 | expect(path).to.equal('test1')
|
267 | expect(value).to.equal('val3')
|
268 | done()
|
269 | })
|
270 | obj.set('test1','val3')
|
271 | obj.get('test1')
|
272 | })
|
273 | it('should validate using error',function(done){
|
274 | var obj = new ObjectManage()
|
275 | obj.validateGet = function(path){
|
276 | expect(path).to.equal('test1')
|
277 | this.error(path + ' must be set to val2')
|
278 | }
|
279 | obj.once('error',function(verb,message,path,value){
|
280 | expect(verb).to.equal('get')
|
281 | expect(message).to.equal('test1 must be set to val2')
|
282 | expect(path).to.equal('test1')
|
283 | expect(value).to.equal('val3')
|
284 | done()
|
285 | })
|
286 | obj.set('test1','val3')
|
287 | expect(function(){obj.get('test1')}).to.throw('test1 must be set to val2')
|
288 | })
|
289 | it('should validate using ok',function(done){
|
290 | var obj = new ObjectManage()
|
291 | obj.validateGet = function(path){
|
292 | expect(path).to.equal('test1')
|
293 | this.ok('val4')
|
294 | }
|
295 | obj.once('get',function(path,value){
|
296 | expect(path).to.equal('test1')
|
297 | expect(value).to.equal('val4')
|
298 | done()
|
299 | })
|
300 | obj.set('test1','val3')
|
301 | obj.get('test1')
|
302 | })
|
303 | it('should validate using return',function(done){
|
304 | var obj = new ObjectManage()
|
305 | obj.validateGet = function(path){
|
306 | expect(path).to.equal('test1')
|
307 | return 'val4'
|
308 | }
|
309 | obj.once('get',function(path,value){
|
310 | expect(path).to.equal('test1')
|
311 | expect(value).to.equal('val4')
|
312 | done()
|
313 | })
|
314 | obj.set('test1','val3')
|
315 | obj.get('test1')
|
316 | })
|
317 | })
|
318 |
|
319 | describe('Circular Reference Handling',function(){
|
320 | it('should fail on circular referenced objects',function(){
|
321 | var x = {
|
322 | 'a' : function () {return null}
|
323 | }
|
324 | x.b = x.a
|
325 | var obj = new ObjectManage()
|
326 | function load(){
|
327 | obj.load(x)
|
328 | }
|
329 | expect(load).to.throw(Error)
|
330 | })
|
331 | it('should work using merge-recursive',function(){
|
332 | var obj = new ObjectManage()
|
333 | obj.merge = ObjectManage.prototype.mergeRecursive
|
334 | obj.load(data1)
|
335 | obj.load(data3)
|
336 | expect(obj.get('test5.test6')).to.equal('val6')
|
337 | })
|
338 | it('should count object depth accurately',function(){
|
339 | var testObject = {foo: {foo: {foo: 'baz'}}}
|
340 | , obj = new ObjectManage()
|
341 | expect(obj.countDepth(testObject)).to.equal(3)
|
342 | })
|
343 | it('should warn on objects more than 50 levels deep',function(){
|
344 |
|
345 | var oldLog = console.log
|
346 | , oldTrace = console.trace
|
347 | , log = []
|
348 | , traced = false
|
349 | console.log = function(msg){
|
350 | log.push(msg)
|
351 | }
|
352 | console.trace = function(){
|
353 | traced = true
|
354 | }
|
355 | var buildObject = function(object,depth,count){
|
356 | if(undefined === object) object = {}
|
357 | if(undefined === count) count = 1
|
358 | if(undefined === depth) depth = 100
|
359 | if(count > depth) return object
|
360 | object[count] = buildObject(object[count],depth,(count + 1))
|
361 | return object
|
362 | }
|
363 |
|
364 | var badObject = buildObject()
|
365 | , obj = new ObjectManage()
|
366 |
|
367 | expect(obj.countDepth(badObject)).to.equal(obj.maxDepth)
|
368 |
|
369 | var oldMaxDepth = obj.maxDepth
|
370 | obj.maxDepth = 20
|
371 | expect(obj.countDepth(badObject)).to.equal(20)
|
372 |
|
373 | obj.maxDepth = oldMaxDepth
|
374 |
|
375 | obj.load(badObject)
|
376 |
|
377 | expect(log[0]).to.equal('WARN [object-manage]: Object being merged is too deep (50)')
|
378 | expect(traced).to.equal(true)
|
379 |
|
380 | log = []
|
381 | traced = false
|
382 |
|
383 | obj.maxDepth = 10
|
384 |
|
385 | obj.load(badObject)
|
386 | expect(log[0]).to.equal('WARN [object-manage]: Object being merged is too deep (10)')
|
387 | expect(traced).to.equal(true)
|
388 |
|
389 | console.log = oldLog
|
390 | console.trace = oldTrace
|
391 | })
|
392 | })
|
393 |
|
394 | }) |
\ | No newline at end of file |