Add tests for propagating a transaction over relations

This commit is contained in:
Raymond Feng 2015-05-15 16:59:59 -07:00
parent 8815e9c961
commit 97c9d54c43
3 changed files with 53 additions and 22 deletions

View File

@ -1039,7 +1039,8 @@ SQLConnector.prototype.all = function find(model, filter, options, cb) {
return self.fromRow(model, obj); return self.fromRow(model, obj);
}); });
if (filter && filter.include) { if (filter && filter.include) {
self.getModelDefinition(model).model.include(objs, filter.include, cb); self.getModelDefinition(model).model.include(
objs, filter.include, options, cb);
} else { } else {
cb(null, objs); cb(null, objs);
} }

View File

@ -10,20 +10,24 @@ var transactionId = 0;
function MockTransaction(connector, name) { function MockTransaction(connector, name) {
this.connector = connector; this.connector = connector;
this.name = name; this.name = name;
this.data = []; this.data = {};
} }
MockTransaction.prototype.commit = function(cb) { MockTransaction.prototype.commit = function(cb) {
var self = this; var self = this;
this.data.forEach(function(d) { // Merge data from this TX to the global data var
self.connector.collection.data.push(d); for (var m in this.data) {
}); self.connector.data[m] = self.connector.data[m] || [];
this.data = []; for (var i = 0, n = this.data[m].length; i < n; i++) {
self.connector.data[m].push(this.data[m]);
}
}
this.data = {};
cb(); cb();
}; };
MockTransaction.prototype.rollback = function(cb) { MockTransaction.prototype.rollback = function(cb) {
this.data = []; this.data = {};
cb(); cb();
}; };
@ -41,9 +45,7 @@ exports.initialize = function initializeDataSource(dataSource, callback) {
function TestConnector(settings) { function TestConnector(settings) {
SQLConnector.call(this, 'testdb', settings); SQLConnector.call(this, 'testdb', settings);
this._tables = {}; this._tables = {};
this.collection = { this.data = {};
data: []
};
} }
util.inherits(TestConnector, SQLConnector); util.inherits(TestConnector, SQLConnector);
@ -203,9 +205,12 @@ TestConnector.prototype.rollback = function(tx, cb) {
TestConnector.prototype.executeSQL = function(sql, params, options, callback) { TestConnector.prototype.executeSQL = function(sql, params, options, callback) {
var transaction = options.transaction; var transaction = options.transaction;
var model = options.model;
if (transaction && transaction.connector === this && transaction.connection) { if (transaction && transaction.connector === this && transaction.connection) {
if (sql.indexOf('INSERT') === 0) { if (sql.indexOf('INSERT') === 0) {
transaction.connection.data.push({title: 't1', content: 'c1'}); transaction.connection.data[model] =
transaction.connection.data[model] || [];
transaction.connection.data[model].push({sql: sql, params: params});
debug('INSERT', transaction.connection.data, sql, debug('INSERT', transaction.connection.data, sql,
transaction.connection.name); transaction.connection.name);
callback(null, 1); callback(null, 1);
@ -213,16 +218,17 @@ TestConnector.prototype.executeSQL = function(sql, params, options, callback) {
else { else {
debug('SELECT', transaction.connection.data, sql, debug('SELECT', transaction.connection.data, sql,
transaction.connection.name); transaction.connection.name);
callback(null, transaction.connection.data); callback(null, transaction.connection.data[model] || []);
} }
} else { } else {
if (sql.indexOf('INSERT') === 0) { if (sql.indexOf('INSERT') === 0) {
this.collection.data.push({title: 't1', content: 'c1'}); this.data[model] = this.data[model] || [];
debug('INSERT', this.collection.data, sql); this.data[model].push({sql: sql, params: params});
debug('INSERT', this.data, sql);
callback(null, 1); callback(null, 1);
} else { } else {
debug('SELECT', this.collection.data, sql); debug('SELECT', this.data, sql);
callback(null, this.collection.data); callback(null, this.data[model] || []);
} }
} }
}; };

View File

@ -6,6 +6,7 @@ var testConnector = require('./connectors/test-sql-connector');
var juggler = require('loopback-datasource-juggler'); var juggler = require('loopback-datasource-juggler');
var db, Post; var db, Post;
var Review;
describe('transactions', function() { describe('transactions', function() {
@ -19,6 +20,11 @@ describe('transactions', function() {
title: {type: String, length: 255, index: true}, title: {type: String, length: 255, index: true},
content: {type: String} content: {type: String}
}); });
Review = db.define('ReviewTX', {
author: String,
content: {type: String}
});
Post.hasMany(Review, {as: 'reviews', foreignKey: 'postId'});
done(); done();
}); });
}); });
@ -54,12 +60,18 @@ describe('transactions', function() {
next(); next();
}); });
currentTx = tx; currentTx = tx;
Post.create(post, {transaction: tx}, Post.create(post, {transaction: tx, model: 'Post'},
function(err, p) { function(err, p) {
if (err) { if (err) {
done(err); done(err);
} else { } else {
done(); p.reviews.create({
author: 'John',
content: 'Review for ' + p.title
}, {transaction: tx, model: 'Review'},
function(err, c) {
done(err);
});
} }
}); });
}); });
@ -70,7 +82,7 @@ describe('transactions', function() {
// records to equal to the count // records to equal to the count
function expectToFindPosts(where, count, inTx) { function expectToFindPosts(where, count, inTx) {
return function(done) { return function(done) {
var options = {}; var options = {model: 'Post'};
if (inTx) { if (inTx) {
options.transaction = currentTx; options.transaction = currentTx;
} }
@ -78,7 +90,19 @@ describe('transactions', function() {
function(err, posts) { function(err, posts) {
if (err) return done(err); if (err) return done(err);
expect(posts.length).to.be.eql(count); expect(posts.length).to.be.eql(count);
done(); if (count) {
// Find related reviews
options.model = 'Review';
// Please note the empty {} is required, otherwise, the options
// will be treated as a filter
posts[0].reviews({}, options, function(err, reviews) {
if (err) return done(err);
expect(reviews.length).to.be.eql(count);
done();
});
} else {
done();
}
}); });
}; };
} }
@ -114,7 +138,7 @@ describe('transactions', function() {
before(function() { before(function() {
// Reset the collection // Reset the collection
db.connector.collection.data = []; db.connector.data = {};
}); });
var post = {title: 't2', content: 'c2'}; var post = {title: 't2', content: 'c2'};
@ -146,7 +170,7 @@ describe('transactions', function() {
before(function() { before(function() {
// Reset the collection // Reset the collection
db.connector.collection.data = []; db.connector.data = {};
}); });
var post = {title: 't3', content: 'c3'}; var post = {title: 't3', content: 'c3'};