diff --git a/test/common_test.js b/test/common_test.js index adc87eb9..ffb179ec 100644 --- a/test/common_test.js +++ b/test/common_test.js @@ -38,6 +38,26 @@ if (process.env.ONLY && !testPerformed) { performTestFor(process.env.ONLY); } +function clearAndCreate(model, data, callback) { + var createdItems = []; + model.destroyAll(function () { + nextItem(null, null); + }); + + var itemIndex = 0; + function nextItem(err, lastItem) { + if (lastItem !== null) { + createdItems.push(lastItem); + } + if (itemIndex >= data.length) { + callback(createdItems); + return; + } + model.create(data[itemIndex], nextItem); + itemIndex++; + } +} + function performTestFor(schemaName) { testPerformed = true; context(schemaName, function () { @@ -123,6 +143,7 @@ function testOrm(schema) { }); Passport.belongsTo(User, {as: 'owner', foreignKey: 'ownerId'}); + User.hasMany(Passport, {as: 'passports', foreignKey: 'ownerId'}); var user = new User; @@ -455,6 +476,7 @@ function testOrm(schema) { test.done(); }); + it('should handle hasMany relationship', function (test) { User.create(function (err, u) { if (err) return console.log(err); @@ -610,6 +632,237 @@ function testOrm(schema) { }; }); + if ( + !schema.name.match(/redis/) && + schema.name !== 'memory' && + schema.name !== 'neo4j' && + schema.name !== 'cradle' + ) + it('should handle include function', function (test) { + var createdUsers = []; + var createdPassports = []; + var createdPosts = []; + var context = null; + + createUsers(); + function createUsers() { + clearAndCreate( + User, + [ + {name: 'User A', age: 21}, + {name: 'User B', age: 22}, + {name: 'User C', age: 23}, + {name: 'User D', age: 24}, + {name: 'User E', age: 25} + ], + function(items) { + createdUsers = items; + createPassports(); + } + ); + } + + function createPassports() { + clearAndCreate( + Passport, + [ + {number: '1', ownerId: createdUsers[0].id}, + {number: '2', ownerId: createdUsers[1].id}, + {number: '3'} + ], + function(items) { + createdPassports = items; + createPosts(); + } + ); + } + + function createPosts() { + clearAndCreate( + Post, + [ + {title: 'Post A', userId: createdUsers[0].id}, + {title: 'Post B', userId: createdUsers[0].id}, + {title: 'Post C', userId: createdUsers[0].id}, + {title: 'Post D', userId: createdUsers[1].id}, + {title: 'Post E'} + ], + function(items) { + createdPosts = items; + makeTests(); + } + ); + } + + function makeTests() { + var unitTests = [ + function() { + context = ' (belongsTo simple string from passports to users)'; + Passport.all({include: 'owner'}, testPassportsUser); + }, + function() { + context = ' (belongsTo simple string from posts to users)'; + Post.all({include: 'author'}, testPostsUser); + }, + function() { + context = ' (belongsTo simple array)'; + Passport.all({include: ['owner']}, testPassportsUser); + }, + function() { + context = ' (hasMany simple string from users to posts)'; + User.all({include: 'posts'}, testUsersPosts); + }, + function() { + context = ' (hasMany simple string from users to passports)'; + User.all({include: 'passports'}, testUsersPassports); + }, + function() { + context = ' (hasMany simple array)'; + User.all({include: ['posts']}, testUsersPosts); + }, + function() { + context = ' (Passports - User - Posts in object)'; + Passport.all({include: {'owner': 'posts'}}, testPassportsUserPosts); + }, + function() { + context = ' (Passports - User - Posts in array)'; + Passport.all({include: [{'owner': 'posts'}]}, testPassportsUserPosts); + }, + function() { + context = ' (Passports - User - Posts - User)'; + Passport.all({include: {'owner': {'posts': 'author'}}}, testPassportsUserPosts); + }, + function() { + context = ' (User - Posts AND Passports)'; + User.all({include: ['posts', 'passports']}, testUsersPostsAndPassports); + } + ]; + + function testPassportsUser(err, passports, callback) { + testBelongsTo(passports, 'owner', callback); + } + + function testPostsUser(err, posts, callback) { + testBelongsTo(posts, 'author', callback); + } + + function testBelongsTo(items, relationName, callback) { + if (typeof callback === 'undefined') { + callback = nextUnitTest; + } + var nbInitialRequests = nbSchemaRequests; + var nbItemsRemaining = items.length; + + for (var i = 0; i < items.length; i++) { + testItem(items[i]); + } + + function testItem(item) { + var relation = item.constructor.relations[relationName]; + var modelNameFrom = item.constructor.modelName; + var modelNameTo = relation.modelTo.modelName; + item[relationName](function(err, relatedItem) { + if (relatedItem !== null) { + test.equal(relatedItem[relation.keyTo], item[relation.keyFrom], modelNameTo + '\'s instance match ' + modelNameFrom + '\'s instance' + context); + } else { + test.ok(item[relation.keyFrom] == null, 'User match passport even when user is null.' + context); + } + nbItemsRemaining--; + if (nbItemsRemaining == 0) { + requestsAreCounted && test.equal(nbSchemaRequests, nbInitialRequests, 'No more request have been executed for loading ' + relationName + ' relation' + context) + callback(); + } + }); + } + } + + function testUsersPosts(err, users, expectedUserNumber, callback) { + if (typeof expectedUserNumber === 'undefined') { + expectedUserNumber = 5; + } + //console.log(users.length, expectedUserNumber); + test.equal(users.length, expectedUserNumber, 'Exactly ' + expectedUserNumber + ' users returned by query' + context); + testHasMany(users, 'posts', callback); + } + + function testUsersPassports(err, users, callback) { + testHasMany(users, 'passports', callback); + } + + function testHasMany(items, relationName, callback) { + if (typeof callback === 'undefined') { + callback = nextUnitTest; + } + var nbInitialRequests = nbSchemaRequests; + var nbItemRemaining = items.length; + for (var i = 0; i < items.length; i++) { + testItem(items[i]); + } + + function testItem(item) { + var relation = item.constructor.relations[relationName]; + var modelNameFrom = item.constructor.modelName; + var modelNameTo = relation.modelTo.modelName; + item[relationName](function(err, relatedItems) { + for (var j = 0; j < relatedItems.length; j++) { + test.equal(relatedItems[j][relation.keyTo], item[relation.keyFrom], modelNameTo + '\'s instances match ' + modelNameFrom + '\'s instance' + context); + } + nbItemRemaining--; + if (nbItemRemaining == 0) { + requestsAreCounted && test.equal(nbSchemaRequests, nbInitialRequests, 'No more request have been executed for loading ' + relationName + ' relation' + context) + callback(); + } + }); + } + } + + function testPassportsUserPosts(err, passports) { + testPassportsUser(err, passports, function() { + var nbPassportsRemaining = passports.length; + for (var i = 0; i < passports.length; i++) { + if (passports[i].ownerId !== null) { + passports[i].owner(function(err, user) { + testUsersPosts(null, [user], 1, function() { + nextPassport(); + }); + }); + } else { + nextPassport(); + } + } + function nextPassport() { + nbPassportsRemaining-- + if (nbPassportsRemaining == 0) { + nextUnitTest(); + } + } + }); + } + + function testUsersPostsAndPassports(err, users) { + testUsersPosts(err, users, 5, function() { + testUsersPassports(err, users, function() { + nextUnitTest(); + }); + }); + } + + var testNum = 0; + function nextUnitTest() { + if (testNum >= unitTests.length) { + test.done(); + return; + } + unitTests[testNum](); + testNum++; + + } + + nextUnitTest(); + } + + }); + it('should destroy all records', function (test) { Post.destroyAll(function (err) { if (err) {