gun
Version:
A realtime, decentralized, offline-first, graph data synchronization engine.
1,743 lines (1,657 loc) • 237 kB
JavaScript
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{ 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 {
require('../lib/yson');
root.Gun = require('../gun');
root.Gun.TESTING = true;
require('../lib/store');
require('../lib/rfs');
//console.log("UNDO THIS SO RAD & SEA RUN!");
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(){
it('deleting old GUN tests (may take long time)', function(done){
done(); // Mocha doesn't print test until after its done, so show this first.
});
it('deleted', function(done){
this.timeout(60 * 1000);
if(!Gun.window){ return done() }
indexedDB.deleteDatabase('radatatest').onsuccess = function(e){ done() }
});
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('YSON', function(){
it('parse', function(){
//var json = require('fs').readFileSync('./radix.json').toString();
//var json = require('fs').readFileSync('./data.json').toString();
//var json = require('fs').readFileSync('./big.json').toString();
//var json = require('fs').readFileSync('./stats.json').toString();
//var json = require('fs').readFileSync('./video.json').toString();
});
it('backslash', function(done){
var o = {z:"test\"wow\\"};
JSON.stringifyAsync(o, function(err,t){
JSON.parseAsync(t, function(err,data){
expect(data).to.be.eql(o);
next();
})
});
function next(){
JSON.parseAsync('{"webRTCsdp":"v=0\r\no=-"}', function(err,data){
var o = {webRTCsdp: 'v=0\r\no=-'};
expect(data).to.be.eql(o);
JSON.stringifyAsync(o, function(err,t){
expect(JSON.parse(t)).to.be.eql(o);
expect(t).to.be(JSON.stringify(o));
expect(t).to.be('{"webRTCsdp":"v=0\\r\\no=-"}');
JSON.parseAsync(t, function(err,d){
expect(d).to.be.eql(o);
done();
})
});
})
}
});
it('stringify', function(done){
function Foo(){}; Foo.prototype.toJSON = function(){};
//var obj = {"what\"lol": {"a": 1, "b": true, "c": false, "d": null, "wow": [{"z": 9}, true, "hi", 3.3]}};
var obj = {"what": {"a": 1, "b": true, "c": false, "d": null, "wow": [{"z": 9}, true, "hi", 3.3]}};
var obj = [{x:"test 😎\\😄🔥",z:"test\\","what\"lol": {"0": 1.01},a:true,b: new Foo,c:3,y:"yes","get":{"#":"chat"},wow:undefined,foo:[1,function(){}, function(){}, 'go'],blah:{a:5,toJSON:function(){ return 9 }}}, {webRTCsdp: "v=0\r\no=-"}, [[]], 10e9, NaN];
JSON.stringifyAsync(obj, function(err, text){
JSON.parseAsync(text, function(err, data){
expect(data).to.be.eql([{x:"test 😎\\😄🔥",z:"test\\","what\"lol": {"0": 1.01},a:true,c:3,y:"yes","get":{"#":"chat"},foo:[1,null,null,'go'],blah:9}, {webRTCsdp: "v=0\r\no=-"}, [[]], 10e9, null]);
var obj = {a: [], b: [""], c: ["", 1], d: [1, ""], e: {"":[]}, "a\"b": {0: 1}, wow: {'': {cool: 1}}};obj.lol = {0: {sweet: 9}};obj.wat = {"": 'cool'};obj.oh = {phew: {}, "": {}};
JSON.stringifyAsync(obj, function(err, text2){
JSON.parseAsync(text2, function(err, data){
expect(data).to.be.eql(obj);
done();
})
})
})
});
});
});
describe('Type Check', function(){
it('random text',function(){
expect(String.random().length).to.be(24);
expect(String.random(11).length).to.be(11);
expect(String.random(4).length).to.be(4);
t.tr = String.random(2,'as'); expect((t.tr=='as'||t.tr=='aa'||t.tr=='sa'||t.tr=='ss')).to.be.ok();
});
it('match text',function(){
expect(String.match("user/mark", 'user/mark')).to.be.ok();
expect(String.match("user/mark/nadal", {'=': 'user/mark'})).to.not.be.ok();
expect(String.match("user/mark/nadal", {'*': 'user/'})).to.be.ok();
expect(String.match("email/mark@gunDB.io", {'*': 'user/'})).to.not.be.ok();
expect(String.match("user/mark/nadal", {'>': 'user/j', '<': 'user/o'})).to.be.ok();
expect(String.match("user/timber/nadal", {'>': 'user/c', '<': 'user/j'})).to.not.be.ok();
expect(String.match("user/timber/nadal", {'>': 'user/m', '<': 'user/u'})).to.be.ok();
expect(String.match("user/mark/nadal", {'>': 'user/a', '<': 'user/c'})).to.not.be.ok();
expect(String.match("mary", {'<': 'm'})).to.not.be.ok();
expect(String.match("mary", {'>': 'm'})).to.be.ok();
expect(String.match("m", {'>': 'm'})).to.be.ok(); // lex is inclusive because it evaluates stricter (=) to looser (>) comparisons, see docs.
expect(String.match("m", {'<': 'm'})).to.be.ok(); // lex is inclusive because it evaluates stricter (=) to looser (<) comparisons, see docs.
return; // below is OLD bloat, still available in lib/match.js
});
it('plain object',function(){
expect(Object.plain({})).to.be(true);
expect(Object.plain({a:1})).to.be(true);
expect(Object.plain(u)).to.be(false);
expect(Object.plain()).to.be(false);
expect(Object.plain(undefined)).to.be(false);
expect(Object.plain(null)).to.be(false);
expect(Object.plain(NaN)).to.be(false);
expect(Object.plain(0)).to.be(false);
expect(Object.plain(1)).to.be(false);
expect(Object.plain('')).to.be(false);
expect(Object.plain('a')).to.be(false);
expect(Object.plain([])).to.be(false);
expect(Object.plain([1])).to.be(false);
expect(Object.plain(false)).to.be(false);
expect(Object.plain(true)).to.be(false);
expect(Object.plain(function(){})).to.be(false);
expect(Object.plain(new Date())).to.be(false);
expect(Object.plain(/regex/)).to.be(false);
this.document && expect(Object.plain(document.createElement('div'))).to.be(false);
expect(Object.plain(new (function Class(){ this.x = 1; this.y = 2 })())).to.be(true);
});
it('empty',function(){
expect(Object.empty()).to.be(true);
expect(Object.empty({a:false})).to.be(false);
expect(Object.empty({a:false},['a'])).to.be(true);
expect(Object.empty({a:false},['a'])).to.be(true);
expect(Object.empty({a:false,b:1},['a'])).to.be(false);
expect(Object.empty({a:false,b:1},['a'])).to.be(false);
expect(Object.empty({a:false,b:1},['a','b'])).to.be(true);
expect(Object.empty({a:false,b:1,c:3},['a','b'])).to.be(false);
expect(Object.empty({1:1},'danger')).to.be(false);
});
});
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;
Object.keys(a.it).forEach(function(f){var v = a.it[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;
Object.keys(a.node).forEach(function(f){var v = a.node[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(-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('valid',function(){
expect(Gun.valid(false)).to.be(true);
expect(Gun.valid(true)).to.be(true);
expect(Gun.valid(0)).to.be(true);
expect(Gun.valid(1)).to.be(true);
expect(Gun.valid('')).to.be(true);
expect(Gun.valid('a')).to.be(true);
expect(Gun.valid({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.valid({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect(Gun.valid(Infinity)).to.be(false); // boohoo :(
expect(Gun.valid(-Infinity)).to.be(false); // boohoo :(
expect(Gun.valid(NaN)).to.be(false);
expect(Gun.valid([])).to.be(false);
expect(Gun.valid([1])).to.be(false);
expect(Gun.valid({})).to.be(false);
expect(Gun.valid({a:1})).to.be(false);
expect(Gun.valid(function(){})).to.be(false);
});
it('is link',function(){
expect(Gun.valid({'#':'somesoulidhere'})).to.be('somesoulidhere');
expect(Gun.valid({'#':'somethingelsehere'})).to.be('somethingelsehere');
expect('string' == typeof Gun.valid({'#':'somesoulidhere', and: 'nope'})).to.be(false);
expect('string' == typeof Gun.valid({or: 'nope', '#':'somesoulidhere'})).to.be(false);
expect('string' == typeof Gun.valid(false)).to.be(false);
expect('string' == typeof Gun.valid(true)).to.be(false);
expect('string' == typeof Gun.valid('')).to.be(false);
expect('string' == typeof Gun.valid('a')).to.be(false);
expect('string' == typeof Gun.valid(0)).to.be(false);
expect('string' == typeof Gun.valid(1)).to.be(false);
expect('string' == typeof Gun.valid(Infinity)).to.be(false); // boohoo :(
expect('string' == typeof Gun.valid(-Infinity)).to.be(false); // boohoo :(
expect('string' == typeof Gun.valid(NaN)).to.be(false);
expect('string' == typeof Gun.valid([])).to.be(false);
expect('string' == typeof Gun.valid([1])).to.be(false);
expect('string' == typeof Gun.valid({})).to.be(false);
expect('string' == typeof Gun.valid({a:1})).to.be(false);
expect('string' == typeof Gun.valid(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});
});
});
});
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);
});*/
}
var goff = Gun();
Gun.statedisk = function(o,s,cb){
goff.get(s).put(o, cb, {turn: function(fn){fn()}});
};
var gun = Gun();
var nopasstun = function(done, g){
g = (g || gun)._.root;
setTimeout(function(){
expect(g.pass).to.not.be.ok();
expect(g.stun).to.not.be.ok();
done && done();
},9);
}
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();
nopasstun(done, gun);
});
});
it('no not found on incremental write', function(done){
gun.get('nnfoiw').get('y').put({a:1}, function(ack){
if(ack.err){ return }
nopasstun(done, gun);
})
});
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', function(ack){ done.a = 1; end() });
ref.get('foo').get('ah').put(1, function(ack){ done.b = 1; end() });
function end(ack){
if(!done.a || !done.b){ return }
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());
nopasstun(done, gun);
};
//setTimeout(function(){ console.log('???', gun._.stun); }, 1700);
});
});
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.statedisk({ alice: { age: 26, name: "Alice", pet: {a:1, name: "Fluffy"} }, bob: { age: 29, name: "Bob!", pet: {b:2, name: "Frisky"} } }, 'u/m', function(){
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('string' == typeof Gun.valid(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('string' == typeof Gun.valid(check.bob.pet)).to.be.ok();
//expect(count.bob).to.be(1);
nopasstun(done, gun);
},10);
}
});
}, 1000);
});
it('uncached synchronous map get on', function(done){
Gun.statedisk({
alice: {
age: 26,
name: "alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/p', function(){
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);
nopasstun(done, gun);
},10);
}
});
}, 1000);
});
it('uncached synchronous map get on node', function(done){
Gun.statedisk({
alice: {
age: 26,
name: "alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/p/n', function() {
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;
nopasstun(done, gun);
},10);
}
});
}, 1000);
});
it('uncached synchronous map get on node get', function(done){
var gun = Gun();
Gun.statedisk({
alice: {
age: 26,
name: "alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/p/n/p', function() {
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){
Object.keys(gun._.graph).forEach(function(s,n){ n = gun._.graph[s];
if('u/m/p/n/p' === s){ return }
var a = Object.keys(n);//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);
nopasstun(done, gun);
},10);
}
});
}, 1000);
});
it('uncached synchronous map on mutate', function(done){
Gun.statedisk({
alice: {
age: 26,
name: "Alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "Bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/mutate', function() {
var check = {}, count = {};
gun.get('u/m/mutate').map().get('name').get(function(at,ev){
var e = at.err, v = at.put, f = at.get;
//console.log("****************", f,v);
check[v] = f;
count[v] = (count[v] || 0) + 1;
if(check.Alice && check.Bob && check['undefined']){
clearTimeout(done.to);
done.to = setTimeout(function(){
//expect(count.Alice).to.be(1);
//expect(count.Bob).to.be(1);
//expect(count['undefined']).to.be(1);
if(done.c){ return } done.c = 1;
nopasstun(done, gun);
},10);
}
});
setTimeout(function(){
gun.get('u/m/mutate').get('alice').put(7);
}, 300);
}, 1000);
});
it('uncached synchronous map on mutate node', function(done){
Gun.statedisk({
alice: {_:{'#':'umaliceo'},
age: 26,
name: "Alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "Bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/mutate/n', function() {
var check = {}, count = {};
gun.get('u/m/mutate/n').map().get('name').get(function(at,ev){
var e = at.err, v = at.put, f = at.get;
check[v] = f;
count[v] = (count[v] || 0) + 1;
//console.log("************", f,v);
if(check.Alice && check.Bob && check['undefined'] && check['Alice Zzxyz']){
clearTimeout(done.to);
done.to = setTimeout(function(){
expect(done.last).to.be.ok();
expect(check['Alice Aabca']).to.not.be.ok();
expect(count.Alice).to.be(1);
expect(count.Bob).to.be(1);
expect(count['undefined']).to.be(1);
expect(count['Alice Zzxyz']).to.be(1);
nopasstun(done, gun);
},200);
}
});
setTimeout(function(){
gun.get('u/m/mutate/n').get('alice').put({
_:{'#':'u/m/m/n/soul'},
name: 'Alice Zzxyz'
});
setTimeout(function(){
gun.get('umaliceo').put({
name: 'Alice Aabca'
});
done.last = true;
}, 10);
}, 300);
}, 1000);
});
it('uncached synchronous map on mutate node uncached', function(done){
Gun.statedisk({
alice: {_:{'#':'umaliceo1'},
age: 26,
name: "Alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "Bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/mutate/n/u', function() {
var check = {}, count = {};
gun.get('u/m/mutate/n/u').map().on(function(v,f){
check[v.name] = f;
count[v.name] = (count[v.name] || 0) + 1;
if(check.Alice && check.Bob && check['Alice Zzxyz']){
clearTimeout(done.to);
//console.log("****", f, v)
done.to = setTimeout(function(){
expect(done.last).to.be.ok();
//expect(check['Alice Aabca']).to.not.be.ok();
//expect(count['Alice']).to.be(1);
//expect(count['Bob']).to.be(1);
//expect(count['Alice Zzxyz']).to.be(1);
if(done.c){ return } done.c = 1;
nopasstun(done, gun);
},200);
}
});
setTimeout(function(){
Gun.statedisk({ name: 'Alice Zzxyz' }, 'u/m/m/n/u/soul', function() {
//console.debug.i=1;console.log("---------------");
gun.get('u/m/mutate/n/u').put({
alice: {'#':'u/m/m/n/u/soul'},
});
/*
{
users: {_:#users
alice: {#newalice}
}
}
*/
setTimeout(function(){
gun.get('umaliceo1').put({
name: 'Alice Aabca'
});
done.last = true;
}, 10);
}, 1000);
}, 300);
}, 1000);
});
it('uncached synchronous map on get mutate node uncached', function(done){
Gun.statedisk({
alice: {_:{'#':'umaliceo2'},
age: 26,
name: "Alice",
pet: {a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "Bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/p/mutate/n/u', function() {
var check = {}, count = {};
gun.get('u/m/p/mutate/n/u').map().get('name').on(function(v,f){
check[v] = f;
count[v] = (count[v] || 0) + 1;
//console.log("*************", f,v);
if(check.Alice && check.Bob && check['Alice Zzxyz']){
clearTimeout(done.to);
done.to = setTimeout(function(){
var a = Object.keys(gun._.graph['u/m/p/m/n/u/soul']); //Gun.obj.map(gun._.graph['u/m/p/m/n/u/soul'], function(v,f,t){t(v)});
expect(a.length).to.be(2);
expect(done.last).to.be.ok();
expect(check['Alice Aabca']).to.not.be.ok();
//expect(count.Alice).to.be(1);
//expect(count.Bob).to.be(1);
//expect(count['Alice Zzxyz']).to.be(1);
nopasstun(done, gun);
},200);
}
});
setTimeout(function(){
Gun.statedisk({ name: 'Alice Zzxyz', age: 34 }, 'u/m/p/m/n/u/soul', function() {
gun.get('u/m/p/mutate/n/u').put({
alice: {'#':'u/m/p/m/n/u/soul'},
});
setTimeout(function(){
gun.get('umaliceo2').put({
name: 'Alice Aabca'
});
done.last = true;
}, 10);
}, 1000);
}, 300);
}, 1000);
});
it('uncached synchronous map on get node mutate node uncached', function(done){
Gun.statedisk({
alice: {_:{'#':'umaliceo3'},
age: 26,
name: "Alice",
pet: {_:{'#':'sflufso'},a:1, name: "Fluffy"}
},
bob: {
age: 29,
name: "Bob",
pet: {b:2, name: "Frisky"}
}
}, 'u/m/p/n/mutate/n/u', function() {
var check = {}, count = {};
gun.get('u/m/p/n/mutate/n/u').map().get('pet').on(function(v,f){
check[v.name] = f;
count[v.name] = (count[v.name] || 0) + 1;
//console.log("*****************", f,v, check);
if(check.Fluffy && check.Frisky && check.Fuzzball){
clearTimeout(done.to);
done.to = setTimeout(function(){
expect(done.last).to.be.ok();
expect(check['Fluffs']).to.not.be.ok();
expect(count.Fluffy).to.be(1);
expect(count.Frisky).to.be(1);
expect(count.Fuzzball).to.be(1);
nopasstun(done, gun);
},200);
}
});
setTimeout(function(){
Gun.statedisk({
name: 'Alice Zzxyz', age: 34,
pet: {c:3, name: "Fuzzball"}
}, 'alice/fuzz/soul', function() {
gun.get('u/m/p/n/mutate/n/u').put({
alice: {'#':'alice/fuzz/soul'},
});
setTimeout(function(){
gun.get('sflufso').put({
name: 'Fluffs'
});
done.last = true;
}, 10);
}, 1000);
}, 300);
}, 1000);
});
it("unlink deeply nested", function(done){
Gun.statedisk({
a: {_:{'#':'audn'},
age: 26,
name: "Alice",
b: {_:{'#':'budn'}, c: {_:{'#':'cudn'}, id: 'first', level: 3}, level: 2}
}
}, 'udn', function() {
var check = {}, count = {};
gun.get('udn').get('a').get('b').get('c').on(function(data){
//console.log("udn.a.b.c:", data);
check[data.id] = 1;
count[data.id] = (count[data.id] || 0) + 1;
expect(data.foo).to.not.be.ok();
//console.log("*****************", f,v, check);
if(check.first && check.other){
clearTimeout(done.to);
done.to = setTimeout(function(){
expect(done.last).to.be.ok();
expect(check.firsta).to.not.be.ok();
expect(count.first).to.be(1);
expect(count.other).to.be(1);
nopasstun(done, gun);
},200);
}
});
setTimeout(function(){
Gun.statedisk({
name: 'Alice2', age: 34,
b: {_:{'#':'2budn'}, c: {_:{'#':'2cudn'}, id: 'other', level: 3}, level: 2}
}, '2audn', function() {
//console.only.i=1;console.log('=============================');
gun.get('udn').put({
a: {'#':'2audn'}
});
setTimeout(function(){
//console.log("- - - - - - - - - - - -");
gun.get('cudn').put({id: 'firsta', foo: 'bar'});
done.last = 1;
}, 50);
});
},50);
});
});
it("get before put in memory", function(done){
var gun = Gun();
var check = {};
var count = {};
gun.get('g/n/m/f/l/n/r').map().on(function(v,f){
//console.log("***********", f,v);
check[f] = v;
count[f] = (count[f] || 0) + 1;
if(check.alice && check.bob && check.alice.PhD){
clearTimeout(done.to);
done.to = setTimeout(function(){
expect(check.alice.age).to.be(24);
expect(check.bob.age).to.be(26);
expect(check.alice.PhD).to.be(true);
//expect(count.alice).to.be(2);
//expect(count.bob).to.be(1);
if(done.c){return} done.c=1;
nopasstun(done, gun);
},50);
}
});
gun.put({_:{'#':'g/n/m/f/l/n/r'},
alice: {_:{'#':'GALICE1'},
name: "alice",
age: 24,
spouse: {
name: "carl",
age: 25,
work: {
name: "GUN INC"
}
},
bout: {huh:1}
},
bob: {
name: "bob",
age: 26,
spouse: {
name: "diana",
age: 27,
work: {
name: "ACME INC"
}
}
}
});
setTimeout(function(){
gun.get('GALICE1').put({PhD: true});
},300);
});
it("in memory get after", function(done){
var gun = Gun();
gun.put({_:{'#':'g/n/m/f/l/n'},
alice: {_:{'#':'GALICE2'},
name: "alice",
age: 24,
spouse: {
name: "carl",
age: 25,
work: {
name: "GUN INC"
}
},
bout: {huh:1}
},
bob: {
name: "bob",
age: 26,
spouse: {
name: "diana",
age: 27,
work: {
name: "ACME INC"
}
}
}
});
var check = {};
//gun.get('g/n/m/f/l/n').get('bob.spouse.work').on(function(v,f){ console.log("!!!!!!!!!", f, v);});return;
gun.get('g/n/m/f/l/n').map().on(function(v,f){
check[f] = v;
//console.log("*******************", f, v);
if(check.alice && check.bob && c