UNPKG

simple-node-db

Version:

A document database with query, insert, update, backup/restore and replication implemented on top of levelup, leveldown, and memdown.

378 lines (282 loc) 10.9 kB
/** * @class SimpleNodeDbTests * * @author: darryl.west@roundpeg.com * @created: 5/24/14 1:10 PM */ const should = require('chai').should(); const dash = require('lodash'); const TestDbDataset = require('./fixtures/TestDbDataset' ); const SimpleNodeDb = require('../lib/SimpleNodeDb' ); const levelup = require( 'levelup' ); const fs = require('fs'); describe('SimpleNodeDb', function() { 'use strict'; const dataset = new TestDbDataset(); const backupFilename = './backups/db-backup.dat'; const populateDatabase = function(db, batch, done) { const ldb = db.__protected().levelDb; ldb.batch( batch, function(err) { if (err) throw err; done(); }); }; describe('#instance', function() { const methods = [ 'query', 'queryKeys', 'find', 'update', 'insert', 'delete', 'backup', 'restore', 'stats', 'isInMemory', 'open', 'close', 'createModelId', 'createDomainKey', 'parseModel', '__protected' ]; it('should create a memory-only instance of SimpleNodeDb', function() { const db = new SimpleNodeDb(); should.exist( db ); db.should.be.instanceof( SimpleNodeDb ); db.isInMemory().should.equal( true ); db.__protected().readAfterChange.should.equal( true ); }); it('should create a file-based instance of SimpleNodeDb', function(done) { const dbfile = `./simpledb-test-${dash.random(1000, 9999)}`; const db = new SimpleNodeDb( dbfile ); should.exist( db ); fs.exists( dbfile, function(exists) { // exists.should.equal( true ); db.close(function() { levelup.destroy( dbfile ); done(); }); }); }); it('should have all know methods by size and type', function() { const db = new SimpleNodeDb(); Object.keys( db ).length.should.equal( methods.length ); methods.forEach(function(method) { db[ method ].should.be.a( 'function' ); }); }); }); describe('find', function() { const db = new SimpleNodeDb(); const users = dataset.createUserList( 23 ); const employees = dataset.createUserList( 34 ); const batch = []; dataset.createPutBatch( 'user', users, batch ); dataset.createPutBatch( 'employee', employees, batch ); beforeEach(function(done) { populateDatabase( db, batch, done ); }); it('should return a known model', function(done) { const user = users[ 4 ]; const key = db.createDomainKey( 'user', user.id ); const callback = function(err, model) { should.not.exist( err ); should.exist( model ); model.id.should.equal( user.id ); done(); }; db.find( key, callback ); }); }); describe('insert', function() { it('should insert a new model and set dateCreated, lastUpdated and version', function(done) { const user = dataset.createUserModel(); const db = new SimpleNodeDb(); const key = db.createDomainKey( 'user', user.id ); const callback = function(err, model) { if (err) { throw err; } should.not.exist( err ); should.exist( model ); // TODO find the user from id model.id.should.equal( user.id ); should.exist( model.dateCreated ); should.exist( model.lastUpdated ); model.version.should.equal( 0 ); const ldb = db.__protected().levelDb; ldb.get( key, function(err, u) { should.not.exist( err ); should.exist( u ); const obj = JSON.parse( u ); obj.id.should.equal( user.id ); done(); }); }; db.insert( key, user, callback ); }); it('should reject a non-object model', function(done) { const model = 'this is a bad model'; const key = 'bad key'; const db = new SimpleNodeDb(); const callback = function(err, result) { should.exist( err ); should.not.exist( result ); done(); }; db.insert( key, model, callback ); }); }); describe('update', function() { let user = dataset.createUserModel(); const db = new SimpleNodeDb(); const key = db.createDomainKey( 'user', user.id ); db.insert( key, user, function(err, model) { user = model; }); it('should update an existing model', function(done) { const version = user.version; const callback = function(err, model) { should.not.exist( err ); should.exist( model ); model.version.should.equal( version + 1 ); done(); }; db.update( key, user, callback ); }); }); describe('query', function() { const db = new SimpleNodeDb(); const size = 35; const users = dataset.createUserList( size ); const batch = dataset.createPutBatch( 'user', users ); beforeEach(function(done) { populateDatabase( db, batch, done ); }); it('should return a list of known models', function(done) { const params = {}; const rowCallback = function(key, value) { return JSON.parse( value ); }; const completeCallback = function(err, list) { should.not.exist( err ); should.exist( list ); list.length.should.be.equal( size ); const user = list[0]; should.exist( user.id ); done(); }; db.query( params, rowCallback, completeCallback ); }); }); describe('queryKeys', function() { const db = new SimpleNodeDb(); const size = 30; const users = dataset.createUserList( size ); const batch = dataset.createPutBatch( 'user', users ); beforeEach(function(done) { populateDatabase( db, batch, done ); }); it('should return a list of known keys', function(done) { const params = {}; const completeCallback = function(err, keys) { should.not.exist( err ); should.exist( keys ); // console.log( keys ); keys.length.should.be.equal( size ); keys[0].indexOf('user:' ).should.equal( 0 ); done(); }; db.queryKeys( params, completeCallback ); }); }); describe('delete', function() { const db = new SimpleNodeDb(); const size = 8; const users = dataset.createUserList( size ); const batch = dataset.createPutBatch( 'user', users ); beforeEach(function(done) { populateDatabase( db, batch, done ); }); it('should remove a known row from the database', function(done) { const user = users[ 4 ]; const key = db.createDomainKey( 'user', user.id ); const callback = function(err) { should.not.exist( err ); done(); }; db.delete( key, callback ); }); }); describe('backup', function() { const db = new SimpleNodeDb(); const users = dataset.createUserList(); const batch = dataset.createPutBatch( 'user', users ); const filename = '/tmp/db-backup.dat'; beforeEach(function(done) { populateDatabase( db, batch, done ); }); it('should backup a database to a file', function(done) { const callback = function(err, count) { should.not.exist( err ); should.exist( count ); count.should.equal( users.length ); done(); }; db.backup( filename, callback ); }); }); describe('restore', function() { const db = new SimpleNodeDb(); it('should restore a database from a file', function(done) { const callback = function(err, count) { should.not.exist( err ); should.exist( count ); count.should.equal( 10 ); done(); }; db.restore( backupFilename, callback ); }); it('should not restore a file that has a parse error'); }); describe('stats', function() { const db = new SimpleNodeDb(); const users = dataset.createUserList( 23 ); const employees = dataset.createUserList( 34 ); const batch = []; dataset.createPutBatch( 'user', users, batch ); dataset.createPutBatch( 'employee', employees, batch ); beforeEach(function(done) { populateDatabase( db, batch, done ); }); it('should report database stats', function(done) { const callback = function(err, stats) { should.not.exist( err ); should.exist( stats ); console.log( stats ); stats.rowcount.should.equal( users.length + employees.length ); dash.size( stats.domains ).should.equal( 2 ); stats.domains.user.should.equal( users.length ); stats.domains.employee.should.equal( employees.length ); done(); }; db.stats( callback ); }); }); describe('parseModel', function() { const db = new SimpleNodeDb(); const user = dataset.createUserModel(); // console.log( user ); it('should parse a json model and set dates to date type', function() { const json = JSON.stringify( user ); const model = db.parseModel( json ); should.exist( model ); model.id.should.equal( user.id ); model.dateCreated.should.be.instanceof( Date ); model.lastUpdated.should.be.instanceof( Date ); model.dateCreated.getTime().should.equal( user.dateCreated.getTime() ); model.lastUpdated.getTime().should.equal( user.lastUpdated.getTime() ); }); }); });