water-orm
Version:
A monolith version of Standalone waterline ORM
353 lines (257 loc) • 11.3 kB
JavaScript
var assert = require('assert'),
Promise = require('bluebird'),
_ = require('lodash');
describe('Association Interface', function() {
describe('n:m association :: .update()', function() {
describe('update nested associations()', function() {
describe('with single level depth', function() {
describe('when association doesn\'t exist', function() {
/////////////////////////////////////////////////////
// TEST SETUP
////////////////////////////////////////////////////
var Driver;
before(function(done) {
Associations.Driver.create({ name: 'm:m update nested' }).exec(function(err, driver) {
if(err) return done(err);
Driver = driver;
done();
});
});
/////////////////////////////////////////////////////
// TEST METHODS
////////////////////////////////////////////////////
it('should create a new taxi and associate it with a driver', function(done) {
var taxiData = {
name: 'm:m update nested - updated',
taxis: [
{ medallion: 1 }
]
};
Associations.Driver.update({ id: Driver.id }, taxiData).exec(function(err, values) {
assert.ifError(err);
// Look up the driver again to be sure the taxis were added
Associations.Driver.findOne(values[0].id)
.populate('taxis')
.exec(function(err, model) {
assert.ifError(err);
assert.equal(model.name, 'm:m update nested - updated');
assert.strictEqual(model.taxis.length, 1);
assert.strictEqual(model.taxis[0].medallion, 1);
done();
});
});
});
});
describe('when associations already exist', function() {
/////////////////////////////////////////////////////
// TEST SETUP
////////////////////////////////////////////////////
var Driver;
before(function(done) {
var data = {
name: 'm:m update nested',
taxis: [
{ medallion: 1 },
{ medallion: 2 }
]
};
Associations.Driver.create(data).exec(function(err, driver) {
if(err) return done(err);
Driver = driver;
done();
});
});
/////////////////////////////////////////////////////
// TEST METHODS
////////////////////////////////////////////////////
it('should reset associations with the updated associations', function(done) {
var taxiData = {
name: 'm:m update nested - updated',
taxis: [
{ medallion: 3 },
{ medallion: 4 },
{ medallion: 5 }
]
};
Associations.Driver.update({ id: Driver.id }, taxiData).exec(function(err, values) {
assert.ifError(err);
// Look up the driver again to be sure the taxis were added
Associations.Driver.findOne(values[0].id)
.populate('taxis',{sort : {medallion : 1}})
.exec(function(err, model) {
assert(!err, 'Error: ' + err);
assert.equal(model.name, 'm:m update nested - updated');
assert.strictEqual(model.taxis.length, 3);
assert.strictEqual(model.taxis[0].medallion, 3);
assert.strictEqual(model.taxis[1].medallion, 4);
assert.strictEqual(model.taxis[2].medallion, 5);
done();
});
});
});
});
describe('when associations have primary keys', function() {
/////////////////////////////////////////////////////
// TEST SETUP
////////////////////////////////////////////////////
var Driver, Taxis;
before(function(done) {
var taxiData = [
{ medallion: 1 },
{ medallion: 2 }
];
var data = {
name: 'm:m update nested',
taxis: [
{ medallion: 100 },
{ medallion: 200 }
]
};
Associations.Taxi.create(taxiData).exec(function(err, taxis) {
if(err) return done(err);
Taxis = taxis;
Associations.Driver.create(data).exec(function(err, driver) {
if(err) return done(err);
Driver = driver;
done();
});
});
});
/////////////////////////////////////////////////////
// TEST METHODS
////////////////////////////////////////////////////
it('should update association values', function(done) {
var taxiData = {
name: 'm:m update nested - updated',
taxis: Taxis.map(function(taxi) { return taxi.toObject(); })
};
Associations.Driver.update({ id: Driver.id }, taxiData).exec(function(err, values) {
assert.ifError(err);
// Look up the driver again to be sure the taxis were added
Associations.Driver.findOne(values[0].id)
.populate('taxis',{sort : {medallion : 1}})
.exec(function(err, model) {
assert.ifError(err);
assert.equal(model.name, 'm:m update nested - updated');
assert.strictEqual(model.taxis.length, 2);
// Ensure association values were updated
assert.strictEqual(model.taxis[0].medallion, 1);
assert.strictEqual(model.taxis[1].medallion, 2);
done();
});
});
});
});
describe('when associations already exist', function() {
/////////////////////////////////////////////////////
// TEST SETUP
////////////////////////////////////////////////////
var Driver;
before(function(done) {
var data = {
name: 'm:m update nested save',
taxis: [ { medallion: 1000 } ]
};
Associations.Driver.create(data).exec(function(err, driver) {
if(err) return done(err);
Driver = driver;
done();
});
});
/////////////////////////////////////////////////////
// TEST METHODS
////////////////////////////////////////////////////
it('should update association values with save()', function(done) {
Associations.Driver.findOne({ id: Driver.id })
.populate('taxis')
.exec(function(err, model) {
var taxi = model.taxis[0];
taxi.medallion = 1001;
taxi.save(function(err){
assert.ifError(err);
Associations.Driver.findOne({ id: Driver.id })
.populate('taxis')
.exec(function(err, model) {
assert.ifError(err);
assert.strictEqual(model.taxis.length, 1);
assert.strictEqual(model.taxis[0].medallion, 1001);
done();
});
});
});
});
});
describe('when associations are sync\'ed rapidly', function() {
/////////////////////////////////////////////////////
// TEST SETUP
////////////////////////////////////////////////////
var Drivers;
var Taxis;
before(function(done) {
var driversData = [
{name: "Rapid 0"},
{name: "Rapid 1"},
{name: "Rapid 2"},
{name: "Rapid 3"}
];
var taxisData = [
{medallion: 200},
{medallion: 201},
{medallion: 202},
{medallion: 203}
];
Associations.Driver.createEach(driversData).exec(function(err, drivers) {
if(err) return done(err);
Drivers = drivers;
Associations.Taxi.createEach(taxisData).exec(function(err, taxis) {
if(err) return done(err);
Taxis = taxis;
done();
});
});
});
/////////////////////////////////////////////////////
// TEST METHODS
////////////////////////////////////////////////////
it('should create the correct associations', function(done) {
// Construct promises
var associationMap = {};
var associationPromises = [];
var driverId, taxiId;
for (var i = 0, il = Drivers.length; i < il; ++i) {
driverId = _.find(Drivers, {name: "Rapid " + i}).id;
taxiId = _.find(Taxis, {medallion: 200 + i}).id;
// Set map for testing later. Maps driver to taxi being associated.
associationMap[driverId] = taxiId;
associationPromises.push(
Associations.Driver.update(driverId, {taxis: [{id: taxiId}]})
);
}
// Perform all updates at once
Promise.all(associationPromises)
.then(function(results){
// Check to see if associations were created as expected
Associations.Driver.find({id: _.map(Drivers, 'id')})
.populate('taxis')
.exec(function(err, drivers) {
if (err) return done(err);
assert.equal(drivers.length, Drivers.length);
// Ensure the correct operations happened per record using associationMap
var driver;
for (var i = 0, il = drivers.length; i < il; ++i) {
driver = drivers[i];
assert(typeof driver === "object" && driver !== null);
assert(Array.isArray(driver.taxis));
assert.equal(driver.taxis.length, 1);
assert.equal(driver.taxis[0].id, associationMap[driver.id]);
}
done();
});
})
.catch(done);
});
});
});
});
});
});