UNPKG

@gooddollar/gun

Version:

A realtime, decentralized, offline-first, graph data synchronization engine.

1,582 lines (1,502 loc) 241 kB
describe('Gun', function(){ var root; (function(){ var env; if(typeof global !== 'undefined'){ env = global } if(typeof window !== 'undefined'){ env = window } root = env.window? env.window : global; try{ env.window && root.localStorage && root.localStorage.clear() }catch(e){} try{ localStorage.clear() }catch(e){} try{ indexedDB.deleteDatabase('radatatest') }catch(e){} try{ require('fs').unlinkSync('data.json') }catch(e){} try{ require('../lib/fsrm')('radatatest') }catch(e){} //root.Gun = root.Gun || require('../gun'); if(root.Gun){ root.Gun = root.Gun; root.Gun.TESTING = true; } else { root.Gun = require('../gun'); root.Gun.TESTING = true; Gun.serve = require('../lib/serve'); //require('../lib/file'); require('../lib/store'); require('../lib/rfs'); require('./rad/rad.js'); require('./sea/sea.js'); } }(this)); //Gun.log.squelch = true; var gleak = {globals: {}, check: function(){ // via tobyho var leaked = [] for (var key in gleak.globe){ if (!(key in gleak.globals)){ leaked.push(key)} } if (leaked.length > 0){ console.log("GLOBAL LEAK!", leaked); return leaked } }}; (function(env){ for (var key in (gleak.globe = env)){ gleak.globals[key] = true } }(this)); var t = {}; describe('Utility', function(){ var u; /* // causes logger to no longer log. it('verbose console.log debugging', function(done) { var gun = Gun(); var log = root.console.log, counter = 1; root.console.log = function(a,b,c){ --counter; //log(a,b,c); } Gun.log.verbose = true; gun.put('bar', function(err, yay){ // intentionally trigger an error that will get logged. expect(counter).to.be(0); Gun.log.verbose = false; gun.put('bar', function(err, yay){ // intentionally trigger an error that will get logged. expect(counter).to.be(0); root.console.log = log; done(); }); }); } ); */ describe('Type Check', function(){ it('binary', function(){ expect(Gun.bi.is(false)).to.be(true); expect(Gun.bi.is(true)).to.be(true); expect(Gun.bi.is(u)).to.be(false); expect(Gun.bi.is(null)).to.be(false); expect(Gun.bi.is('')).to.be(false); expect(Gun.bi.is('a')).to.be(false); expect(Gun.bi.is(0)).to.be(false); expect(Gun.bi.is(1)).to.be(false); expect(Gun.bi.is([])).to.be(false); expect(Gun.bi.is([1])).to.be(false); expect(Gun.bi.is({})).to.be(false); expect(Gun.bi.is({a:1})).to.be(false); expect(Gun.bi.is(function(){})).to.be(false); }); it('number',function(){ expect(Gun.num.is(0)).to.be(true); expect(Gun.num.is(1)).to.be(true); expect(Gun.num.is(Infinity)).to.be(true); expect(Gun.num.is(u)).to.be(false); expect(Gun.num.is(null)).to.be(false); expect(Gun.num.is(NaN)).to.be(false); expect(Gun.num.is('')).to.be(false); expect(Gun.num.is('a')).to.be(false); expect(Gun.num.is([])).to.be(false); expect(Gun.num.is([1])).to.be(false); expect(Gun.num.is({})).to.be(false); expect(Gun.num.is({a:1})).to.be(false); expect(Gun.num.is(false)).to.be(false); expect(Gun.num.is(true)).to.be(false); expect(Gun.num.is(function(){})).to.be(false); }); it('text',function(){ expect(Gun.text.is('')).to.be(true); expect(Gun.text.is('a')).to.be(true); expect(Gun.text.is(u)).to.be(false); expect(Gun.text.is(null)).to.be(false); expect(Gun.text.is(false)).to.be(false); expect(Gun.text.is(true)).to.be(false); expect(Gun.text.is(0)).to.be(false); expect(Gun.text.is(1)).to.be(false); expect(Gun.text.is([])).to.be(false); expect(Gun.text.is([1])).to.be(false); expect(Gun.text.is({})).to.be(false); expect(Gun.text.is({a:1})).to.be(false); expect(Gun.text.is(function(){})).to.be(false); }); it('list',function(){ expect(Gun.list.is([])).to.be(true); expect(Gun.list.is([1])).to.be(true); expect(Gun.list.is(u)).to.be(false); expect(Gun.list.is(null)).to.be(false); expect(Gun.list.is(0)).to.be(false); expect(Gun.list.is(1)).to.be(false); expect(Gun.list.is('')).to.be(false); expect(Gun.list.is('a')).to.be(false); expect(Gun.list.is({})).to.be(false); expect(Gun.list.is({a:1})).to.be(false); expect(Gun.list.is(false)).to.be(false); expect(Gun.list.is(true)).to.be(false); expect(Gun.list.is(function(){})).to.be(false); }); it('obj',function(){ expect(Gun.obj.is({})).to.be(true); expect(Gun.obj.is({a:1})).to.be(true); expect(Gun.obj.is(u)).to.be(false); expect(Gun.obj.is()).to.be(false); expect(Gun.obj.is(undefined)).to.be(false); expect(Gun.obj.is(null)).to.be(false); expect(Gun.obj.is(NaN)).to.be(false); expect(Gun.obj.is(0)).to.be(false); expect(Gun.obj.is(1)).to.be(false); expect(Gun.obj.is('')).to.be(false); expect(Gun.obj.is('a')).to.be(false); expect(Gun.obj.is([])).to.be(false); expect(Gun.obj.is([1])).to.be(false); expect(Gun.obj.is(false)).to.be(false); expect(Gun.obj.is(true)).to.be(false); expect(Gun.obj.is(function(){})).to.be(false); expect(Gun.obj.is(new Date())).to.be(false); expect(Gun.obj.is(/regex/)).to.be(false); this.document && expect(Gun.obj.is(document.createElement('div'))).to.be(false); expect(Gun.obj.is(new (function Class(){ this.x = 1; this.y = 2 })())).to.be(true); }); it('fn',function(){ expect(Gun.fn.is(function(){})).to.be(true); expect(Gun.fn.is(u)).to.be(false); expect(Gun.fn.is(null)).to.be(false); expect(Gun.fn.is('')).to.be(false); expect(Gun.fn.is('a')).to.be(false); expect(Gun.fn.is(0)).to.be(false); expect(Gun.fn.is(1)).to.be(false); expect(Gun.fn.is([])).to.be(false); expect(Gun.fn.is([1])).to.be(false); expect(Gun.fn.is({})).to.be(false); expect(Gun.fn.is({a:1})).to.be(false); expect(Gun.fn.is(false)).to.be(false); expect(Gun.fn.is(true)).to.be(false); }); it('time',function(){ t.ts = Gun.time.is(); expect(13 <= t.ts.toString().length).to.be.ok(); expect(Gun.num.is(t.ts)).to.be.ok(); expect(Gun.time.is(new Date())).to.be.ok(); }); }); describe('Text', function(){ it('ify',function(){ expect(Gun.text.ify(0)).to.be('0'); expect(Gun.text.ify(22)).to.be('22'); expect(Gun.text.ify([true,33,'yay'])).to.be('[true,33,"yay"]'); expect(Gun.text.ify({a:0,b:'1',c:[0,'1'],d:{e:'f'}})).to.be('{"a":0,"b":"1","c":[0,"1"],"d":{"e":"f"}}'); expect(Gun.text.ify(false)).to.be('false'); expect(Gun.text.ify(true)).to.be('true'); }); it('random',function(){ expect(Gun.text.random().length).to.be(24); expect(Gun.text.random(11).length).to.be(11); expect(Gun.text.random(4).length).to.be(4); t.tr = Gun.text.random(2,'as'); expect((t.tr=='as'||t.tr=='aa'||t.tr=='sa'||t.tr=='ss')).to.be.ok(); }); it('match',function(){ expect(Gun.text.match("user/mark", 'user/mark')).to.be.ok(); expect(Gun.text.match("user/mark/nadal", {'=': 'user/mark'})).to.not.be.ok(); expect(Gun.text.match("user/mark/nadal", {'*': 'user/'})).to.be.ok(); expect(Gun.text.match("email/mark@gunDB.io", {'*': 'user/'})).to.not.be.ok(); expect(Gun.text.match("user/mark/nadal", {'>': 'user/j', '<': 'user/o'})).to.be.ok(); expect(Gun.text.match("user/amber/nadal", {'>': 'user/j', '<': 'user/o'})).to.not.be.ok(); expect(Gun.text.match("user/amber/nadal", {'>': 'user/a', '<': 'user/c'})).to.be.ok(); expect(Gun.text.match("user/mark/nadal", {'>': 'user/a', '<': 'user/c'})).to.not.be.ok(); return; // below is OLD bloat, still available in lib/match.js expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '>': 'j', '<': 'o', '?': 'm/n'})).to.be.ok(); expect(Gun.text.match("user/amber/cazzell", {'*': 'user/', '?': 'm/n'})).to.not.be.ok(); expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '-': 'mad'})).to.be.ok(); expect(Gun.text.match("user/mad/person", {'*': 'user/', '-': 'mad'})).to.not.be.ok(); expect(Gun.text.match("user/mark/timothy/nadal", {'*': 'user/', '-': ['mark', 'nadal']})).to.not.be.ok(); expect(Gun.text.match("user/amber/rachel/cazzell", {'*': 'user/', '-': ['mark', 'nadal']})).to.be.ok(); expect(Gun.text.match("user/mark/nadal", {'*': 'user/', '+': 'ark'})).to.be.ok(); expect(Gun.text.match("user/mad/person", {'*': 'user/', '+': 'ark'})).to.not.be.ok(); expect(Gun.text.match("user/mark/timothy/nadal", {'*': 'user/', '+': ['mark', 'nadal']})).to.be.ok(); expect(Gun.text.match("user/mark/timothy/nadal", {'*': 'user/', '+': ['nadal', 'mark']})).to.be.ok(); expect(Gun.text.match("user/mark/timothy/nadal", {'*': 'user/', '+': ['mark', 'amber']})).to.not.be.ok(); expect(Gun.text.match("user/mark/rachel/nadal/cazzell", {'*': 'user/', '+': ['mark', 'cazzell'], '-': ['amber', 'timothy']})).to.be.ok(); expect(Gun.text.match("user/mark/rachel/timothy/cazzell", {'*': 'user/', '+': ['mark', 'cazzell'], '-': ['amber', 'timothy']})).to.not.be.ok(); expect(Gun.text.match("photo/kitten.jpg", {'*': 'photo/', '!': '.jpg'})).to.be.ok(); expect(Gun.text.match("photo/kittens.gif", {'*': 'photo/', '!': '.jpg'})).to.not.be.ok(); expect(Gun.text.match("user/mark", {'~': 'user/Mark'})).to.be.ok(); }); }); describe('List', function(){ it('slit',function(){ (function(){ expect(Gun.list.slit.call(arguments, 0)).to.eql([1,2,3,'a','b','c']); }(1,2,3,'a','b','c')); }); it('sort',function(){ expect([{i:9},{i:4},{i:1},{i:-3},{i:0}].sort(Gun.list.sort('i'))).to.eql([{i:-3},{i:0},{i:1},{i:4},{i:9}]); }); it('map',function(){ expect(Gun.list.map([1,2,3,4,5],function(v,i,t){ t(v+=this.d); this.d=v; },{d:0})).to.eql([1,3,6,10,15]); expect(Gun.list.map([2,3,0,4],function(v,i,t){ if(!v){ return } t(v*=this.d); this.d=v; },{d:1})).to.eql([2,6,24]); expect(Gun.list.map([true,false,NaN,Infinity,'',9],function(v,i,t){ if(i===3){ return 0 }})).to.be(0); }); }); describe('Object', function(){ it('del',function(){ var obj = {a:1,b:2}; Gun.obj.del(obj,'a'); expect(obj).to.eql({b:2}); }); it('has',function(){ var obj = {a:1,b:2}; expect(Gun.obj.has(obj,'a')).to.be.ok(); }); it('empty',function(){ expect(Gun.obj.empty()).to.be(true); expect(Gun.obj.empty({a:false})).to.be(false); expect(Gun.obj.empty({a:false},'a')).to.be(true); expect(Gun.obj.empty({a:false},{a:1})).to.be(true); expect(Gun.obj.empty({a:false,b:1},'a')).to.be(false); expect(Gun.obj.empty({a:false,b:1},{a:1})).to.be(false); expect(Gun.obj.empty({a:false,b:1},{a:1,b:1})).to.be(true); expect(Gun.obj.empty({a:false,b:1,c:3},{a:1,b:1})).to.be(false); expect(Gun.obj.empty({1:1},'danger')).to.be(false); }); it('copy',function(){ var obj = {"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}}; var copy = Gun.obj.copy(obj); expect(copy).to.eql(obj); expect(copy).to.not.be(obj); }); it('ify',function(){ expect(Gun.obj.ify('[0,1]')).to.eql([0,1]); expect(Gun.obj.ify('{"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}}')).to.eql({"a":false,"b":1,"c":"d","e":[0,1],"f":{"g":"h"}}); }); it('map',function(){ expect(Gun.obj.map({a:'z',b:'y',c:'x'},function(v,i,t){ t(v,i) })).to.eql({x:'c',y:'b',z:'a'}); expect(Gun.obj.map({a:'z',b:false,c:'x'},function(v,i,t){ if(!v){ return } t(i,v) })).to.eql({a:'z',c:'x'}); expect(Gun.obj.map({a:'z',b:3,c:'x'},function(v,i,t){ if(v===3){ return 0 }})).to.be(0); }); }); describe('Functions', function(){ /* it.skip('sum',function(done){ // deprecate? var obj = {a:2, b:2, c:3, d: 9}; Gun.obj.map(obj, function(num, key){ setTimeout(this.add(function(){ this.done(null, num * num); }, key), parseInt((""+Math.random()).substring(2,5))); }, Gun.fn.sum(function(err, val){ expect(val.a).to.eql(4); expect(val.b).to.eql(4); expect(val.c).to.eql(9); expect(val.d).to.eql(81); done(); })); }); */ }); describe('On', function(){ it('subscribe', function(done){ var e = {on: Gun.on}; e.on('foo', function(a){ done.first = true; expect(a).to.be(1); this.to.next(a); }); e.on('foo', function(a){ expect(a).to.be(1); expect(done.first).to.be.ok(); done(); }); e.on('foo', 1); }); it('unsubscribe', function(done){ var e = {on: Gun.on}; e.on('foo', function(a){ this.off(); done.first = a; expect(a).to.be(1); this.to.next(a); }); e.on('foo', function(a){ var to = this; expect(a).to.be(done.second? 2 : 1); expect(done.first).to.be(1); done.second = true; if(a === 2){ setTimeout(function(){ expect(e.tag.foo.to === to).to.be.ok(); done(); }, 10); } }); e.on('foo', 1); e.on('foo', 2); }); it('stun', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ if(2 === a){ done.first2 = true; this.to.next(a); return; } setTimeout(function(){ expect(done.second).to.not.be.ok(); expect(done.second2).to.be.ok(); expect(done.first2).to.be.ok(); done(); },10); }); e.on('foo', function(a, ev){ if(2 === a){ done.second2 = true; } else { done.second = true; } }); e.on('foo', 1); e.on('foo', 2); }); it('resume', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ var to = this.to; setTimeout(function(){ expect(done.second).to.not.be.ok(); to.next(a); },10); }); e.on('foo', function(a){ done.second = true; expect(a).to.be(1); done(); }); e.on('foo', 1); }); it('double resume', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ var to = this.to; setTimeout(function(){ if(1 === a){ done.first1 = true; expect(done.second).to.not.be.ok(); } if(2 === a){ done.first2 = true; } to.next(a); },10); }); e.on('foo', function(a, ev){ done.second = true; if(1 === a){ expect(done.first2).to.not.be.ok(); done.second1 = true; } if(2 === a){ expect(done.first2).to.be.ok(); if(done.second1){ done(); } } }); e.on('foo', 1); e.on('foo', 2); }); it('double resume different event', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ var to = this.to; setTimeout(function(){ done.first1 = true; to.next(a); },10); }); e.on('foo', function(a){ if(1 === a){ expect(done.first1).to.be.ok(); done(); } }); e.on('foo', 1); e.on('bar', 2); }); it('resume params', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ var to = this.to; setTimeout(function(){ expect(done.second).to.not.be.ok(); to.next(0); },10); }); e.on('foo', function(a){ done.second = true; expect(a).to.be(0); done(); }); e.on('foo', 1); }); it('map', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ var to = this.to; Gun.obj.map(a.it, function(v,f){ setTimeout(function(){ var emit = {field: 'where', soul: f}; to.next(emit); },10); }) }); e.on('foo', function(a, ev){ var to = this.to; setTimeout(function(){ to.next({node: a.soul}); },100); }); e.on('foo', function(a){ if('a' == a.node){ done.a = true; } else { expect(done.a).to.be.ok(); done(); } }); e.on('foo', {field: 'where', it: {a: 1, b: 2}}); }); it('map synchronous', function(done){ var e = {on: Gun.on}; e.on('foo', function(a, ev){ var to = this.to; Gun.obj.map(a.node, function(v,f){ //setTimeout(function(){ var emit = {field: 'where', soul: f}; to.next(emit); //},10); }) }); e.on('foo', function(a, ev){ var to = this.to; setTimeout(function(){ to.next({node: a.soul}); },100); }); e.on('foo', function(a){ expect(this.as.hi).to.be(1); if('a' == a.node){ done.a = true; } else { expect(done.a).to.be.ok(); done(); } }, {hi: 1}).on.on('foo', {field: 'where', node: {a: 1, b: 2}}); }); it('synchronous async', function(done){ var e = {on: Gun.on}; e.on('foo', function(a){ expect(a.b).to.be(5); done.first = true; this.to.next(a); }); e.on('foo', function(a, ev){ expect(a.b).to.be(5); done.second = true; var to = this.to; setTimeout(function(){ to.next({c: 9, again: a.again}); },100); }); e.on('foo', function(a){ this.off(); expect(a.again).to.not.be.ok(); expect(a.c).to.be(9); expect(done.first).to.be.ok(); expect(done.second).to.be.ok(); done(); }).on.on('foo', {b: 5}).on.on('foo', {b:5, again: true}); }); }); describe('flow', function(){ var i = 0; function flow(){ var f = function(arg){ var cb = f.cb? f.cb.fn : f.fn; if(cb){ f.cb = cb; var ff = flow(); ff.f = f; cb(ff); return; } if(f.f){ f.f(arg); f.cb = 0; return; } }, cb; f.flow = function(fn){ cb = (cb || f).fn = fn; return f; }; return f; } it('intermittent interruption', function(done){ var f = flow(); //var f = {flow: flow} f.flow(function(f){ //console.log(1); f.flow(function(f){ //console.log(2); f({yes: 'please'}); }); setTimeout(function(){ f.flow(function(f){ //console.log(2.1); f({forever: 'there'}); }); f({strange: 'places'}); //console.log("-----"); f({earlier: 'location'}); },100); }); f.flow(function(f){ //console.log(3); f({ok: 'now'}); }); f.flow(function(f){ //console.log(4); done(); }); setTimeout(function(){ f({hello: 'world'}); }, 100); }); var i = 0; ;(function(exports){ function next(arg){ var n = this; if(arg instanceof Function){ if(!n.fn){ return n.fn = arg, n } var f = {next: next, fn: arg, first: n.first || n}; n.last = (n.last || n).to = f; return n; } if(n.fn){ var sub = {next: next, from: n.to || (n.first || {}).from}; n.fn(sub); return; } if(n.from){ n.from.next(arg); return; } } exports.next = next; }(Gun)); it('intermittent interruptions', function(done){ //var f = flow(); var f = {next: Gun.next}; // for now f.next(function(f){ //console.log(1, f); f.next(function(f){ //console.log(2, f); f.next({yes: 'please'}); }); setTimeout(function(){ f.next(function(f){ //console.log(2.1, f); f.next({forever: 'there'}); }); f.next({strange: 'places'}); //console.log("-----"); f.next({earlier: 'location'}); },100); }); f.next(function(f){ //console.log(3); f.next({ok: 'now'}); }); f.next(function(f){ //console.log(4); if(!done.a){ return done.a = true } done(); }); setTimeout(function(){ f.next({hello: 'world'}); }, 100); }); }); describe('Gun Safety', function(){ /* WARNING NOTE: Internal API has significant breaking changes! */ var gun = Gun(); it('is',function(){ expect(Gun.is(gun)).to.be(true); expect(Gun.is(true)).to.be(false); expect(Gun.is(false)).to.be(false); expect(Gun.is(0)).to.be(false); expect(Gun.is(1)).to.be(false); expect(Gun.is('')).to.be(false); expect(Gun.is('a')).to.be(false); expect(Gun.is(Infinity)).to.be(false); expect(Gun.is(NaN)).to.be(false); expect(Gun.is([])).to.be(false); expect(Gun.is([1])).to.be(false); expect(Gun.is({})).to.be(false); expect(Gun.is({a:1})).to.be(false); expect(Gun.is(function(){})).to.be(false); }); it('is value',function(){ expect(Gun.val.is(false)).to.be(true); expect(Gun.val.is(true)).to.be(true); expect(Gun.val.is(0)).to.be(true); expect(Gun.val.is(1)).to.be(true); expect(Gun.val.is('')).to.be(true); expect(Gun.val.is('a')).to.be(true); expect(Gun.val.is({'#':'somesoulidhere'})).to.be('somesoulidhere'); expect(Gun.val.is({'#':'somesoulidhere', and: 'nope'})).to.be(false); expect(Gun.val.is(Infinity)).to.be(false); // boohoo :( expect(Gun.val.is(NaN)).to.be(false); expect(Gun.val.is([])).to.be(false); expect(Gun.val.is([1])).to.be(false); expect(Gun.val.is({})).to.be(false); expect(Gun.val.is({a:1})).to.be(false); expect(Gun.val.is(function(){})).to.be(false); }); it('is link',function(){ expect(Gun.val.link.is({'#':'somesoulidhere'})).to.be('somesoulidhere'); expect(Gun.val.link.is({'#':'somethingelsehere'})).to.be('somethingelsehere'); expect(Gun.val.link.is({'#':'somesoulidhere', and: 'nope'})).to.be(false); expect(Gun.val.link.is({or: 'nope', '#':'somesoulidhere'})).to.be(false); expect(Gun.val.link.is(false)).to.be(false); expect(Gun.val.link.is(true)).to.be(false); expect(Gun.val.link.is('')).to.be(false); expect(Gun.val.link.is('a')).to.be(false); expect(Gun.val.link.is(0)).to.be(false); expect(Gun.val.link.is(1)).to.be(false); expect(Gun.val.link.is(Infinity)).to.be(false); // boohoo :( expect(Gun.val.link.is(NaN)).to.be(false); expect(Gun.val.link.is([])).to.be(false); expect(Gun.val.link.is([1])).to.be(false); expect(Gun.val.link.is({})).to.be(false); expect(Gun.val.link.is({a:1})).to.be(false); expect(Gun.val.link.is(function(){})).to.be(false); }); it.skip('is lex',function(){ expect(Gun.is.lex({'#': 'soul'})).to.eql({soul: 'soul'}); expect(Gun.is.lex({'.': 'field'})).to.eql({field: 'field'}); expect(Gun.is.lex({'=': 'value'})).to.eql({value: 'value'}); expect(Gun.is.lex({'>': 'state'})).to.eql({state: 'state'}); expect(Gun.is.lex({'#': {'=': 'soul'}})).to.eql({soul: {'=': 'soul'}}); expect(Gun.is.lex({'#': {'=': 'soul'}, '.': []})).to.be(false); expect(Gun.is.lex({'#': {'=': 'soul'}, 'asdf': 'oye'})).to.be(false); expect(Gun.is.lex()).to.be(false); expect(Gun.is.lex('')).to.be(false); }); it.skip('is lex ify',function(){ expect(Gun.is.lex.ify({'#': 'soul', '.': 'field', soul: 'foo', field: 'field', state: 0})).to.eql({'#': 'soul', '.': 'field', '>': 0}); }); it('is node',function(){ var n; expect(Gun.node.is({_:{'#':'somesoulidhere'}})).to.be(true); expect(Gun.node.is(n = {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}})).to.be(true); expect(Gun.node.is({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}, g: Infinity})).to.be(false); expect(Gun.node.is({_:{'#':'somesoulidhere'}, a:0, b: 1, z: NaN, c: '', d: 'e'})).to.be(false); expect(Gun.node.is({_:{'#':'somesoulidhere'}, a:0, b: 1, y: {_: 'cool'}, c: '', d: 'e'})).to.be(false); expect(Gun.node.is({_:{'#':'somesoulidhere'}, a:0, b: 1, x: [], c: '', d: 'e'})).to.be(false); expect(Gun.node.is({})).to.be(false); expect(Gun.node.is({a:1})).to.be(false); expect(Gun.node.is({_:{}})).to.be(false); expect(Gun.node.is({_:{}, a:1})).to.be(false); expect(Gun.node.is({'#':'somesoulidhere'})).to.be(false); Gun.node.is(n, function(v,f){ //console.log("v/f", v,f); }); }); it('is graph',function(){ var g; expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}}})).to.be(true); expect(Gun.graph.is(g = {'somesoulidhere': {_:{'#':'somesoulidhere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(true); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(true); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}})).to.be(true); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: 1, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {_:{'#':'FOO'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}}, foo: {_:{}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: Infinity, c: '', d: 'e', f: {'#':'somethingelsehere'}}})).to.be(false); expect(Gun.graph.is({'somesoulidhere': {_:{'#':'somesoulidhere'}, a:0, b: Infinity, c: '', d: 'e', f: {'#':'somethingelsehere'}}, 'somethingelsehere': {_:{'#':'somethingelsehere'}}})).to.be(false); expect(Gun.graph.is({_:{'#':'somesoulidhere'}})).to.be(false); expect(Gun.graph.is({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}})).to.be(false); expect(Gun.graph.is({_:{'#':'somesoulidhere'}, a:0, b: 1, c: '', d: 'e', f: {'#':'somethingelsehere'}, g: Infinity})).to.be(false); expect(Gun.graph.is({_:{'#':'somesoulidhere'}, a:0, b: 1, z: NaN, c: '', d: 'e'})).to.be(false); expect(Gun.graph.is({_:{'#':'somesoulidhere'}, a:0, b: 1, y: {_: 'cool'}, c: '', d: 'e'})).to.be(false); expect(Gun.graph.is({_:{'#':'somesoulidhere'}, a:0, b: 1, x: [], c: '', d: 'e'})).to.be(false); expect(Gun.graph.is({})).to.be(false); // Empty graph is not a graph :( expect(Gun.graph.is({a:1})).to.be(false); expect(Gun.graph.is({_:{}})).to.be(false); expect(Gun.graph.is({_:{}, a:1})).to.be(false); expect(Gun.graph.is({'#':'somesoulidhere'})).to.be(false); Gun.graph.is(g, function(n,s){ //console.log("node/soul", n,s); }); }); it('graph ify', function(done){ function map(v,f,n){ done.m = true; } var graph = Gun.graph.ify({ _: {'#': 'yay'}, a: 1 }, map); expect(graph).to.eql({ yay: { _: {'#': 'yay'}, a: 1 } }); expect(done.m).to.be.ok(); var graph = Gun.graph.ify({ _: {'#': 'yay', '>': {a: 9}}, a: 1 }, map); expect(graph).to.eql({ yay: { _: {'#': 'yay', '>': {a: 9}}, a: 1 } }); var map = Gun.state.map(map, 9); var graph = Gun.graph.ify({ _: {'#': 'yay', '>': {a: 1}}, a: 1 }, map); expect(graph).to.eql({ yay: { _: {'#': 'yay', '>': {a: 9}}, a: 1 } }); var graph = Gun.graph.ify({a:1}); Gun.obj.map(graph, function(node){ expect(node._['#']).to.be.ok(); }); var alice = {_:{'#':'ASDF'}, age: 27, name: "Alice"}; var bob = {_:{'#':'DASF'}, age: 29, name: "Bob"}; var cat = {_:{'#':'FDSA'}, name: "Fluffy", species: "kitty"}; alice.spouse = bob; bob.spouse = alice; alice.pet = cat; cat.slave = bob; cat.master = alice; var graph = Gun.graph.ify(bob); expect(graph).to.eql({ 'ASDF': {_:{'#':'ASDF'}, age: 27, name: "Alice", spouse: {'#':'DASF'}, pet: {'#':'FDSA'} }, 'DASF': {_:{'#':'DASF'}, age: 29, name: 'Bob', spouse: {'#':'ASDF'}, }, 'FDSA': {_:{'#':'FDSA'}, name: "Fluffy", species: "kitty", slave: {'#':'DASF'}, master: {'#':'ASDF'} } }); done(); }); }); }); describe('ify', function(){ console.log("TODO: BUG! Upgrade IFY tests to new internal API!"); return; var test, gun = Gun(); it('null', function(done){ Gun.ify(null, function(err, ctx){ expect(err).to.be.ok(); done(); }); }); it('basic', function(done){ var data = {a: false, b: true, c: 0, d: 1, e: '', f: 'g', h: null}; Gun.ify(data, function(err, ctx){ expect(err).to.not.be.ok(); expect(ctx.err).to.not.be.ok(); expect(ctx.root).to.eql(data); expect(ctx.root === data).to.not.ok(); done(); }, {pure: true}); }); it('basic soul', function(done){ var data = {_: {'#': 'SOUL'}, a: false, b: true, c: 0, d: 1, e: '', f: 'g', h: null}; Gun.ify(data, function(err, ctx){ expect(err).to.not.be.ok(); expect(ctx.err).to.not.be.ok(); expect(ctx.root).to.eql(data); expect(ctx.root === data).to.not.be.ok(); expect(Gun.node.soul(ctx.root) === Gun.node.soul(data)); done(); }, {pure: true}); }); it('arrays', function(done){ var data = {before: {path: 'kill'}, one: {two: {lol: 'troll', three: [9, 8, 7, 6, 5]}}}; Gun.ify(data, function(err, ctx){ expect(err).to.be.ok(); expect((err.err || err).indexOf("one.two.three")).to.not.be(-1); done(); }); }); it('undefined', function(done){ var data = {z: undefined, x: 'bye'}; Gun.ify(data, function(err, ctx){ expect(err).to.be.ok(); done(); }); }); it('NaN', function(done){ var data = {a: NaN, b: 2}; Gun.ify(data, function(err, ctx){ expect(err).to.be.ok(); done(); }); }); it('Infinity', function(done){ // SAD DAY PANDA BEAR :( :( :(... Mark wants Infinity. JSON won't allow. var data = {a: 1, b: Infinity}; Gun.ify(data, function(err, ctx){ expect(err).to.be.ok(); done(); }); }); it('function', function(done){ var data = {c: function(){}, d: 'hi'}; Gun.ify(data, function(err, ctx){ expect(err).to.be.ok(); done(); }); }); it('extraneous', function(done){ var data = {_: {'#': 'shhh', meta: {yay: 1}}, sneak: true}; Gun.ify(data, function(err, ctx){ expect(err).to.not.be.ok(); // extraneous metadata needs to be stored, but it can't be used for data. done(); }); }); it('document', function(done){ var data = {users: {1: {where: {lat: Math.random(), lng: Math.random(), i: 1}}}}; Gun.ify(data, function(err, ctx){ var soul, node; expect(soul = Gun.val.link.is(ctx.root.users)).to.be.ok(); node = ctx.graph[soul]; expect(soul = Gun.val.link.is(node[1])).to.be.ok(); node = ctx.graph[soul]; expect(soul = Gun.val.link.is(node.where)).to.be.ok(); node = ctx.graph[soul]; expect(node.lat).to.be.ok(); expect(node.lng).to.be.ok(); expect(node.i).to.be(1); done(); }); }); return; // TODO! Fix GUN to handle this! data = {}; data.sneak = false; data.both = {inside: 'meta data'}; data._ = {'#': 'shhh', data: {yay: 1}, spin: data.both}; test = Gun.ify(data); expect(test.err.meta).to.be.ok(); // TODO: Fail: this passes, somehow? Fix ify code! }); describe('Schedule', function(){ console.log("TODO: BUG! Upgrade SCHEDULE tests to new internal API!"); return; it('one', function(done){ Gun.schedule(Gun.time.is(), function(){ expect(true).to.be(true); done(); //setTimeout(function(){ done() },1); }); }); it('many', function(done){ Gun.schedule(Gun.time.is() + 50, function(){ done.first = true; }); Gun.schedule(Gun.time.is() + 100, function(){ done.second = true; }); Gun.schedule(Gun.time.is() + 200, function(){ done.third = true; expect(done.first).to.be(true); expect(done.second).to.be(true); expect(done.third).to.be(true); done(); //setTimeout(function(){ done() },1); }); }); }); describe('Union', function(){ console.log("TODO: BUG! Upgrade UNION tests to new internal API!"); return; var gun = Gun(); it('fail', function(){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ a: 'cheating' }}, a: 0 } } expect(gun.__.graph['asdf']).to.not.be.ok(); var ctx = Gun.HAM.graph(gun, prime); expect(ctx).to.not.be.ok(); });return; it('basic', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ a: Gun.time.is() }}, a: 0 } } expect(gun.__.graph['asdf']).to.not.be.ok(); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['asdf'].a).to.be(0); done(); }); }); it('disjoint', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ b: Gun.time.is() }}, b: 'c' } } expect(gun.__.graph['asdf'].a).to.be(0); expect(gun.__.graph['asdf'].b).to.not.be.ok(); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['asdf'].a).to.be(0); expect(gun.__.graph['asdf'].b).to.be('c'); done(); }); }); it('mutate', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ b: Gun.time.is() }}, b: 'd' } } expect(gun.__.graph['asdf'].b).to.be('c'); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['asdf'].b).to.be('d'); done(); }); }); it('disjoint past', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ x: 0 // beginning of time! }}, x: 'hi' } } expect(gun.__.graph['asdf'].x).to.not.be.ok(); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['asdf'].x).to.be('hi'); done(); }); }); it('past', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ x: Gun.time.is() - (60 * 1000) // above lower boundary, below now or upper boundary. }}, x: 'hello' } } expect(gun.__.graph['asdf'].x).to.be('hi'); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['asdf'].x).to.be('hello'); done(); }); }); it('future', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ x: Gun.time.is() + (200) // above now or upper boundary, aka future. }}, x: 'how are you?' } } expect(gun.__.graph['asdf'].x).to.be('hello'); var now = Gun.time.is(); var ctx = Gun.union(gun, prime, function(){ expect(Gun.time.is() - now).to.be.above(100); expect(gun.__.graph['asdf'].x).to.be('how are you?'); done(); }); }); var to = 5000; it('disjoint future', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ y: Gun.time.is() + (200) // above now or upper boundary, aka future. }}, y: 'goodbye' } } expect(gun.__.graph['asdf'].y).to.not.be.ok(); var now = Gun.time.is(); var ctx = Gun.union(gun, prime, function(){ expect(Gun.time.is() - now).to.be.above(100); expect(gun.__.graph['asdf'].y).to.be('goodbye'); done(); }); }); it('disjoint future max', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ y: Gun.time.is() + (2), // above now or upper boundary, aka future. z: Gun.time.is() + (200) // above now or upper boundary, aka future. }}, y: 'bye', z: 'who' } } expect(gun.__.graph['asdf'].y).to.be('goodbye'); expect(gun.__.graph['asdf'].z).to.not.be.ok(); var now = Gun.time.is(); var ctx = Gun.union(gun, prime, function(){ expect(Gun.time.is() - now).to.be.above(100); expect(gun.__.graph['asdf'].y).to.be('bye'); expect(gun.__.graph['asdf'].z).to.be('who'); done(); //setTimeout(function(){ done() },1); }); }); it('future max', function(done){ var prime = { 'asdf': { _: {'#': 'asdf', '>':{ w: Gun.time.is() + (2), // above now or upper boundary, aka future. x: Gun.time.is() - (60 * 1000), // above now or upper boundary, aka future. y: Gun.time.is() + (200), // above now or upper boundary, aka future. z: Gun.time.is() + (50) // above now or upper boundary, aka future. }}, w: true, x: 'nothing', y: 'farewell', z: 'doctor who' } } expect(gun.__.graph['asdf'].w).to.not.be.ok(); expect(gun.__.graph['asdf'].x).to.be('how are you?'); expect(gun.__.graph['asdf'].y).to.be('bye'); expect(gun.__.graph['asdf'].z).to.be('who'); var now = Gun.time.is(); var ctx = Gun.union(gun, prime, function(){ expect(Gun.time.is() - now).to.be.above(100); expect(gun.__.graph['asdf'].w).to.be(true); expect(gun.__.graph['asdf'].x).to.be('how are you?'); expect(gun.__.graph['asdf'].y).to.be('farewell'); expect(gun.__.graph['asdf'].z).to.be('doctor who'); done(); //setTimeout(function(){ done() },1); }); }); it('two nodes', function(done){ // chat app problem where disk dropped the last data, turns out it was a union problem! var state = Gun.time.is(); var prime = { 'sadf': { _: {'#': 'sadf', '>':{ 1: state }}, 1: {'#': 'fdsa'} }, 'fdsa': { _: {'#': 'fdsa', '>':{ msg: state }}, msg: "Let's chat!" } } expect(gun.__.graph['sadf']).to.not.be.ok(); expect(gun.__.graph['fdsa']).to.not.be.ok(); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['sadf'][1]).to.be.ok(); expect(gun.__.graph['fdsa'].msg).to.be("Let's chat!"); done(); }); }); it('append third node', function(done){ // chat app problem where disk dropped the last data, turns out it was a union problem! var state = Gun.time.is(); var prime = { 'sadf': { _: {'#': 'sadf', '>':{ 2: state }}, 2: {'#': 'fads'} }, 'fads': { _: {'#': 'fads', '>':{ msg: state }}, msg: "hi" } } expect(gun.__.graph['sadf']).to.be.ok(); expect(gun.__.graph['fdsa']).to.be.ok(); var ctx = Gun.union(gun, prime, function(){ expect(gun.__.graph['sadf'][1]).to.be.ok(); expect(gun.__.graph['sadf'][2]).to.be.ok(); expect(gun.__.graph['fads'].msg).to.be("hi"); done(); }); }); it('ify null', function(){ var node = Gun.union.ify(null, 'pseudo'); expect(Gun.node.soul(node)).to.be('pseudo'); }); it('ify node', function(){ var graph = { 'asdf': { _: {'#': 'asdf', '>': { x: Gun.time.is(), y: Gun.time.is() }}, x: 1, y: 2 }, 'soul': { _: {'#': 'soul', '~': 1, '>': { 'asdf': Gun.time.is() }}, 'asdf': {'#': 'asdf'} } } var node = Gun.union.ify(graph, 'soul'); expect(Gun.node.soul(node)).to.be('soul'); expect(node.x).to.be(1); expect(node.y).to.be(2); }); it('ify graph', function(){ var graph = { 'asdf': { _: {'#': 'asdf', '>': { a: Gun.time.is() - 2, z: Gun.time.is() - 2 }}, a: 1, z: 1 }, 'fdsa': { _: {'#': 'fdsa', '>': { b: Gun.time.is() - 1, z: Gun.time.is() - 1 }}, b: 2, z: 2 }, 'sadf': { _: {'#': 'sadf', '>': { c: Gun.time.is(), z: Gun.time.is() - 100 }}, c: 3, z: 3 }, 'soul': { _: {'#': 'soul', '~': 1, '>': { 'asdf': Gun.time.is(), 'fdsa': Gun.time.is(), 'sadf': Gun.time.is() }}, 'asdf': {'#': 'asdf'}, 'fdsa': {'#': 'fdsa'}, 'sadf': {'#': 'sadf'} } } var node = Gun.union.ify(graph, 'soul'); expect(Gun.node.soul(node)).to.be('soul'); expect(node.a).to.be(1); expect(node.b).to.be(2); expect(node.c).to.be(3); expect(node.z).to.be(2); }); }); describe('API', function(){ var gopt = {wire:{put:function(n,cb){cb()},get:function(k,cb){cb()}}}; if(Gun.window && location.search){ /*console.log("LOCALHOST PEER MUST BE ON!"); var peer = {url: 'http://localhost:8765/gun'}; Gun.on('opt', function(root){ if(root.opt.test_no_peer){ return this.to.next(root) } root.opt.peers = root.opt.peers || {}; root.opt.peers['http://localhost:8765/gun'] = peer; this.to.next(root); });*/ } Gun.on('create', function(root){ root.on('test', function(msg){ var put = msg.put; this.to.next(msg); root.on('out', msg); Gun.graph.is(put, function(n,s){ root.$.get(s).off() }); }) }) var gun = Gun(); it.skip('gun chain separation', function(done){ // TODO: UNDO! var gun = Gun(); var c1 = gun.put({hello: 'world'}); var c2 = gun.put({hi: 'earth'}); c1.on(function(val){ expect(val.hi).to.not.be.ok(); }); c2.on(function(val){ expect(val.hello).to.not.be.ok(); if(done.c){ return } done(); done.c = 1; }); }); describe.skip('timeywimey', function(){ // TODO: UNDO! it('kitty', function(done){ var g1 = gun.put({hey: 'kitty'}).key('timeywimey/kitty'); var g2 = gun.get('timeywimey/kitty').on(function(val){ delete val._; //console.log("kitty?", val); expect(val.hey).to.be('kitty'); expect(val.hi).to.not.be.ok(); expect(val.hello).to.not.be.ok(); expect(val.foo).to.not.be.ok(); if(done.c){ return } done(); done.c = 1; }); }); it('kitty puppy', function(done){ var g3 = gun.put({hey: 'kitty'}).key('timeywimey/kitty/puppy'); var g4 = gun.put({hi: 'puppy'}).key('timeywimey/kitty/puppy'); var g5 = gun.get('timeywimey/kitty/puppy').on(function(val){ //delete val._; //console.log("puppy?", val); expect(val.hey).to.be('kitty'); expect(val.hi).to.be('puppy'); if(done.c){ return } done(); done.c = 1; }); }); it('hello', function(done){ gun.get('timeywimey/hello').on(function(val){ //delete val._; //console.log("hello?", val); expect(val.hello).to.be('world'); if(done.c){ return } done(); done.c = 1; }); gun.put({hello: 'world'}).key('timeywimey/hello'); }); it('hello foo', function(done){ gun.get('timeywimey/hello/foo').on(function(val){ //delete val._; expect(val.hello).to.be('world'); if(val.foo){ expect(val.foo).to.be('bar'); if(done.c){ return } done(); done.c = 1; } }); gun.put({hello: 'world'}).key('timeywimey/hello/foo'); gun.put({foo: 'bar'}).key('timeywimey/hello/foo'); }); it('all', function(done){ gun.put({hey: 'kitty'}).key('timeywimey/all'); gun.put({hi: 'puppy'}).key('timeywimey/all'); gun.get('timeywimey/all').on(function(val){ // console.log('all', done.c, val); expect(val.hey).to.be('kitty'); expect(val.hi).to.be('puppy'); if(val.hello){ expect(val.hello).to.be('world'); done.hello = true; } if(val.foo){ expect(val.foo).to.be('bar'); if(done.c || !done.hello){ return } done(); done.c = 1; } }); gun.put({hello: 'world'}).key('timeywimey/all'); gun.put({foo: 'bar'}).key('timeywimey/all'); }); }); describe('predictable souls', function(){ it('public', function(done){ gun.get('z').get('y').get('x').put({c: {b: {a: 1}}}, function(){ if(done.c){ return } done.c = 1; var g = gun._.graph; expect(g['z']).to.be.ok(); expect(g['z/y']).to.be.ok(); expect(g['z/y/x']).to.be.ok(); expect(g['z/y/x/c']).to.be.ok(); expect(g['z/y/x/c/b']).to.be.ok(); done(); }); }); it('public mix', function(done){ var ref = gun.get('zasdf').put({a: 9}); var at = gun.get('zfdsa').get('y').get('x').get('c').put(ref); at.get('foo').get('bar').put('yay'); ref.get('foo').get('ah').put(1, function(){ if(done.c){ return } done.c = 1; var g = gun._.graph; expect(Object.keys(g['zasdf']).sort()).to.be.eql(['_', 'a', 'foo'].sort()); expect(Object.keys(g['zasdf/foo']).sort()).to.be.eql(['_', 'bar', 'ah'].sort()); done(); }); }); }); describe('plural chains', function(){ this.timeout(9000); it('uncached synchronous map on', function(done){ /* Biggest challenges so far: - Unsubscribe individual mapped next. ! - Performance deduplication on asking relation's next. ! - Replying immediately to parent cached contexts. - Performant read lock on write contexts. - Proxying event across maps. */ gun.on('test', {$: gun, put: Gun.graph.ify({ alice: { age: 26, name: "Alice", pet: {a:1, name: "Fluffy"} }, bob: { age: 29, name: "Bob!", pet: {b:2, name: "Frisky"} } }, Gun.state.map(), 'u/m')}); var check = {}, count = {}; gun.get('u/m').map().on(function(v,f){ check[f] = v; count[f] = (count[f] || 0) + 1; //console.log("***********", f, v); if(check.alice && check.bob){ clearTimeout(done.to); done.to = setTimeout(function(){ expect(check.alice.age).to.be(26); expect(check.alice.name).to.be('Alice'); expect(Gun.val.link.is(check.alice.pet)).to.be.ok(); //expect(count.alice).to.be(1); expect(check.bob.age).to.be(29); expect(check.bob.name).to.be('Bob!'); expect(Gun.val.link.is(check.bob.pet)).to.be.ok(); //expect(count.bob).to.be(1); done(); },10); } }); }); it('uncached synchronous map get on', function(done){ gun.on('test', {$: gun, put: Gun.graph.ify({ alice: { age: 26, name: "alice", pet: {a:1, name: "Fluffy"} }, bob: { age: 29, name: "bob", pet: {b:2, name: "Frisky"} } }, Gun.state.map(), 'u/m/p')}); var check = {}, count = {}; gun.get('u/m/p').map().get('name').on(function(v,f){ //console.log("*****************", f, v); check[v] = f; count[v] = (count[v] || 0) + 1; if(check.alice && check.bob){ clearTimeout(done.to); done.to = setTimeout(function(){ expect(check.alice).to.be('name'); expect(check.bob).to.be('name'); //expect(count.alice).to.be(1); //expect(count.bob).to.be(1); done(); },10); } }); }); it('uncached synchronous map get on node', function(done){ gun.on('test', {$: gun, put: Gun.graph.ify({ alice: { age: 26, name: "alice", pet: {a:1, name: "Fluffy"} }, bob: { age: 29, name: "bob", pet: {b:2, name: "Frisky"} } }, Gun.state.map(), 'u/m/p/n')}); var check = {}, count = {}; gun.get('u/m/p/n').map().get('pet').on(function(v,f){ //console.log("********************", f,v); check[v.name] = v; count[v.name] = (count[v.name] || 0) + 1; if(check.Fluffy && check.Frisky){ clearTimeout(done.to); done.to = setTimeout(function(){ expect(check.Fluffy.a).to.be(1); expect(check.Frisky.b).to.be(2); //expect(count.Fluffy).to.be(1); //expect(count.Frisky).to.be(1); //expect(count['undefined']).to.not.be.ok(); if(done.c){return}done.c=1; done(); },10); } }); }); it('uncached synchronous map get on node get', function(done){ var gun = Gun(); gun.on('test', {$: gun, put: Gun.graph.ify({ alice: { age: 26, name: "alice", pet: {a:1, name: "Fluffy"} }, bob: { age: 29, name: "bob", pet: {b:2, name: "Frisky"} } }, Gun.state.map(), 'u/m/p/n/p')}); var check = {}, count = {}; //console.debug.i=1;console.log('-------------------'); gun.get('u/m/p/n/p').map().get('pet').get('name').on(function(v,f){ check[v] = f; count[v] = (count[v] || 0) + 1; //console.log("*****************", f, v); if(check.Fluffy && check.Frisky){ clearTimeout(done.to); done.to = setTimeout(function(){ expect(check.Fluffy).to.be('name'); expect(check.Frisky).to.be('name'); //console.log("????", gun._.graph); Gun.obj.map(gun._.graph, function(n,s){ if('u/m/p/n/p' === s){ return } var a = Gun.obj.map(n, function(v,f,t){t(v)}); expect(a.length).to.be(2); // make sure that ONLY the selected properties were loaded, not the whole node. }); //expect(count.Fluffy).to.be(1); //expect(count.Frisky).to.be(1); done(); },10); } }); }); it('uncached synchronous map on mutate', function(done){ gun.on('test', {$: gun, put: Gun.graph.ify({ alice: { age: 26, name: "Alice", pet: {a:1, name: "Fluffy"} }, bob: { age: 29, name: "Bob",