Add model tests

This commit is contained in:
Ritchie Martori 2014-01-28 14:32:13 -08:00
parent 2582c3fc65
commit a0e595dce8
3 changed files with 184 additions and 96 deletions

View File

@ -338,6 +338,20 @@ Model.checkpoint = function(cb) {
}); });
} }
/**
* Get the current checkpoint id.
*
* @callback {Function} callback
* @param {Error} err
* @param {Number} currentCheckpointId
* @end
*/
Model.currentCheckpoint = function(cb) {
var Checkpoint = this.getChangeModel().getCheckpointModel();
Checkpoint.current(cb);
}
/** /**
* Replicate changes since the given checkpoint to the given target model. * Replicate changes since the given checkpoint to the given target model.
* *
@ -489,6 +503,12 @@ Model.bulkUpdate = function(updates, callback) {
async.parallel(tasks, callback); async.parallel(tasks, callback);
} }
/**
* Get the `Change` model.
*
* @return {Change}
*/
Model.getChangeModel = function() { Model.getChangeModel = function() {
var changeModel = this.Change; var changeModel = this.Change;
if(changeModel) return changeModel; if(changeModel) return changeModel;
@ -497,8 +517,25 @@ Model.getChangeModel = function() {
return changeModel; return changeModel;
} }
/**
* Get the source identifier for this model / dataSource.
*
* @callback {Function} callback
* @param {Error} err
* @param {String} sourceId
*/
Model.getSourceId = function(cb) { Model.getSourceId = function(cb) {
cb(null, 'foo') var dataSource = this.dataSource;
if(!dataSource) {
this.once('dataSourceAttached', this.getSourceId.bind(this, cb));
}
assert(
dataSource.connector.name,
'Model.getSourceId: cannot get id without dataSource.connector.name'
);
var id = [dataSource.connector.name, this.modelName].join('-');
cb(null, id);
} }
/** /**

View File

@ -253,8 +253,11 @@ describe('Change', function(){
it('should return delta and conflict lists', function (done) { it('should return delta and conflict lists', function (done) {
var remoteChanges = [ var remoteChanges = [
// an update => should result in a delta
{rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1}, {rev: 'foo2', prev: 'foo', modelName: this.modelName, modelId: 9, checkpoint: 1},
// no change => should not result in a delta / conflict
{rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1}, {rev: 'bar', prev: 'bar', modelName: this.modelName, modelId: 10, checkpoint: 1},
// a conflict => should result in a conflict
{rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1}, {rev: 'bat2', prev: 'bat0', modelName: this.modelName, modelId: 11, checkpoint: 1},
]; ];

View File

@ -1,4 +1,7 @@
var ACL = require('../').ACL; var async = require('async');
var loopback = require('../');
var ACL = loopback.ACL;
var Change = loopback.Change;
describe('Model', function() { describe('Model', function() {
@ -523,33 +526,33 @@ describe('Model', function() {
describe('Model.extend() events', function() { describe('Model.extend() events', function() {
it('create isolated emitters for subclasses', function() { it('create isolated emitters for subclasses', function() {
var User1 = loopback.createModel('User1', { var User1 = loopback.createModel('User1', {
'first': String, 'first': String,
'last': String 'last': String
}); });
var User2 = loopback.createModel('User2', { var User2 = loopback.createModel('User2', {
'name': String 'name': String
}); });
var user1Triggered = false; var user1Triggered = false;
User1.once('x', function(event) { User1.once('x', function(event) {
user1Triggered = true; user1Triggered = true;
}); });
var user2Triggered = false; var user2Triggered = false;
User2.once('x', function(event) { User2.once('x', function(event) {
user2Triggered = true; user2Triggered = true;
}); });
assert(User1.once !== User2.once); assert(User1.once !== User2.once);
assert(User1.once !== loopback.Model.once); assert(User1.once !== loopback.Model.once);
User1.emit('x', User1); User1.emit('x', User1);
assert(user1Triggered); assert(user1Triggered);
assert(!user2Triggered); assert(!user2Triggered);
}); });
}); });
@ -581,80 +584,125 @@ describe('Model', function() {
} }
}); });
// describe('Model.hasAndBelongsToMany()', function() { describe('Model.getChangeModel()', function() {
// it("TODO: implement / document", function(done) { it('Get the Change Model', function () {
// /* example - var UserChange = User.getChangeModel();
// var change = new UserChange();
// */ assert(change instanceof Change);
// done(new Error('test not implemented')); });
// }); });
// });
// describe('Model.remoteMethods()', function() { describe('Model.getSourceId(callback)', function() {
// it("Return a list of enabled remote methods", function() { it('Get the Source Id', function (done) {
// app.model(User); User.getSourceId(function(err, id) {
// User.remoteMethods(); // ['save', ...] assert.equal('memory-user', id);
// }); done();
// }); });
});
});
// describe('Model.availableMethods()', function() { describe('Model.checkpoint(callback)', function() {
// it("Returns the currently available api of a model as well as descriptions of any modified behavior or methods from attached data sources", function(done) { it('Create a checkpoint', function (done) {
// /* example - var Checkpoint = User.getChangeModel().getCheckpointModel();
// User.attachTo(oracle); var tasks = [
// console.log(User.availableMethods()); getCurrentCheckpoint,
// checkpoint
// { ];
// 'User.all': { var result;
// accepts: [{arg: 'filter', type: 'object', description: '...'}], var current;
// returns: [{arg: 'users', type: ['User']}]
// }, async.parallel(tasks, function(err) {
// 'User.find': { if(err) return done(err);
// accepts: [{arg: 'id', type: 'any'}],
// returns: [{arg: 'items', type: 'User'}] assert.equal(result, current + 1);
// }, done();
// ... });
// }
// var oracle = loopback.createDataSource({ function getCurrentCheckpoint(cb) {
// connector: 'oracle', Checkpoint.current(function(err, cp) {
// host: '111.22.333.44', current = cp;
// database: 'MYDB', cb(err);
// username: 'username', });
// password: 'password' }
// });
// function checkpoint(cb) {
// */ User.checkpoint(function(err, cp) {
// done(new Error('test not implemented')); result = cp.id;
// }); cb(err);
// }); });
}
// describe('Model.before(name, fn)', function(){ });
// it('Run a function before a method is called', function() { });
// // User.before('save', function(user, next) {
// // console.log('about to save', user); describe('Replication / Change APIs', function() {
// // beforeEach(function(done) {
// // next(); var test = this;
// // }); this.dataSource = loopback.createDataSource({connector: loopback.Memory});
// // var SourceModel = this.SourceModel = this.dataSource.createModel('SourceModel', {}, {
// // User.before('delete', function(user, next) { trackChanges: true
// // // prevent all delete calls });
// // next(new Error('deleting is disabled')); var TargetModel = this.TargetModel = this.dataSource.createModel('TargetModel', {}, {
// // }); trackChanges: true
// // User.beforeRemote('save', function(ctx, user, next) { });
// // if(ctx.user.id === user.id) {
// // next(); var createOne = SourceModel.create.bind(SourceModel, {
// // } else { name: 'baz'
// // next(new Error('must be logged in to update')) });
// // }
// // }); async.parallel([
// createOne,
// throw new Error('not implemented'); function(cb) {
// }); SourceModel.currentCheckpoint(function(err, id) {
// }); if(err) return cb(err);
// test.startingCheckpoint = id;
// describe('Model.after(name, fn)', function(){ cb();
// it('Run a function after a method is called', function() { });
// }
// throw new Error('not implemented'); ], process.nextTick.bind(process, done));
// }); });
// });
describe('Model.changes(since, filter, callback)', function() {
it('Get changes since the given checkpoint', function (done) {
this.SourceModel.changes(this.startingCheckpoint, {}, function(err, changes) {
assert.equal(changes.length, 1);
done();
});
});
});
describe('Model.replicate(since, targetModel, options, callback)', function() {
it('Replicate data using the target model', function (done) {
var test = this;
var options = {};
var sourceData;
var targetData;
this.SourceModel.replicate(this.startingCheckpoint, this.TargetModel,
options, function(err, conflicts) {
assert(conflicts.length === 0);
async.parallel([
function(cb) {
test.SourceModel.find(function(err, result) {
if(err) return cb(err);
sourceData = result;
cb();
});
},
function(cb) {
test.TargetModel.find(function(err, result) {
if(err) return cb(err);
targetData = result;
cb();
});
}
], function(err) {
if(err) return done(err);
assert.deepEqual(sourceData, targetData);
done();
});
});
});
});
});
}); });