pathdb
Version:
Database built on levelup/leveldb that stores javascript objects as a series of paths and values.
170 lines (149 loc) • 4.26 kB
JavaScript
var expect = require('expect.js'),
level = require('level'),
bytewise = require('bytewise'),
path = require('path'),
rimraf = require('rimraf'),
diff = require('changeset'),
clone = require('clone'),
after = require('after'),
observejs = require('observejs'),
through2 = require('through2'),
pathdb = require('..');
describe('pathdb', function() {
var db, dbPath = path.join(__dirname, '..', 'data', 'testdb');
function noop() {}
var o;
beforeEach(function(done) {
o = {
name: 'Eugene',
number: 42,
tags: ['tag1', 'tag2', 'tag3'],
cars: [
{
make: 'Toyota',
model: 'Camry'
},
{
make: 'Toyota',
model: 'Corolla'
}
]
};
rimraf.sync(dbPath);
db = level(dbPath, { keyEncoding: bytewise, valueEncoding: 'json' });
done();
});
afterEach(function(done) {
db.close(done);
});
it('should be able to replicate replica changes', function(done) {
db = pathdb(db);
db.pathdb.put(['people'], { old: 'data' }, watch);
function watch(err) {
var obj;
if (err) return done(err);
db.pathdb.watch(['people'])
.on('value', function (value) {
expect(value).to.eql({ old: 'data' });
obj = clone(value);
obj.my = { changed: 'data' };
delete obj.old;
var changes = diff(value, obj);
db.pathdb.batch(['people'], changes, noop);
})
.on('change', function (changeset) {
diff.apply(changeset, obj, true);
expect(obj).to.eql({ my: { changed: 'data' }});
done();
})
.on('error', done);
}
});
it('should be able to replicate multiple replica changes', function(done) {
db = pathdb(db);
db.pathdb.put(['people'], { old: 'data' }, watches);
var obj, obj2;
var next = after(2, change);
var changed = after(4, check);
function watches(err) {
if (err) return done(err);
watch();
watch2();
}
function watch() {
db.pathdb.watch(['people'])
.on('value', function (value) {
expect(value).to.eql({ old: 'data' });
obj = clone(value);
next();
})
.on('change', function (changeset) {
diff.apply(changeset, obj, true);
changed();
})
.on('error', done);
}
function watch2() {
db.pathdb.watch(['people'])
.on('value', function (value) {
expect(value).to.eql({ old: 'data' });
obj2 = clone(value);
next();
})
.on('change', function (changeset) {
diff.apply(changeset, obj2, true);
changed();
})
.on('error', done);
}
function change() {
var old = clone(obj);
obj.my = { changed: 'data' };
delete obj.old;
db.pathdb.batch(['people'], diff(old, obj), noop);
obj2.a = { 'new': 'field' };
db.pathdb.batch(['people'], diff(old, obj2), noop);
}
function check() {
var expected = { my: { changed: 'data' }, a: { 'new': 'field' } };
expect(obj).to.eql(expected);
expect(obj2).to.eql(expected);
expect(obj).to.eql(obj2);
done();
}
});
it('should be able to replicate changes using observejs', function(done) {
db = pathdb(db);
db.pathdb.put(['people'], o, change);
var batch = [];
function change(err) {
if (err) return done(err);
var next = after(2, sync);
observejs.observe(o).pipe(through2({ objectMode: true },
function (chunk, enc, cb) {
batch.push(chunk);
next();
cb();
}));
o.name = 'Susan';
o.number = 21;
}
function sync() {
expect(batch).to.eql([
{ type: 'put', key: [ 'name' ], value: 'Susan' },
{ type: 'put', key: [ 'number' ], value: 21 }
]);
db.pathdb.batch(['people'], batch, get);
}
function get(err) {
if (err) return done(err);
db.pathdb.get(['people'], check);
}
function check(err, data) {
if (err) return done(err);
expect(o.name).to.equal('Susan');
expect(o.number).to.equal(21);
done();
}
});
});