1 | bus = require('../statebus')()
|
2 | util = require('util')
|
3 | fs = require('fs')
|
4 | bus.label = 'bus'
|
5 | statelog_indent++
|
6 |
|
7 |
|
8 | var {test, run_tests, log, assert, delay} = require('../statebus').testing
|
9 |
|
10 |
|
11 | try {
|
12 | var reqs = 'sockjs chokidar websocket bcrypt-nodejs'.split(' ')
|
13 | for (var i=0; i<reqs.length; i++) require(reqs[i])
|
14 | } catch (e) {
|
15 | console.log(e)
|
16 | console.warn('#### Yo! You need to run "npm install sockjs chokidar websocket bcrypt-nodejs"')
|
17 | process.exit()
|
18 | }
|
19 |
|
20 |
|
21 |
|
22 | test(function equality (done) {
|
23 | var equality_tests = [
|
24 | [1, 1, true],
|
25 | [1, 3, false],
|
26 | [NaN, NaN, true],
|
27 | [NaN, undefined, false],
|
28 | [null, {}, false],
|
29 | [null, null, true],
|
30 | [[], [], true],
|
31 | [{}, [], false],
|
32 | [{}, {}, true],
|
33 | [[1], [], false],
|
34 | [[1], [1], true],
|
35 | [[1], [1, 1], false],
|
36 | [[{}], [{}], true],
|
37 | [{a:[]}, {a:[]}, true],
|
38 | [{a:[]}, {}, false],
|
39 | [[[[]]], [[[]]], true],
|
40 | [[[[]]], [[[[]]]], false],
|
41 | [[[{a:3,b:4}]], [[{b:4,a:3}]], true],
|
42 | [[[{a:3,b:4}]], [[{b:4,a:4}]], false],
|
43 | [function () {}, function () {}, false],
|
44 | [require, require, true],
|
45 | [require, function () {}, false],
|
46 | [{key:'f'}, {key:'f'}, true]
|
47 | ]
|
48 |
|
49 | for (var i=0; i<equality_tests.length; i++) {
|
50 | assert(bus.deep_equals(equality_tests[i][0],
|
51 | equality_tests[i][1])
|
52 | === equality_tests[i][2],
|
53 | 'Equality test failed forward', equality_tests[i])
|
54 |
|
55 | assert(bus.deep_equals(equality_tests[i][1],
|
56 | equality_tests[i][0])
|
57 | === equality_tests[i][2],
|
58 | 'Equality test failed backward', equality_tests[i])
|
59 | }
|
60 |
|
61 | done()
|
62 | })
|
63 |
|
64 | test(function validation (done) {
|
65 | var v_tests = [
|
66 | ['something', 'string', true],
|
67 | ['something', 'something', true],
|
68 | ['something', 3, false],
|
69 | [3, 3, true],
|
70 | [3, 'number', true],
|
71 | [3, 'string', false],
|
72 | [3, {}, false],
|
73 | [3, [], false],
|
74 | [{}, {}, true],
|
75 | [{}, {'key': 'string'}, false],
|
76 | [{}, {'?key': 'string'}, true],
|
77 | [{key: 3}, {'?key': 'string'}, false],
|
78 | [{key: '/foo'}, {key: 'string'}, true],
|
79 | [{a: 2, b: [], c: 'foo'}, {a: 'number', b: 'array', c: 'string'}, true],
|
80 | [{a: 2, b: [], c: 'foo', d: false}, {a: 'number', b: 'array', c: 'string'}, false],
|
81 | [{a: false}, {a: 'boolean'}, true],
|
82 | [{a: 1, b: 2}, {a: 1}, false],
|
83 | [{a: 1, b: 2}, {a: 1, '*':'*'}, true],
|
84 | [{a: 2, b: 2}, {a: 1, '*':'*'}, false]
|
85 | ]
|
86 |
|
87 | for (var i=0; i<v_tests.length; i++)
|
88 | assert(bus.validate(v_tests[i][0], v_tests[i][1]) === v_tests[i][2],
|
89 | 'Validation test failed', v_tests[i])
|
90 |
|
91 | done()
|
92 | })
|
93 |
|
94 | test(function applying_patches (done) {
|
95 | var tests = [
|
96 | ['0', '[0] = "1"', '1'],
|
97 | [['0'], '[0] = "1"', ['1']],
|
98 | [['0'], '[0] = [1]', [[1]]],
|
99 | ['', '[0:0] = "something"', 'something'],
|
100 | ['hello', '[-0:-0] = " there"', 'hello there'],
|
101 | [{}, '.foo = "bar"', {foo: 'bar'}],
|
102 | [{a:1}, '.a = true', {a: true}],
|
103 | [[1,2,3], '[1:1] = [4, 5, 6]', [1, 4, 5, 6, 2, 3]],
|
104 | [[1,2,3], '[-0:-0] = 0', [1, 2, 3, 0]],
|
105 | [[1,2,3], '[-1] = 0', [1, 2, 0]],
|
106 | [[1,2,3], '[-1:-0] = [0]', [1, 2, 0]],
|
107 | [[1,2,3], '[-1:-0] = [0, 0, 0]', [1, 2, 0, 0, 0]]
|
108 | ]
|
109 |
|
110 | for (var i=0; i<tests.length; i++) {
|
111 | var x = bus.apply_patch(tests[i][0], tests[i][1])
|
112 | assert(bus.deep_equals(x, tests[i][2]),
|
113 | `Patch applied wrong ${JSON.stringify(tests[i])} got ${x}`)
|
114 | }
|
115 | done()
|
116 | })
|
117 |
|
118 | test(function prune (done) {
|
119 | var boose = require('../statebus')()
|
120 | boose.save({key: 'nark', _: 333666})
|
121 | var a = {key: 'funny',
|
122 | b: {key: 'farty', booger: 3}}
|
123 | assert(!boose.prune(a).b.booger)
|
124 | var b = {key: 'farty',
|
125 | a: a,
|
126 | arr: [1, 3, a, {key: 'nark', ___: 999}]}
|
127 | done()
|
128 | })
|
129 |
|
130 | test(function auto_vars (done) {
|
131 | var n = require('../statebus')()
|
132 | n('r/*').to_fetch = function (rest, o) {return {rest: rest, o: o}}
|
133 | log(n.fetch('r/3'))
|
134 | assert(n.fetch('r/3').rest === '3')
|
135 | assert(n.fetch('r/3').o === undefined)
|
136 |
|
137 | n('v/*').to_fetch = function (vars, star) {return {vars: vars, rest: star}}
|
138 | log(n.fetch('v/[3,9 4]').rest)
|
139 | log(n.fetch('v/[3,9 4]').rest.match(/$Bad/))
|
140 | assert(n.fetch('v/[3,9 4]').rest === '[3,9 4]')
|
141 |
|
142 | log(n.fetch('v/[3,9 4]').vars)
|
143 | log(n.fetch('v/[3,9 4]').vars.match(/^Bad/))
|
144 | assert(n.fetch('v/[3,9 4]').vars.match(/^Bad/))
|
145 | assert(Array.isArray(n.fetch('v/[3,4]').vars))
|
146 |
|
147 | n('a/*').to_save = function (t, k, obj) {
|
148 | log('k:', k, 't:', t, 'o:', obj)
|
149 | assert(k === 'a/foo')
|
150 | assert(typeof obj === 'object')
|
151 | assert(obj.i >= 0 && obj.i <= 4)
|
152 | assert(Object.keys(obj).length === 2)
|
153 | assert(t.version)
|
154 | t.done()
|
155 | }
|
156 | for (var i=0; i<4; i++)
|
157 | n.save({key: 'a/foo', i:i})
|
158 |
|
159 | log('Forgetting things now')
|
160 | n('v/*').to_forget = function (vars, star) {log('(from auto_vars) forgot v/' + star)}
|
161 | n.forget('v/[3,9 4]')
|
162 | n.forget('v/[3,4]')
|
163 |
|
164 | done()
|
165 | })
|
166 |
|
167 | test(function serve_options (done) {
|
168 | var filename = 'test1.db', backups = 'test1.backups', certs = 'testcerts'
|
169 |
|
170 |
|
171 | try {
|
172 |
|
173 | fs.unlinkSync(filename)
|
174 |
|
175 |
|
176 | fs.readdirSync(backups).forEach((f) => {
|
177 | fs.unlinkSync(backups + "/" + f);
|
178 | })
|
179 | fs.rmdirSync(backups)
|
180 |
|
181 |
|
182 |
|
183 |
|
184 |
|
185 |
|
186 | } catch (e) {log(e)}
|
187 |
|
188 | var b = require('../statebus').serve({
|
189 | port: 31829,
|
190 |
|
191 | file_store: {filename: filename, save_delay: 0, backup_dir: backups},
|
192 | certs: {private_key: certs+'/pk', certificate: certs+'/cert'},
|
193 | })
|
194 |
|
195 | b.save({key: 'foo', body: 'is this on disk?'})
|
196 | setTimeout(() => done(), 60)
|
197 | })
|
198 |
|
199 | test(function transactions (done) {
|
200 | var bus = require('../statebus')()
|
201 | bus.honk = 'statelog'
|
202 | bus.label = 'tranny'
|
203 |
|
204 |
|
205 | bus('foo1').to_fetch = function (t) {
|
206 | log('to_fetching foo1')
|
207 | setTimeout(()=>{
|
208 | log('returning something for foo1')
|
209 | t.done({something: 'yeah'})
|
210 | }, 0)
|
211 | }
|
212 | var foo1 = bus.fetch('foo1')
|
213 | assert(!foo1.something)
|
214 | setTimeout(() => { log('test foo1'); assert(foo1.something === 'yeah') }, 10)
|
215 |
|
216 |
|
217 | bus('foo2').to_fetch = (t) => { return {something: 'yeah'} }
|
218 | var foo2 = bus.fetch('foo2')
|
219 | setTimeout(() => { log('test foo2'); assert(foo2.something === 'yeah') }, 10)
|
220 |
|
221 |
|
222 |
|
223 | log('Set up some rocks')
|
224 | bus.save({key: 'rock1', a:1})
|
225 | bus.save({key: 'rock2', a:1})
|
226 | bus.save({key: 'softrock1', a:1})
|
227 | bus.save({key: 'softrock2', a:1})
|
228 |
|
229 |
|
230 | bus('rock1').to_save = (t) => {setTimeout(()=>{ t.abort() }, 0)}
|
231 | bus('rock2').to_save = ( ) => {return 'abort'}
|
232 | bus('softrock1').to_save = (t) => {setTimeout(()=>{ t.done() }, 0)}
|
233 | bus('softrock2').to_save = ( ) => {return 'done'}
|
234 |
|
235 |
|
236 | setTimeout(() => {
|
237 | log('Save some changes')
|
238 | bus.save({key: 'rock1', a:2})
|
239 | bus.save({key: 'rock2', a:2})
|
240 | bus.save({key: 'softrock1', a:2})
|
241 | bus.save({key: 'softrock2', a:2})
|
242 |
|
243 | setTimeout(() => {
|
244 | log('Check if the saves worked...')
|
245 | assert(bus.cache.rock1.a == 1)
|
246 | assert(bus.cache.rock2.a == 1)
|
247 | assert(bus.cache.softrock1.a == 2)
|
248 | assert(bus.cache.softrock2.a == 2)
|
249 |
|
250 |
|
251 | log("Now let's delete")
|
252 | bus('rock1').to_delete = (t) => {setTimeout(()=>{ t.abort() }, 0)}
|
253 | bus('rock2').to_delete = ( ) => {return 'abort'}
|
254 | bus('softrock1').to_delete = (t) => {setTimeout(()=>{ t.done() }, 0)}
|
255 | bus('softrock2').to_delete = ( ) => {return 'done'}
|
256 |
|
257 | log('Delete some rocks')
|
258 | bus.delete('rock1')
|
259 | bus.delete('rock2')
|
260 | bus.delete('softrock1')
|
261 | bus.delete('softrock2')
|
262 |
|
263 | setTimeout(() => {
|
264 | log("Test if the deletes worked")
|
265 | assert(bus.cache.rock1)
|
266 | assert(bus.cache.rock2)
|
267 | assert(!bus.cache.softrock1)
|
268 | assert(!bus.cache.softrock2)
|
269 | done()
|
270 | }, 10)
|
271 |
|
272 | }, 10)
|
273 | }, 20)
|
274 | })
|
275 |
|
276 | test(function url_translation (done) {
|
277 | var tests = [
|
278 | ['foo', 'foo'],
|
279 | [['a', 'b'], ['a', 'b']],
|
280 | [{key: 'a'}, {key: '/a'}],
|
281 | [{key: 'a', f: '3'}, {key: '/a', f: '3'}],
|
282 | [{a: {b: {key: 'a'}}}, {a: {b: {key: '/a'}}}],
|
283 | [{a: {b: {_key: ['a', 'b']}}}, {a: {b: {_key: ['/a', '/b']}}}],
|
284 | [{a: {b: {bombs_key: ['a', 1]}}}, {a: {b: {bombs_key: ['/a', 1]}}}],
|
285 | [{a: {b: {_key: ['a', {_key: 'b'}]}}}, {a: {b: {_key: ['/a', {_key: '/b'}]}}}],
|
286 | [{a: ['a', {_key: 'b'}]}, {a: ['a', {_key: '/b'}]}],
|
287 | ]
|
288 | for (var i=0; i<tests.length; i++) {
|
289 | log('Testing', i, JSON.stringify(tests[i][0]))
|
290 | var trans = bus.translate_keys(tests[i][0], function (k) {return '/' + k})
|
291 | assert(bus.deep_equals(trans, tests[i][1]),
|
292 | 'Bad translation: ' + JSON.stringify(trans))
|
293 | }
|
294 | done()
|
295 | })
|
296 |
|
297 | test(function basics (done) {
|
298 | bus('basic wait').to_fetch = function () {
|
299 | setTimeout(function () {bus.save.fire({key:'basic wait', a:1})},
|
300 | 30)
|
301 | }
|
302 |
|
303 | var count = 0
|
304 | bus(function () {
|
305 | var v = bus.fetch('basic wait')
|
306 | log('On round', count, 'we see', v)
|
307 | if (count == 0)
|
308 | assert(!v.a)
|
309 | if (count == 1) {
|
310 | assert(v.a)
|
311 | bus.forget()
|
312 | done()
|
313 | }
|
314 | count++
|
315 | })
|
316 | })
|
317 |
|
318 |
|
319 | test(function multiple_handlers1 (done) {
|
320 | var cuss = require('../statebus')()
|
321 | cuss('foo').to_fetch = () => {log('do nothing 1')}
|
322 | cuss('foo').to_fetch = () => {log('do nothing 2')}
|
323 | cuss('foo').to_fetch = () => (log('doing something'),{b: 3})
|
324 | cuss.fetch('foo', (o) => {
|
325 | log('Multi-handle got', o)
|
326 | cuss.forget()
|
327 | setTimeout(()=>{done()})
|
328 | })
|
329 | })
|
330 |
|
331 | test(function multiple_handlers2 (done) {
|
332 | var cuss = require('../statebus')()
|
333 | cuss('foo').to_save = (o) => {log('do nothing 1')}
|
334 | cuss('foo').to_save = (o) => {log('do nothing 2')}
|
335 | cuss('foo').to_save = (o) => {log('doin something'); cuss.save.fire(o)}
|
336 |
|
337 | cuss.save({key: 'foo', b: 55})
|
338 | log('over and out')
|
339 | setTimeout(()=>{done()})
|
340 | })
|
341 |
|
342 |
|
343 | test(function fetch_with_callback (done) {
|
344 | var count = 0
|
345 |
|
346 | function bbs() {
|
347 | return bus.bindings('bar', 'on_save').map(
|
348 | function (f){return bus.funk_name(f)})
|
349 | }
|
350 | function cb (o) {
|
351 | count++
|
352 |
|
353 | var bar = bus.fetch('bar')
|
354 | log('cb called', count, 'times', 'bar is', bar, 'foo is', o)
|
355 |
|
356 | }
|
357 |
|
358 |
|
359 |
|
360 |
|
361 | bus.fetch('foo', cb)
|
362 |
|
363 |
|
364 | setTimeout(function () {
|
365 | assert(count === 1, '1!=' + count)
|
366 |
|
367 |
|
368 | log('firing a new foo')
|
369 |
|
370 | bus.save.fire({key: 'foo', count:count})
|
371 | }, 30)
|
372 |
|
373 |
|
374 | setTimeout(function () {
|
375 | log('firing a new bar')
|
376 |
|
377 | assert(count === 2, '2!=' + count)
|
378 | bus.honk = true
|
379 | bus.save.fire({key: 'bar', count:count})
|
380 | log('fired the new bar')
|
381 |
|
382 | }, 50)
|
383 |
|
384 |
|
385 | setTimeout(function () {
|
386 | assert(count === 2, '2!=' + count)
|
387 | bus.forget('foo', cb)
|
388 |
|
389 | done()
|
390 | }, 100)
|
391 | })
|
392 |
|
393 | test(function fetch_once (done) {
|
394 | var calls = 0
|
395 | bus.fetch('fetch_once', function cb (o) {
|
396 | calls++
|
397 | log('Fetch_once called', calls)
|
398 | assert(calls < 2, 'Fetch-once called twice')
|
399 | bus.forget('fetch_once', cb)
|
400 | })
|
401 | bus.save.fire({key: 'fetch_once', _: 0})
|
402 | setTimeout(()=> { bus.save.fire({key: 'fetch_once', _: 1}) }, 10)
|
403 | setTimeout(()=> { bus.save.fire({key: 'fetch_once', _: 2}) }, 20)
|
404 | setTimeout(()=> { done() }, 30 )
|
405 | })
|
406 |
|
407 | test(function once (done) {
|
408 | bus('takeawhile').to_fetch = (t) => {
|
409 | setTimeout(_=> t.return({_: 3}), 150)
|
410 | }
|
411 | bus.once(_=> {
|
412 | var x = bus.fetch('takeawhile')
|
413 | var y = bus.fetch('changing')
|
414 | log('running the once func! loading is', bus.loading())
|
415 | assert(!bus.cache.certified)
|
416 | bus.save({key: 'whendone', certified: true})
|
417 | })
|
418 |
|
419 | delay(50, _=> assert(!bus.fetch('whendone').certified))
|
420 | delay(10, _=> bus.save({key: 'changing', _: 1}))
|
421 | delay(10, _=> bus.save({key: 'changing', _: 2}))
|
422 | delay(150, _=> assert(bus.fetch('whendone').certified))
|
423 | delay(10, _=> bus.save({key: 'changing', _: 3}))
|
424 | delay(10, _=> bus.save({key: 'changing', _: 4}))
|
425 | delay(30, _=> done())
|
426 | })
|
427 |
|
428 |
|
429 |
|
430 | test(function fetch_remote (done) {
|
431 | var count = 0
|
432 |
|
433 |
|
434 | bus('moon').to_fetch =
|
435 | function (k) { setTimeout(function () {bus.save.fire({key:k})},30) }
|
436 | function cb (o) {
|
437 | count++
|
438 | var moon = bus.fetch('hey over there')
|
439 | log('cb called', count, 'times')
|
440 | }
|
441 |
|
442 |
|
443 | bus.fetch('moon', cb)
|
444 | assert(count === 0, '0!=' + count)
|
445 |
|
446 |
|
447 | setTimeout(function () {
|
448 | assert(count === 1, '1!=' + count)
|
449 | bus.forget('moon', cb)
|
450 | done()
|
451 | }, 50)
|
452 | })
|
453 |
|
454 |
|
455 | test(function duplicate_fires (done) {
|
456 | var calls = new Set()
|
457 | var count = 0
|
458 | var dupes = []
|
459 | function cb (o) {
|
460 | count++
|
461 | if (calls.has(o.n)) dupes.push(o.n)
|
462 | calls.add(o.n)
|
463 | log('cb called', count, 'times with', calls)
|
464 | }
|
465 |
|
466 |
|
467 | bus.fetch('foo', cb)
|
468 | assert(count === 1, '1!=' + count)
|
469 |
|
470 |
|
471 | setTimeout(function () {
|
472 | log('Firing a few new foos')
|
473 | bus.save.fire({key: 'foo', n:0})
|
474 | bus.save.fire({key: 'foo', n:1})
|
475 | bus.save.fire({key: 'foo', n:2})
|
476 | bus.save.fire({key: 'foo', n:3})
|
477 | log("ok, now let's see what happens.")
|
478 | }, 30)
|
479 |
|
480 |
|
481 | setTimeout(function () {
|
482 | assert(count === 2, '2!=' + count)
|
483 | assert(dupes.length === 0, 'CB got duplicate calls', dupes)
|
484 | log('Well, that went smoothly!')
|
485 | bus.forget('foo', cb)
|
486 |
|
487 | done()
|
488 | }, 60)
|
489 | })
|
490 |
|
491 |
|
492 | test(function identity (done) {
|
493 | var key = 'kooder'
|
494 | var count = 0
|
495 | function fire () { bus.save.fire({key: 'kooder', count: count}) }
|
496 | bus(key).to_fetch = function () { setTimeout(fire, 10) }
|
497 | function cb() {
|
498 | count++
|
499 | log('cb called', count, 'times')
|
500 | bus.save.fire(bus.fetch('new'))
|
501 | }
|
502 | bus.fetch(key, cb)
|
503 |
|
504 |
|
505 | setTimeout(function () {
|
506 |
|
507 |
|
508 |
|
509 | assert(count === 1, 'cb called '+count+'!=1 times')
|
510 | bus.forget(key, cb)
|
511 | bus(key).to_fetch.delete(fire)
|
512 | done()
|
513 | }, 40)
|
514 | })
|
515 |
|
516 |
|
517 |
|
518 | test(function forgetting (done) {
|
519 | var key = 'kooder'
|
520 | var count = 0
|
521 | function fire () { log('firing!'); bus.save.fire({key: key, count: count}) }
|
522 | bus(key).to_fetch = function () { setTimeout(fire, 10) }
|
523 |
|
524 | function cb (o) {
|
525 | count++
|
526 | log('cb2 called', count, 'times', 'on', o)
|
527 |
|
528 | if (count > 2) assert(false, 'cb2 too many calls')
|
529 | if (count > 1) {
|
530 | log('cb2 forgetting', key)
|
531 | bus.forget(key, cb)
|
532 | log('forgot.')
|
533 | }
|
534 | }
|
535 |
|
536 | bus.fetch(key, cb)
|
537 | setTimeout(fire, 70)
|
538 | setTimeout(fire, 80)
|
539 |
|
540 |
|
541 | setTimeout(function () {
|
542 | assert(count === 2, "Count should be 2 but is", count)
|
543 | bus(key).to_fetch.delete(fire)
|
544 | done()
|
545 | }, 100)
|
546 | })
|
547 |
|
548 |
|
549 | test(function nested_fetch (done) {
|
550 | function outer () { return {inner: bus.fetch('inner') } }
|
551 | bus('outer').to_fetch = outer
|
552 | log('fetching the outer wrapper')
|
553 | var obj = bus.fetch('outer')
|
554 | log('Ok, we fetched:', obj)
|
555 | assert(obj.inner.key === 'inner')
|
556 | bus.save({key: 'inner', c: 1})
|
557 | assert(obj.inner.c === 1)
|
558 |
|
559 | log('vvv Grey line follows (cause outer fetched inner) vvv')
|
560 |
|
561 |
|
562 | setTimeout(function () {
|
563 | bus('outer').to_fetch.delete(outer)
|
564 | done()
|
565 | }, 10)
|
566 | })
|
567 |
|
568 |
|
569 | test(function russian_doll_nesting (done) {
|
570 | var nothing = 3
|
571 | function big () { return {middle: bus.fetch('middle') } }
|
572 | function middle () { return {small: bus.fetch('small') } }
|
573 | function small () { return {nothing: nothing} }
|
574 | bus('big').to_fetch = big
|
575 | bus('middle').to_fetch = middle
|
576 | bus('small').to_fetch = small
|
577 |
|
578 | log('fetching')
|
579 | var obj = bus.fetch('big')
|
580 | log('we got', obj)
|
581 |
|
582 | setTimeout(function () {
|
583 | bus.fetch('big', function (o) {
|
584 | nothing = 5
|
585 | log('About to update small')
|
586 | bus.save.fire({key: 'small', something: nothing})
|
587 | log('We did it.')
|
588 | })}, 10)
|
589 |
|
590 | setTimeout(function () {
|
591 | bus.fetch('big', function ruskie (o) {
|
592 | nothing = 50
|
593 | var small = bus.fetch('small')
|
594 | log()
|
595 | log('Second try. Small starts as', small)
|
596 | bus.save.fire({key: 'small', something: nothing})
|
597 | log('Now it is', bus.fetch('small'))
|
598 | })}, 15)
|
599 |
|
600 |
|
601 |
|
602 | setTimeout(function () {
|
603 | bus('big').to_fetch.delete(big)
|
604 | bus('middle').to_fetch.delete(middle)
|
605 | bus('small').to_fetch.delete(small)
|
606 | done()
|
607 | }, 50)
|
608 | })
|
609 |
|
610 | test(function some_handlers_suicide (done) {
|
611 |
|
612 |
|
613 |
|
614 |
|
615 |
|
616 |
|
617 |
|
618 |
|
619 |
|
620 |
|
621 |
|
622 | done()
|
623 | })
|
624 |
|
625 | test(function uncallback (done) {
|
626 | try {
|
627 | var chokidar = require('chokidar')
|
628 | } catch (e) {
|
629 | console.warn('#### Yo! You need to run "npm install chokidar"')
|
630 | process.exit()
|
631 | }
|
632 |
|
633 | var watchers = {}
|
634 | function read_file (filename, cb) {
|
635 | fs.readFile(filename, function (err, result) {
|
636 | if (err) throw err
|
637 | else cb(null, result + '')
|
638 | })
|
639 | }
|
640 |
|
641 | read_file = bus.uncallback(read_file, {
|
642 | start_watching: (args, dirty, del) => {
|
643 | var filename = args[0]
|
644 | assert(!(filename in watchers), 'WTF... the file ' + filename + ' is already being watched?')
|
645 | watchers[filename] = chokidar.watch(filename)
|
646 | watchers[filename].on('change', () => { bus.dirty(this.key) })
|
647 | },
|
648 | stop_watching: (json) => {
|
649 | filename = json[0]
|
650 | log('unwatching', filename)
|
651 |
|
652 | watchers[filename].close()
|
653 | delete watchers[filename]
|
654 | }})
|
655 |
|
656 | fs.writeFileSync('/tmp/blah', 'foo')
|
657 |
|
658 | bus.honk = 3
|
659 | var runs = 0
|
660 | bus(() => {
|
661 | runs++
|
662 | var result = read_file('/tmp/blah')
|
663 | log('read file as', JSON.stringify(result && result.substr(0,50)))
|
664 |
|
665 | if (bus.loading())
|
666 | log('Still loading!')
|
667 | else
|
668 | if (result == '1' || result == '2' || result == '3') {
|
669 | log('done. forgetting')
|
670 | bus.forget()
|
671 | }
|
672 |
|
673 | switch(runs) {
|
674 | case 1:
|
675 | console.assert(result == undefined); break
|
676 | case 2:
|
677 | console.assert(result == 'foo'); break
|
678 | case 3:
|
679 | case 4:
|
680 | console.assert(result == '1' || result == '2' || result == '3'); break;
|
681 | }
|
682 | })
|
683 |
|
684 | delay(10, () => {log('* MODIFY 1'); fs.writeFileSync('/tmp/blah', '1')})
|
685 | delay(200, () => {log('* MODIFY 2'); fs.writeFileSync('/tmp/blah', '2')})
|
686 | delay(200, () => {log('* MODIFY 3'); fs.writeFileSync('/tmp/blah', '3')})
|
687 |
|
688 | delay(200, () => {console.assert(runs < 4, 'There were', runs, 'runs'); done()})
|
689 | })
|
690 |
|
691 | test(function readfile (done) {
|
692 | var b = require('../statebus')(),
|
693 | count = 0
|
694 |
|
695 | fs.writeFileSync('/tmp/blah', '1')
|
696 | b(() => {
|
697 | var r = b.read_file('/tmp/blah')
|
698 | log('Got', r, 'at count', count)
|
699 | switch(count++) {
|
700 | case 0:
|
701 | console.assert(r === undefined); break
|
702 | case 1:
|
703 | console.assert(r === '1'); break
|
704 | case 2:
|
705 | console.assert(r === '2'); b.forget(); break
|
706 | case 3:
|
707 | console.assert(false); break
|
708 | }
|
709 | })
|
710 |
|
711 | delay(300, () => {log('* MODIFY 2'); fs.writeFileSync('/tmp/blah', '2')})
|
712 | delay(300, () => {log('* MODIFY 3'); fs.writeFileSync('/tmp/blah', '3')})
|
713 | delay(200, () => {done()})
|
714 | })
|
715 |
|
716 | test(function proxies (done) {
|
717 | var bus = require('../statebus')()
|
718 | db = bus.sb
|
719 | db.foo.a = 3
|
720 | assert(db.foo.a == 3)
|
721 | db.foo.a = [1,3,5, 'hello']
|
722 | db.foo.a.push({key: 'bar', 4:4})
|
723 |
|
724 |
|
725 |
|
726 |
|
727 |
|
728 | log('Now foo is', db.foo)
|
729 | log('And bar is', db.bar)
|
730 |
|
731 | db.f = 3
|
732 | assert(bus.validate(bus.cache['f'], {key: 'f', _: 3}),
|
733 | bus.cache['f'], 'should be', {key: 'f', _: 3})
|
734 | assert(db.f === 3)
|
735 |
|
736 | db.g = [1,2,4,5]
|
737 | assert(bus.cache['g']._.length = 4)
|
738 |
|
739 | done()
|
740 | })
|
741 |
|
742 | test(function proxies2 (done) {
|
743 | var bus = require('../statebus')()
|
744 | var state = bus.state
|
745 |
|
746 | assert(state.array === undefined)
|
747 | assert(state.bar === undefined)
|
748 |
|
749 | state.array = []
|
750 | log('array:', state.array)
|
751 | assert(state.array.length === 0)
|
752 | state.array[0] = 1
|
753 | log('array:', state.array)
|
754 | assert(state.array.length === 1)
|
755 | state.bar = {}
|
756 | log('bar:', state.bar)
|
757 | state.bar = {a: 1}
|
758 | log('bar:', state.bar)
|
759 | assert(state.bar.a === 1)
|
760 | state.bar.a = state.array
|
761 | log('bar:', state.bar)
|
762 | state.array[1] = 2
|
763 | log('array:', state.array)
|
764 | log('bar:', state.bar)
|
765 | assert(state.bar.a[1] === 2,
|
766 | "Array ref didn't link.\n\t"
|
767 | + JSON.stringify(bus.cache.bar) + '\n\t'
|
768 | + JSON.stringify(bus.cache.array))
|
769 |
|
770 | state.undefining = undefined
|
771 | assert(state.undefining === undefined)
|
772 | state.undefining = {a: undefined}
|
773 | log('state.undefining =', state.undefining)
|
774 |
|
775 |
|
776 | state.undefining = {}
|
777 | assert(!('a' in state.undefining))
|
778 | state.undefining.a = undefined
|
779 | assert('a' in state.undefining)
|
780 | assert(state.undefining.a === undefined)
|
781 |
|
782 | state.b = {a: undefined}
|
783 | assert('a' in state.b)
|
784 | assert(state.b.a === undefined)
|
785 | delete state.b.a
|
786 |
|
787 | assert(!('a' in state.b))
|
788 | assert(state.b.a === undefined)
|
789 |
|
790 | return done()
|
791 |
|
792 | |
793 |
|
794 |
|
795 |
|
796 |
|
797 |
|
798 |
|
799 |
|
800 |
|
801 |
|
802 |
|
803 |
|
804 |
|
805 |
|
806 | state.foo = 3
|
807 |
|
808 | console.assert(bus.validate(bus.cache.foo,
|
809 | {key: 'foo', _: 3}))
|
810 |
|
811 |
|
812 | state.foo = {a: 5}
|
813 |
|
814 | console.assert(bus.validate(bus.cache.foo,
|
815 | {key: 'foo', a: 5}))
|
816 | state.foo.b = 6
|
817 | console.assert(bus.validate(bus.cache.foo,
|
818 | {key: 'foo', b: 6}))
|
819 |
|
820 | state.bar = [3]
|
821 | state.foo = {a: 3, bar: state.bar}
|
822 |
|
823 | bus(() => {
|
824 | state.foo
|
825 | state.foo.bar
|
826 | state.foo.a
|
827 | })
|
828 |
|
829 |
|
830 | bus(() => {
|
831 | state.bar
|
832 | })
|
833 |
|
834 |
|
835 | })
|
836 |
|
837 | test(function only_one (done) {
|
838 | bus('only_one/*').to_fetch = function (k) {
|
839 | var id = k[k.length-1]
|
840 | return {selected: bus.fetch('selector').choice == id}
|
841 | }
|
842 |
|
843 | assert(!bus.fetch('only_one/1').selected)
|
844 | assert(!bus.fetch('only_one/2').selected)
|
845 | assert(!bus.fetch('only_one/3').selected)
|
846 |
|
847 | bus.save({key: 'selector', choice: 1})
|
848 |
|
849 | setTimeout(function () {
|
850 | assert( bus.fetch('only_one/1').selected)
|
851 | assert(!bus.fetch('only_one/2').selected)
|
852 | assert(!bus.fetch('only_one/3').selected)
|
853 |
|
854 | bus.save({key: 'selector', choice: 2})
|
855 | }, 10)
|
856 |
|
857 | setTimeout(function () {
|
858 | assert(!bus.fetch('only_one/1').selected)
|
859 | assert( bus.fetch('only_one/2').selected)
|
860 | assert(!bus.fetch('only_one/3').selected)
|
861 |
|
862 | bus.save({key: 'selector', choice: 3})
|
863 | }, 20)
|
864 |
|
865 | setTimeout(function () {
|
866 | assert(!bus.fetch('only_one/1').selected)
|
867 | assert(!bus.fetch('only_one/2').selected)
|
868 | assert( bus.fetch('only_one/3').selected)
|
869 | done()
|
870 | }, 30)
|
871 | })
|
872 |
|
873 | test(function save_can_trigger_tofetch (done) {
|
874 |
|
875 | bus('save_trigger_tofetch').to_fetch =
|
876 | function (k, old) {
|
877 | old.yes = Math.random()
|
878 | return old
|
879 | }
|
880 |
|
881 | var obj
|
882 | var triggered = 0
|
883 | bus(() => {
|
884 | log('Aight! Fetching save_trigger_fetch')
|
885 | obj = bus.fetch('save_trigger_tofetch')
|
886 | if (bus.loading()) return
|
887 | triggered++
|
888 | log('Triggered', triggered, 'times', obj)
|
889 |
|
890 |
|
891 | assert(triggered <= 4)
|
892 | log('GGGGGGGGGGGG')
|
893 | })
|
894 |
|
895 | delay(30, () => { log('savin 1!'); obj.a = 1; bus.save(obj) })
|
896 | delay(30, () => { log('savin 2!'); obj.a = 2; bus.save(obj) })
|
897 | delay(30, done)
|
898 | })
|
899 |
|
900 | test(function rollback_savefire (done) {
|
901 | var count = 0
|
902 | var error = false
|
903 | var phase = 0
|
904 |
|
905 | function wait () { setTimeout(function () {
|
906 | assert(phase++ === 1)
|
907 | log('Firing wait')
|
908 | bus.save.fire({key: 'wait', count: count})
|
909 | }, 50) }
|
910 | bus('wait').to_fetch = wait
|
911 |
|
912 |
|
913 | bus.save.fire({key: 'undo me', state: 'start'})
|
914 |
|
915 |
|
916 | bus(function () {
|
917 | log('Reaction', ++count, 'starting with state',
|
918 | bus.fetch('undo me').state, 'and loading =', bus.loading())
|
919 |
|
920 |
|
921 | var wait = bus.fetch('wait')
|
922 |
|
923 |
|
924 | bus.save.fire({key: 'undo me', state: 'progressing'})
|
925 |
|
926 | if (count === 1 && !bus.loading()) {
|
927 | log('### Error! We should be loading!')
|
928 | error = true
|
929 | }
|
930 | log('Done with this reaction')
|
931 | })
|
932 |
|
933 | assert(!error)
|
934 |
|
935 | var state = bus.cache['undo me'].state
|
936 | log('After first reaction, the state is', state)
|
937 | assert(state === 'start', 'The state did not roll back.')
|
938 |
|
939 |
|
940 | setTimeout(function () {
|
941 | assert(bus.cache['undo me'].state === 'start')
|
942 | assert(phase++ === 0, phase)
|
943 | },
|
944 | 40)
|
945 |
|
946 |
|
947 | setTimeout(function () {
|
948 | log('state is', bus.cache['undo me'].state)
|
949 | assert(bus.cache['undo me'].state === 'progressing')
|
950 | assert(phase++ === 2)
|
951 | },
|
952 | 60)
|
953 |
|
954 | setTimeout(function () {
|
955 | bus('wait').to_fetch.delete(wait)
|
956 | assert(phase === 3)
|
957 | done()
|
958 | }, 80)
|
959 | })
|
960 |
|
961 | test(function rollback_del (done) {
|
962 | bus('wait forever').to_fetch = function () {}
|
963 | bus.save.fire({key: 'kill me', alive: true})
|
964 |
|
965 |
|
966 | bus(function () {
|
967 | log('Doing a rollback on', bus.cache['kill me'])
|
968 | bus.fetch('wait forever')
|
969 | bus.del('kill me')
|
970 | })
|
971 | assert(bus.cache['kill me'].alive === true)
|
972 |
|
973 |
|
974 | bus(function () {
|
975 | log('Doing a real delete on', bus.cache['kill me'])
|
976 | bus.del('kill me')
|
977 | })
|
978 | assert(!('kill me' in bus.cache))
|
979 | log('Now kill me is', bus.cache['kill me'])
|
980 | done()
|
981 | })
|
982 |
|
983 | test(function rollback_save (done) {
|
984 | var saves = []
|
985 | var all_done = false
|
986 | bus('candy').to_save = function (o) {saves.push(o); bus.save.fire(o)}
|
987 | bus.save.fire({key: 'candy', flavor: 'lemon'})
|
988 |
|
989 | log('Trying some rollbacks starting with', bus.cache['candy'])
|
990 |
|
991 |
|
992 | bus(function () { if (all_done) return;
|
993 | log('Doing a rollback on bananafied candy')
|
994 | bus.fetch('wait forever')
|
995 | bus.save({key:'candy', flavor: 'banana'})
|
996 | log('...and the candy is', bus.cache['candy'])
|
997 |
|
998 | })
|
999 | assert(bus.cache['candy'].flavor === 'lemon')
|
1000 | assert(saves.length === 0)
|
1001 |
|
1002 |
|
1003 | bus(function () { if (all_done) return
|
1004 | log("Now we'll First we licoricize the", bus.cache['candy'])
|
1005 | bus.fetch('wait forever')
|
1006 | var candy = bus.fetch('candy')
|
1007 | candy.flavor = 'licorice'
|
1008 | log('...the candy has become', bus.cache['candy'])
|
1009 | bus.save(candy)
|
1010 | log('...and now it\'s rolled back to', bus.cache['candy'])
|
1011 | bus.forget('candy')
|
1012 | })
|
1013 | assert(bus.cache['candy'].flavor === 'lemon')
|
1014 | assert(saves.length === 0)
|
1015 |
|
1016 |
|
1017 | bus(function () {
|
1018 | log('Doing a real save on', bus.cache['candy'])
|
1019 | bus.save({key:'candy', flavor: 'orangina'})
|
1020 | })
|
1021 | assert(bus.cache['candy'].flavor = 'orangina')
|
1022 | assert(saves.length === 1, 'Saves.length 1 != '+saves.length)
|
1023 |
|
1024 | log('Now candy is', bus.cache['candy'])
|
1025 | all_done = true
|
1026 | done()
|
1027 | })
|
1028 |
|
1029 | test(function rollback_abort (done) {
|
1030 | var bus = require('../statebus')()
|
1031 | bus('foo').to_save = (o, t) => {t.abort()}
|
1032 | bus(()=> {
|
1033 | var o = bus.fetch('foo')
|
1034 | o.bar = 3
|
1035 | bus.save(o)
|
1036 | })
|
1037 | setTimeout(() => {
|
1038 | assert(!bus.cache.foo.bar)
|
1039 | done()
|
1040 | }, 40)
|
1041 | })
|
1042 |
|
1043 | test(function loading_quirk (done) {
|
1044 |
|
1045 |
|
1046 |
|
1047 |
|
1048 | bus('wait a sec').to_fetch = function (k) {
|
1049 | setTimeout(function () { bus.save.fire({key: k}) }, 50)
|
1050 | }
|
1051 |
|
1052 |
|
1053 | var loaded = false
|
1054 | var num_calls = 0
|
1055 | bus(function () {
|
1056 | num_calls++
|
1057 | log('called', num_calls, 'times')
|
1058 | bus.fetch('wait a sec')
|
1059 | loaded = !bus.loading()
|
1060 | })
|
1061 |
|
1062 |
|
1063 | setTimeout(function () {
|
1064 | assert(loaded, 'We never got loaded.')
|
1065 | assert(num_calls == 2,
|
1066 | 'We got called '+num_calls+'!=2 times')
|
1067 | done()
|
1068 | }, 100)
|
1069 | })
|
1070 |
|
1071 | test(function requires (done) {
|
1072 | try {
|
1073 | require.resolve('sockjs')
|
1074 | require.resolve('websocket')
|
1075 | } catch (e) {
|
1076 | console.warn('#### Yo! You need to run "npm install sockjs websocket"')
|
1077 | process.exit()
|
1078 | }
|
1079 | log('Ok good, we have the goods.')
|
1080 | done()
|
1081 | })
|
1082 |
|
1083 | test(function default_route (done) {
|
1084 | var b1 = require('../statebus')()
|
1085 | var b2 = require('../statebus')()
|
1086 | b1.shadows(b2)
|
1087 | b2.save({key: 'foo', bar: 3})
|
1088 | console.assert(b1.fetch('foo').bar)
|
1089 | log(b1.fetch('foo'))
|
1090 | log(b2.fetch('foo'))
|
1091 | b1.delete('foo')
|
1092 | log(b1.fetch('foo'))
|
1093 | log(b2.fetch('foo'))
|
1094 | console.assert(!b1.fetch('foo').bar)
|
1095 | console.assert(!b2.fetch('foo').bar)
|
1096 | done()
|
1097 | })
|
1098 |
|
1099 | test(function setup_server (done) {
|
1100 | s = require('../statebus').serve({port: 3948, file_store: false})
|
1101 | s.label = 's'
|
1102 | log('Saving /far on server')
|
1103 | s.save({key: 'far', away:'is this'})
|
1104 |
|
1105 | c = require('../statebus')()
|
1106 | c.label = 'c'
|
1107 | c.ws_client('/*', 'statei://localhost:3948')
|
1108 |
|
1109 |
|
1110 |
|
1111 |
|
1112 | setTimeout(function () {
|
1113 | log('Fetching /far on client')
|
1114 | var count = 0
|
1115 | c.fetch('/far', function (o) {
|
1116 | log('cb !!!!!!!!! --- ^_^')
|
1117 | c.fetch('/far')
|
1118 | if (o.away === 'is this') {
|
1119 | log('We got '+o.key+' from the server!')
|
1120 |
|
1121 | c.forget()
|
1122 | console.assert(count++ === 0, "Forget didn't work.")
|
1123 |
|
1124 | setTimeout(function () {done()})
|
1125 | }
|
1126 | })
|
1127 | }, 100)
|
1128 |
|
1129 | var matches = new Set()
|
1130 | for (var k in s.busses) {
|
1131 | log("Checking unique bus id", k, 'with name', s.busses[k].toString())
|
1132 | console.assert(!matches.has(k), 'duplicate bus id', k)
|
1133 | matches.add(k)
|
1134 | }
|
1135 | })
|
1136 |
|
1137 | test(function login (done) {
|
1138 | s.save({key: 'users',
|
1139 | all: [ { key: 'user/1',
|
1140 | name: 'mike',
|
1141 | email: 'toomim@gmail.com',
|
1142 | admin: true,
|
1143 | pass: '$2a$10$Ti7BgAZS8sB0Z62o2NKsIuCdmU3q9xP7jexVccTcG19Y8qpBpl/1y' }
|
1144 |
|
1145 | ,{ key: 'user/2',
|
1146 | name: 'j',
|
1147 | email: 'jtoomim@gmail.com',
|
1148 | admin: true,
|
1149 | pass: '$2a$10$Ti7BgAZS8sB0Z62o2NKsIuCdmU3q9xP7jexVccTcG19Y8qpBpl/1y' }
|
1150 |
|
1151 | ,{ key: 'user/3',
|
1152 | name: 'boo',
|
1153 | email: 'boo@gmail.com',
|
1154 | admin: false,
|
1155 | pass: '$2a$10$4UTjzf5OOGdkrCEsT.hO/.csKqf7u8mZ23ZT6stamBAWNV7u5WJuu' } ] })
|
1156 |
|
1157 | c(function () {
|
1158 | var u = c.fetch('/current_user')
|
1159 | if (u.logged_in) {
|
1160 | log('Yay! We are logged in as', u.user.name)
|
1161 | forget()
|
1162 | setTimeout(function () {done()})
|
1163 | } else
|
1164 | log("Ok... we aren't logged in yet. We be patient.")
|
1165 | })
|
1166 |
|
1167 | var u = c.fetch('/current_user')
|
1168 | u.login_as = {name: 'mike', pass: 'yeah'}
|
1169 | log('Logging in')
|
1170 | c.save(u)
|
1171 | })
|
1172 |
|
1173 | test(function wrong_password (done) {
|
1174 | var u = c.fetch('/current_user')
|
1175 | assert(u.logged_in && u.user.name == 'mike')
|
1176 | u.login_as = {name: 'j', pass: 'nah'}
|
1177 | c.save(u)
|
1178 | setTimeout(function () {
|
1179 | assert(!u.login_as, 'Aborted login needs to abort')
|
1180 | log('Good, the login failed.')
|
1181 | done()
|
1182 | }, 300)
|
1183 | })
|
1184 |
|
1185 | test(function create_account (done) {
|
1186 | assert(c.fetch('/current_user').logged_in)
|
1187 | var count = 0
|
1188 | c(function () {
|
1189 | count++
|
1190 | var u = c.fetch('/current_user')
|
1191 |
|
1192 | log('Phase', count, '(logged '+(u.logged_in?'in)':'out)'))
|
1193 |
|
1194 | switch (count) {
|
1195 | case 1:
|
1196 | log('In 1 - Logging out')
|
1197 | assert(u.logged_in, '1 not logged in')
|
1198 | u.logout = true; c.save(u)
|
1199 | break
|
1200 | case 2: break
|
1201 | case 3:
|
1202 |
|
1203 |
|
1204 |
|
1205 |
|
1206 |
|
1207 |
|
1208 |
|
1209 | log('In 3 - Creating bob, logging in as bob')
|
1210 | assert(!u.logged_in, '3 logged in')
|
1211 | u.create_account = {name: 'bob', email: 'b@o.b', pass: 'boob'}
|
1212 | c.save(u)
|
1213 |
|
1214 |
|
1215 | delete u.create_account
|
1216 |
|
1217 | u.login_as = {name: 'bob', pass: 'boob'}
|
1218 | c.save(u)
|
1219 | break
|
1220 | case 4: break
|
1221 | case 5:
|
1222 | log('In 5 - Logging out')
|
1223 | assert(u.logged_in)
|
1224 | assert(u.user.name === 'bob'
|
1225 | && u.user.email === 'b@o.b'
|
1226 | && u.user.pass === undefined
|
1227 | && u.user.key.match(/\/user\/.*/),
|
1228 | 'Bad user', u)
|
1229 |
|
1230 | log('Almost done 5')
|
1231 | u.logout = true; c.save(u)
|
1232 | log('Done 5')
|
1233 | break
|
1234 | case 6: break
|
1235 | case 7:
|
1236 | log('In 7 - Logging back in as boob')
|
1237 | assert(!u.logged_in, '7. still logged in, as', u)
|
1238 | u.login_as = {name: 'bob', pass:'boob'}
|
1239 | c.save(u)
|
1240 | break
|
1241 | case 8: break
|
1242 | case 9:
|
1243 | log('In 9 - Forget and finish.')
|
1244 | assert(u.logged_in, '9 not logged in')
|
1245 | forget()
|
1246 | setTimeout(function () {done()})
|
1247 | break
|
1248 | default:
|
1249 | assert(false)
|
1250 | break
|
1251 | }
|
1252 | })
|
1253 | })
|
1254 |
|
1255 | function connections_helper (done, port, options) {
|
1256 |
|
1257 | var s = require('../statebus').serve({port: port,
|
1258 | file_store: false,
|
1259 | connections: options})
|
1260 | s.label = 's'
|
1261 |
|
1262 |
|
1263 | var c1 = require('../statebus')()
|
1264 | c1.label = 'c1'
|
1265 | c1.ws_client('/*', 'statei://localhost:' + port)
|
1266 |
|
1267 | var c2 = require('../statebus')()
|
1268 | c2.label = 'c2'
|
1269 | c2.ws_client('/*', 'statei://localhost:' + port)
|
1270 |
|
1271 |
|
1272 | c1.c = c1.fetch('/connection')
|
1273 | c2.c = c2.fetch('/connection')
|
1274 | c1.all = c1.fetch('/connections')
|
1275 |
|
1276 | delay(50, _=> {
|
1277 |
|
1278 | log('c1.c:', c1.c)
|
1279 | log('c2.c:', c2.c)
|
1280 | log('all:', c1.all)
|
1281 | assert(c1.c.id)
|
1282 | assert(c2.c.id)
|
1283 |
|
1284 |
|
1285 | c1.c1 = c1.fetch('/connection/' + c1.c.id)
|
1286 | c1.c2 = c1.fetch('/connection/' + c2.c.id)
|
1287 | c2.c1 = c2.fetch('/connection/' + c1.c.id)
|
1288 | c2.c2 = c2.fetch('/connection/' + c2.c.id)
|
1289 | })
|
1290 |
|
1291 | delay(50, _=> {
|
1292 |
|
1293 | assert(c1.validate(c1.c1, {key: 'string', client: 'string', id: 'string'}))
|
1294 | log('c1.c1', JSON.stringify(c1.c1))
|
1295 | log('c2.c2', JSON.stringify(c2.c2))
|
1296 | assert(c1.c1.id === c1.c.id)
|
1297 | assert(c1.c2.id === c2.c.id)
|
1298 | assert(c2.c1.id === c1.c.id)
|
1299 | assert(c2.c2.id === c2.c.id)
|
1300 |
|
1301 |
|
1302 | c1.c.foo = 'bar'; c1.save(c1.c)
|
1303 | c2.c2.fuzz = 'buzz'; c2.save(c2.c2)
|
1304 | })
|
1305 |
|
1306 | delay(50, _=> {
|
1307 |
|
1308 | assert(c1.c.foo === 'bar')
|
1309 | assert(c1.c1.foo === 'bar')
|
1310 | assert(c2.c1.foo === 'bar')
|
1311 |
|
1312 | assert(c2.c.fuzz === 'buzz')
|
1313 | assert(c2.c2.fuzz === 'buzz')
|
1314 | assert(c1.c2.fuzz === 'buzz')
|
1315 |
|
1316 |
|
1317 | c1.c2.fuzz = 'fart'; c1.save(c1.c2)
|
1318 | c2.c1.free = 'willy'; c2.save(c2.c1)
|
1319 | })
|
1320 |
|
1321 | delay(50, _=> {
|
1322 |
|
1323 | if (options.edit_others) {
|
1324 | assert(c1.c2.fuzz === 'fart')
|
1325 | assert(c2.c2.fuzz === 'fart')
|
1326 | assert(c1.c1.free === 'willy')
|
1327 | assert(c2.c1.free === 'willy')
|
1328 | } else {
|
1329 | assert(c1.c2.fuzz !== 'fart')
|
1330 | assert(c2.c2.fuzz !== 'fart')
|
1331 | assert(c1.c1.free !== 'willy')
|
1332 | assert(c2.c1.free !== 'willy')
|
1333 | }
|
1334 | })
|
1335 |
|
1336 |
|
1337 |
|
1338 | delay(50, _=> done())
|
1339 | }
|
1340 |
|
1341 | test(function connections_1 (done) {
|
1342 | connections_helper(done, 3951, {include_users: true, edit_others: true})
|
1343 | })
|
1344 |
|
1345 | test(function connections_2 (done) {
|
1346 | connections_helper(done, 3952, {include_users: false, edit_others: false})
|
1347 | })
|
1348 |
|
1349 | test(function flashbacks (done) {
|
1350 |
|
1351 |
|
1352 |
|
1353 |
|
1354 |
|
1355 | var port = 3873
|
1356 |
|
1357 |
|
1358 | var s = require('../statebus').serve({port: port, file_store: false})
|
1359 | s.label = 's'
|
1360 |
|
1361 | s('x').to_save = (o, t) => {
|
1362 | log('Saving x with', o)
|
1363 | o.x++
|
1364 | t.done(o)
|
1365 | }
|
1366 |
|
1367 |
|
1368 | var c1 = require('../statebus')()
|
1369 | c1.label = 'c1'
|
1370 | c1.ws_client('*', 'statei://localhost:' + port)
|
1371 |
|
1372 | var c2 = require('../statebus')()
|
1373 | c2.label = 'c2'
|
1374 | c2.ws_client('*', 'statei://localhost:' + port)
|
1375 |
|
1376 | c1.x = c1.fetch('x')
|
1377 | c2.x = c2.fetch('x')
|
1378 |
|
1379 |
|
1380 | delay(50, _=> {
|
1381 | c1.x.x = 1
|
1382 | c1.save(c1.x)
|
1383 | })
|
1384 |
|
1385 |
|
1386 | delay(50, _=> {
|
1387 | assert(c2.x.x === 2, 'c2 didn\'t get it')
|
1388 | assert(c1.x.x === 2, 'c1 didn\'t get it')
|
1389 | log('complete!', c1.x, c2.x)
|
1390 | done()
|
1391 | })
|
1392 | })
|
1393 |
|
1394 | test(function email_read_permissions (done) {
|
1395 | var phase = -1
|
1396 | var u, user1, user2, user3
|
1397 | var tmp1
|
1398 |
|
1399 | var states = function () { return [
|
1400 |
|
1401 | [true,
|
1402 | function () {
|
1403 | log('Logging in as mike')
|
1404 |
|
1405 | u.login_as = {name: 'mike', pass: 'yeah'}; c.save(u)
|
1406 | }],
|
1407 |
|
1408 |
|
1409 |
|
1410 | [(u.logged_in
|
1411 | && u.user.name === 'mike'
|
1412 | && u.user.key === '/user/1'
|
1413 |
|
1414 |
|
1415 | && u.user.email
|
1416 | && user1.email
|
1417 |
|
1418 |
|
1419 | && !user2.email
|
1420 | && !user3.email),
|
1421 |
|
1422 | function () {
|
1423 | !tmp1 && log('Logging in as j')
|
1424 | setTimeout(function () {
|
1425 | if (tmp1) return
|
1426 | tmp1 = true
|
1427 | log('Firing the actual j login')
|
1428 |
|
1429 | u.login_as = {name: 'j', pass: 'yeah'}; c.save(u)
|
1430 | log('We just logged in as j. now user is:', u.user.name)
|
1431 | }, 10)
|
1432 | }],
|
1433 |
|
1434 |
|
1435 |
|
1436 | [(u.logged_in
|
1437 | && u.user.name === 'j'
|
1438 | && u.user.key === '/user/2'
|
1439 |
|
1440 |
|
1441 | && u.user.email
|
1442 | && user2.email
|
1443 |
|
1444 |
|
1445 | && !user1.email
|
1446 | && !user3.email),
|
1447 |
|
1448 |
|
1449 | function () { log("That's all, Doc."); setTimeout(function () {done()}) }]
|
1450 | ]}
|
1451 |
|
1452 | c('/current_user').on_save = function (o) {
|
1453 |
|
1454 |
|
1455 |
|
1456 |
|
1457 | }
|
1458 | c('/user/*').on_save = function (o) {
|
1459 |
|
1460 | }
|
1461 | c('/current_user').on_save = function (o) {
|
1462 |
|
1463 | }
|
1464 | c(function loop () {
|
1465 | u = c.fetch('/current_user')
|
1466 | user1 = c.fetch('/user/1')
|
1467 | user2 = c.fetch('/user/2')
|
1468 | user3 = c.fetch('/user/3')
|
1469 | var st = states()
|
1470 |
|
1471 | if (phase===1)
|
1472 | log('\n\tcurr u:\t',u.user, '\n\t1:\t', user1,'\n\t2:\t', user2,'\n\t3:\t', user3)
|
1473 |
|
1474 | if (phase >= st.length) {
|
1475 | loop.forget()
|
1476 | return
|
1477 | }
|
1478 |
|
1479 | if (phase + 1 < st.length && st[phase + 1][0]) {
|
1480 | phase++
|
1481 | log()
|
1482 | log('## Shifting to phase', phase)
|
1483 | }
|
1484 |
|
1485 |
|
1486 | st[phase][1]()
|
1487 | })
|
1488 | })
|
1489 |
|
1490 | test(function closet_space (done) {
|
1491 | var s = require('../statebus').serve({port: 3949,
|
1492 | file_store: false,
|
1493 | client: (c)=>{c.honk=true}})
|
1494 | s.label = 's'
|
1495 |
|
1496 | var c = require('../statebus')()
|
1497 | c.label = 'c'
|
1498 | c.ws_client('/*', 'statei://localhost:3949')
|
1499 |
|
1500 |
|
1501 | var cu = c.fetch('/current_user')
|
1502 | c.save({key: '/current_user', create_account: {name: 'a', pass: 'a'}})
|
1503 | c.save({key: '/current_user', login_as: {name: 'a', pass: 'a'}})
|
1504 | var a_closet = c.fetch('/user/a/foo')
|
1505 | var a_private = c.fetch('/user/a/private/foo')
|
1506 |
|
1507 | delay(400, () => {
|
1508 | c.save({key: '/user/a/foo', _: 3})
|
1509 | c.save({key: '/user/a/private/foo', _: 4})
|
1510 | })
|
1511 |
|
1512 |
|
1513 | delay(450, ()=> {
|
1514 | log('1. Now curr user is', cu)
|
1515 | console.assert(cu.logged_in == true, 'not logged in')
|
1516 | log('closet is', a_closet)
|
1517 | console.assert(a_closet._ === 3, 'closet not right')
|
1518 | console.assert(a_private._ === 4, 'private not right')
|
1519 |
|
1520 |
|
1521 | c.save({key: '/current_user', create_account: {name: 'b', pass: 'b'}})
|
1522 | c.save({key: '/current_user', login_as: {name: 'b', pass: 'b'}})
|
1523 | })
|
1524 |
|
1525 |
|
1526 | delay(450, ()=> {
|
1527 | log('3. Now curr user is', cu)
|
1528 | log('closet is', {closet:a_closet, private:a_private})
|
1529 | console.assert(a_closet._ === 3, 'A\'s closet is not visible')
|
1530 | console.assert(a_private._ !== 4, 'damn can still see private')
|
1531 |
|
1532 |
|
1533 | a_closet._ = 5; c.save(a_closet)
|
1534 | })
|
1535 |
|
1536 |
|
1537 | delay(350, ()=> {
|
1538 | console.assert(a_closet._ === 3, 'damn he could edit it')
|
1539 | })
|
1540 |
|
1541 | delay(50, ()=>done())
|
1542 | })
|
1543 |
|
1544 | test(function ambiguous_ordering (done) {
|
1545 |
|
1546 |
|
1547 | |
1548 |
|
1549 |
|
1550 |
|
1551 |
|
1552 |
|
1553 | var user = 3
|
1554 | bus('user').to_fetch =
|
1555 | function (k) {
|
1556 | return {user: user}
|
1557 | }
|
1558 |
|
1559 | bus('user').to_save =
|
1560 | function (o) {
|
1561 | if (o.funny)
|
1562 | bus.save({key: 'user', user: 'funny'})
|
1563 |
|
1564 | user = o.user
|
1565 | bus.dirty('user')
|
1566 | }
|
1567 |
|
1568 | log("Eh, nevermind.")
|
1569 | done()
|
1570 | })
|
1571 |
|
1572 | run_tests() |
\ | No newline at end of file |