nodal
Version:
An API Server and Framework for node.js
1,785 lines (1,259 loc) • 44.8 kB
JavaScript
;
module.exports = Nodal => {
const async = require('async');
let expect = require('chai').expect;
describe('Nodal.Composer', function() {
let mainDb = new Nodal.Database();
let readonlyDb = new Nodal.Database();
let connectionParams = [{
db: mainDb,
config: Nodal.my.Config.db.main
}, {
db: readonlyDb,
config: Nodal.my.Config.db.readonly
}];
let originalParentNames = [
'Albert',
'Derek',
'Dingleberry',
'James',
'Joe',
'Sally',
'Samantha',
'Samuel',
'Suzy',
'Zoolander'
];
let schemaParent = {
table: 'parents',
columns: [
{name: 'id', type: 'serial'},
{name: 'name', type: 'string'},
{name: 'shirt', type: 'string'},
{name: 'hidden', type: 'string'},
{name: 'pantaloons', type: 'string'},
{name: 'created_at', type: 'datetime'},
{name: 'updated_at', type: 'datetime'}
]
};
let schemaCareer = {
table: 'careers',
columns: [
{name: 'id', type: 'serial'},
{name: 'parent_id', type: 'int'},
{name: 'title', type: 'string'},
{name: 'is_active', type: 'boolean'},
{name: 'created_at', type: 'datetime'},
{name: 'updated_at', type: 'datetime'}
]
};
let schemaFriendship = {
table: 'friendships',
columns: [
{name: 'id', type: 'serial'},
{name: 'from_parent_id', type: 'int'},
{name: 'to_parent_id', type: 'int'},
{name: 'created_at', type: 'datetime'},
{name: 'updated_at', type: 'datetime'}
]
};
let schemaChild = {
table: 'children',
columns: [
{name: 'id', type: 'serial'},
{name: 'parent_id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'age', type: 'int'},
{name: 'is_favorite', type: 'boolean'},
{name: 'license', type: 'string'},
{name: 'created_at', type: 'datetime'},
{name: 'updated_at', type: 'datetime'}
]
};
let schemaPartner = {
table: 'partners',
columns: [
{name: 'id', type: 'serial'},
{name: 'parent_id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'job', type: 'string'},
{name: 'full_time', type: 'boolean'},
{name: 'created_at', type: 'datetime'},
{name: 'updated_at', type: 'datetime'}
]
};
let schemaPet = {
table: 'pets',
columns: [
{name: 'id', type: 'serial'},
{name: 'parent_id', type: 'int'},
{name: 'name', type: 'string'},
{name: 'animal', type: 'string'},
{name: 'is_alive', type: 'boolean'},
{name: 'details', type: 'json'},
{name: 'created_at', type: 'datetime'},
{name: 'updated_at', type: 'datetime'}
]
};
class Parent extends Nodal.Model {}
Parent.setDatabase(mainDb);
Parent.setSchema(schemaParent);
Parent.hides('hidden');
class Career extends Nodal.Model {};
Career.setDatabase(mainDb);
Career.setSchema(schemaCareer);
Career.joinsTo(Parent, {multiple: true});
class Friendship extends Nodal.Model {}
Friendship.setDatabase(mainDb);
Friendship.setSchema(schemaFriendship);
Friendship.joinsTo(Parent, {name: 'fromParent', as: 'outgoingFriendships', multiple: true});
Friendship.joinsTo(Parent, {name: 'toParent', as: 'incomingFriendships', multiple: true});
class Child extends Nodal.Model {}
Child.setDatabase(mainDb);
Child.setSchema(schemaChild);
Child.joinsTo(Parent, {multiple: true});
class Partner extends Nodal.Model {}
Partner.setDatabase(mainDb);
Partner.setSchema(schemaPartner);
Partner.joinsTo(Parent);
class Pet extends Nodal.Model {}
Pet.setDatabase(mainDb);
Pet.setSchema(schemaPet);
Pet.joinsTo(Parent, {multiple: true});
before(function(done) {
async.series(connectionParams.map((connection) => {
return (cb) => {
let db = connection.db;
let config = connection.config;
db.connect(config);
db.enableLogs(true);
Parent.setDatabase(db);
Career.setDatabase(db);
Friendship.setDatabase(db);
Child.setDatabase(db);
Partner.setDatabase(db);
Pet.setDatabase(db);
db.transaction(
[
schemaParent,
schemaCareer,
schemaFriendship,
schemaChild,
schemaPartner,
schemaPet
].map(schema => {
return [
db.adapter.generateDropTableQuery(schema.table, true),
db.adapter.generateCreateTableQuery(schema.table, schema.columns)
].join(';');
}).join(';'),
function(err, result) {
expect(err).to.equal(null);
let parents = originalParentNames.map((name, i) => new Parent({
name: name,
shirt: ['red', 'green', 'blue'][i % 3],
pantaloons: ['jeans', 'shorts'][i % 2],
hidden: 'abcdef'.split('')[i % 6]
}));
parents = Nodal.ModelArray.from(parents);
parents.forEach((p, i) => {
let id = i + 1;
let careers = ['Freelancer', 'Poet'].map((title, n) => {
return new Career({parent_id: id, title: title, is_active: true});
});
p.setJoined('careers', Nodal.ModelArray.from(careers));
let children = 'ABCDEFGHIJ'.split('').map((name, n) => {
var ageOffset = (n >= 5) ? 16 : 0;
return new Child({
parent_id: id,
name: `Child${name}`,
age: ageOffset + ((Math.random() * 30) | 0),
is_favorite: !!(n % 2),
license: !!ageOffset ? 'DL_APPROVED' : null
});
});
p.setJoined('children', Nodal.ModelArray.from(children));
let pets = ['Oliver', 'Ruby', 'Pascal'].map((name, i) => {
return new Pet({
parent_id: id,
name: name,
animal: ['Cat', 'Dog', 'Cat'][i],
is_alive: true,
details: { language: name === 'Pascal' }
});
});
p.setJoined('pets', Nodal.ModelArray.from(pets));
let partner = new Partner({
parent_id: id,
name: `Partner${i}`,
job: ['Plumber', 'Engineer', 'Nurse', 'Scientist'][i % 4],
full_time: !!(i % 2)
});
p.setJoined('partner', partner);
let friendships = new Nodal.ModelArray(Friendship);
while (i--) {
let friendship = new Friendship({from_parent_id: id, to_parent_id: i + 1});
friendships.push(friendship);
}
p.setJoined('outgoingFriendships', friendships);
});
parents.saveAll(err => {
expect(err).to.equal(null);
async.series(
[].concat(
parents.map(p => p.joined('careers').saveAll.bind(p.joined('careers'))),
parents.map(p => p.joined('children').saveAll.bind(p.joined('children'))),
parents.map(p => p.joined('pets').saveAll.bind(p.joined('pets'))),
parents.map(p => p.joined('partner').save.bind(p.joined('partner'))),
parents.map(p => p.joined('outgoingFriendships').saveAll.bind(p.joined('outgoingFriendships'))).filter(p => p)
), (err) => {
expect(err).to.not.exist;
cb()
}
);
});
}
);
};
}), (err) => {
if (err) {
return done(err);
}
Parent.setDatabase(mainDb);
Career.setDatabase(mainDb);
Friendship.setDatabase(mainDb);
Child.setDatabase(mainDb);
Partner.setDatabase(mainDb);
Pet.setDatabase(mainDb);
return done();
});
});
after(function(done) {
async.series(connectionParams.map((connection) => {
return (cb) => {
connection.db.close(function() {
cb();
});
};
}), done);
});
it('Should query all parents (10)', function(done) {
Parent.query()
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents).to.be.an.instanceOf(Nodal.ModelArray);
expect(parents.length).to.equal(10);
done();
});
});
it('Should query all partners (10)', function(done) {
Partner.query()
.end((err, partners) => {
expect(err).to.equal(null);
expect(partners).to.be.an.instanceOf(Nodal.ModelArray);
expect(partners.length).to.equal(10);
done();
});
});
it('Should query all Children (100)', function(done) {
Child.query()
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(100);
done();
});
});
it('Should have parent lazy load models after fetching', (done) => {
Parent.query()
.limit(1)
.end((err, parents) => {
let parent = parents[0];
expect(err).to.equal(null);
expect(parent.joined('children')).to.be.undefined;
expect(parent.joined('partner')).to.be.undefined;
parent.include((err, children, partner) => {
expect(err).to.equal(null);
expect(children.length).to.equal(10);
expect(partner).to.exist;
expect(parent.joined('children')).to.equal(children);
expect(parent.joined('partner')).to.equal(partner);
done();
});
});
});
it('Should also lazy load from Child', (done) => {
Child.query()
.limit(1)
.end((err, children) => {
let child = children[0];
expect(err).to.equal(null);
expect(child.get('parent')).to.be.undefined;
child.include((err, parent) => {
expect(err).to.equal(null);
expect(parent).to.exist;
expect(child.joined('parent')).to.equal(parent);
done();
});
});
});
it('Should orderBy properly (DESC)', function(done) {
Child.query()
.orderBy('id', 'DESC')
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(100);
expect(children[0].get('id')).to.equal(100);
done();
});
});
it('Should orderBy a joined property properly (DESC)', function(done) {
Child.query()
.join('parent')
.orderBy('parent__name', 'DESC')
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(100);
expect(children[0].joined('parent').get('name')).to.equal('Zoolander');
expect(children[99].joined('parent').get('name')).to.equal('Albert');
done();
});
});
it('Should limit properly (10)', function(done) {
Child.query()
.limit(5, 10)
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(10);
expect(children._meta.total).to.equal(100);
expect(children._meta.offset).to.equal(5);
done();
});
});
it('Should limit properly with an undefined offset', function(done) {
Child.query()
.limit(undefined, 10)
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(10);
expect(children._meta.total).to.equal(100);
expect(children._meta.offset).to.equal(0);
done();
});
});
it('Should limit properly (query params, offset)', (done) => {
Child.query()
.where({__offset: 5})
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(95);
expect(children._meta.total).to.equal(100);
expect(children._meta.offset).to.equal(5);
done();
});
});
it('Should limit properly (query params, count)', (done) => {
Child.query()
.where({__count: 10})
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(10);
expect(children._meta.total).to.equal(100);
expect(children._meta.offset).to.equal(0);
done();
});
});
it('Should limit properly (query params, count + offset)', (done) => {
Child.query()
.where({__offset: 5, __count: 10})
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(10);
expect(children._meta.total).to.equal(100);
expect(children._meta.offset).to.equal(5);
done();
});
});
it('Should limit and orderBy properly (ASC)', function(done) {
Child.query()
.limit(10, 10)
.orderBy('id', 'ASC')
.end((err, children) => {
expect(err).to.equal(null);
expect(children).to.be.an.instanceOf(Nodal.ModelArray);
expect(children.length).to.equal(10);
expect(children[0].get('id')).to.equal(11);
done();
});
});
it('Should first properly', function(done) {
Parent.query()
.orderBy('id', 'ASC')
.first((err, parent) => {
expect(err).to.equal(null);
expect(parent).to.exist;
expect(parent.get('id')).to.equal(1);
done();
});
});
it('Should give error on first if nothing found', function(done) {
Parent.query()
.where({name: 'Spongebob'})
.first((err, parent) => {
expect(err).to.exist;
expect(parent).to.not.exist;
done();
});
});
it('Should do an "is" where query properly', (done) => {
Parent.query()
.where({name: 'Zoolander'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(1);
expect(parents[0].get('name')).to.equal('Zoolander');
done();
});
});
it('Should do an "not" where query properly', (done) => {
Parent.query()
.where({name__not: 'Zoolander'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(9);
done();
});
});
it('Should do a "lt" where query properly', (done) => {
Parent.query()
.where({name__lt: 'Zoolander'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(9);
done();
});
});
it('Should do a "lte" where query properly', (done) => {
Parent.query()
.where({name__lte: 'Zoolander'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(10);
done();
});
});
it('Should do a "gt" where query properly', (done) => {
Parent.query()
.where({name__gt: 'Albert'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(9);
done();
});
});
it('Should do a "gte" where query properly', (done) => {
Parent.query()
.where({name__gte: 'Albert'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(10);
done();
});
});
it('Should do a "contains" where query properly', (done) => {
Parent.query()
.where({name__contains: 'am'}) // James, Samantha, Samuel
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(3);
done();
});
});
it('Should do an "icontains" where query properly', (done) => {
Parent.query()
.where({name__icontains: 'z'}) // Suzy, Zoolander
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
done();
});
});
it('Should do an "startswith" where query properly', (done) => {
Parent.query()
.where({name__startswith: 'Sam'}) // Samantha, Samuel
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
done();
});
});
it('Should do an "endswith" where query properly', (done) => {
Parent.query()
.where({name__endswith: 'y'}) // Dingleberry, Sally, Suzy
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(3);
done();
});
});
it('Should do an "iendswith" where query properly', (done) => {
Parent.query()
.where({name__iendswith: 'Y'}) // Dingleberry, Sally, Suzy
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(3);
done();
});
});
it('Should allow for OR queries', (done) => {
Parent.query()
.where({name: 'Zoolander'}, {name: 'Albert'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
done();
});
});
it('Should where by "hidden" field', (done) => {
Parent.query()
.where({hidden: 'a'})
.end((err, parents) => {
expect(parents.length).to.be.lessThan(10);
done();
});
});
it('Should safeWhere and ignore "hidden" field', (done) => {
Parent.query()
.safeWhere({hidden: 'a'})
.end((err, parents) => {
expect(parents.length).to.equal(10);
done();
});
});
it('Should safeWhere and ignore "hidden" field with modifier', (done) => {
Parent.query()
.safeWhere({hidden__not: 'a'})
.end((err, parents) => {
expect(parents.length).to.equal(10);
done();
});
});
it('Should find all children with parent id = "1", by id', (done) => {
Child.query()
.where({parent_id: 1})
.end((err, children) => {
expect(err).to.equal(null);
expect(children.length).to.equal(10);
done();
});
});
it('Should find all children with parent id = "1", by joining', (done) => {
Child.query()
.join('parent')
.where({parent__id: 1})
.end((err, children) => {
expect(err).to.equal(null);
expect(children.length).to.equal(10);
done();
});
});
it('Should find all children with parent name = "Zoolander", by joining', (done) => {
Child.query()
.join('parent')
.where({parent__name: 'Zoolander'})
.end((err, children) => {
expect(err).to.equal(null);
expect(children.length).to.equal(10);
done();
});
});
it('Should find all parents with children id <= 15, by joining', (done) => {
Parent.query()
.join('children')
.where({children__id__lte: 15})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
expect(parents[0].joined('children').length).to.equal(10);
expect(parents[1].joined('children').length).to.equal(10);
done();
});
});
it('Should find all parents with children id <= 15, by joining with restrictions', (done) => {
Parent.query()
.join('children', {id__lte: 15})
.where({children__id__lte: 15})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
expect(parents[0].joined('children').length).to.equal(10);
expect(parents[1].joined('children').length).to.equal(5);
done();
});
});
it('Should find all parents with children id <= 15, by joining with more restrictions', (done) => {
Parent.query()
.join('children', {id__lte: 15, id__gte: 11})
.where({children__id__lte: 15})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
expect(parents[0].joined('children').length).to.equal(0);
expect(parents[1].joined('children').length).to.equal(5);
done();
});
});
it('Should find all parents with children id <= 15, by joining with parent restrictions', (done) => {
Parent.query()
.join('children', {parent__id: 1})
.where({children__id__lte: 15})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
expect(parents[0].joined('children').length).to.equal(10);
expect(parents[1].joined('children').length).to.equal(0);
done();
});
});
it('Should find all parents with children id <= 15, by joining with parent restrictions that joins another field', (done) => {
Parent.query()
.join('children', {parent__children__id__in: [1, 2, 3]})
.where({children__id__lte: 15})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
expect(parents[0].joined('children').length).to.equal(10);
expect(parents[1].joined('children').length).to.equal(0);
done();
});
});
it('Should join children and partners both to parents', (done) => {
Parent.query()
.join('children')
.join('partner')
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(10);
done();
});
});
it('Should join children and partners both to parents, and where each', (done) => {
Parent.query()
.join('children')
.where({children__id__lte: 25})
.join('partner')
.where({partner__name: 'Partner0'}, {partner__name: 'Partner1'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
done();
});
});
it('Should where from both relationships, but keep 10 children per parent', (done) => {
Parent.query()
.join('children')
.where({children__id__lte: 25})
.join('partner')
.where({partner__name: 'Partner0'}, {partner__name: 'Partner1'})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(2);
expect(parents[0].joined('children').length).to.equal(10);
expect(parents[1].joined('children').length).to.equal(10);
done();
});
});
it('Should join children and partners both to parents, and where each, with an additional where of the first join', (done) => {
Parent.query()
.join('children')
.where({children__id__lte: 25})
.join('partner')
.where({partner__name: 'Partner0'}, {partner__name: 'Partner1'})
.where({children__id__gte: 15})
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(1);
done();
});
});
it('Should limit based on the Parent, not joined fields', (done) => {
Parent.query()
.join('children')
.where({children__id__lte: 70})
.limit(5)
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(5);
done();
});
});
it('Should where without joining', (done) => {
Parent.query()
.where({children__id__lte: 70})
.limit(5)
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(5);
done();
});
});
it('Should have Parent join many mutiple fields (Children, Pets) and parse properly', (done) => {
Parent.query()
.join('children')
.join('pets')
.limit(3)
.end((err, parents) => {
expect(err).to.equal(null);
expect(parents.length).to.equal(3);
parents.forEach(parent => {
expect(parent.joined('children').length).to.equal(10);
expect(parent.joined('pets').length).to.equal(3);
});
done();
});
});
it('Should have Parent join Incoming + Outgoing Friendships', (done) => {
Parent.query()
.join('incomingFriendships')
.join('outgoingFriendships')
.orderBy('id', 'ASC')
.end((err, parents) => {
expect(err).to.equal(null);
parents.forEach((parent, i) => {
expect(parent.joined('incomingFriendships').length).to.equal(9 - i);
expect(parent.joined('outgoingFriendships').length).to.equal(i);
});
done();
});
});
it('Should get all Friendships and their Parents', (done) => {
Friendship.query()
.join('fromParent')
.join('toParent')
.end((err, friendships) => {
expect(err).to.equal(null);
expect(friendships.length).to.equal(45);
friendships.forEach((friendship, i) => {
expect(friendship.joined('fromParent')).to.not.be.undefined;
expect(friendship.joined('toParent')).to.not.be.undefined;
});
done();
});
});
it('Should get all Friendships belonging to a parent', (done) => {
Friendship.query()
.join('fromParent')
.join('toParent')
.where({fromParent__id: 5}, {toParent__id: 5})
.end((err, friendships) => {
expect(friendships.length).to.equal(9);
friendships.forEach(friendship => {
expect(
friendship.joined('fromParent').get('id') === 5 ||
friendship.joined('toParent').get('id') === 5
).to.equal(true);
});
done();
});
});
it('Should AND icontains with an Array', (done) => {
// 'Albert',
// 'Derek',
// 'Dingleberry',
// 'James',
// 'Joe',
// 'Sally',
// 'Samantha',
// 'Samuel',
// 'Suzy',
// 'Zoolander'
Parent.query()
.where({name__icontains: ['a', 'e']})
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(4);
expect(parents.map(p => p.get('name'))).to.contain('Albert');
expect(parents.map(p => p.get('name'))).to.contain('James');
expect(parents.map(p => p.get('name'))).to.contain('Samuel');
expect(parents.map(p => p.get('name'))).to.contain('Zoolander');
done();
});
});
it('Should be able to filter multiple join types', (done) => {
Parent.query()
.join('partner', {job: 'Plumber', full_time: true}, {job: 'Nurse', full_time: true})
.join('pets', {name: 'Ruby'})
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(10);
for (let i = 0; i < 10; i++) {
let parent = parents[i];
expect(parent.joined('pets').length).to.equal(1);
expect(parent.joined('pets')[0].get('name')).to.equal('Ruby');
if (parent.joined('partner')) {
expect(['Plumber', 'Nurse']).to.include(parent.joined('partner').get('job'));
expect(parent.joined('partner').get('full_time')).to.equal(true);
}
}
done();
});
});
it('Should get correct pets on an OR join', (done) => {
Parent.query()
.join('pets', {name: 'Ruby'}, {name: 'Oliver'})
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(10);
for (let i = 0; i < parents.length; i++) {
let parent = parents[i];
expect(parent.joined('pets').length).to.equal(2);
}
done();
});
});
it('Should LIMIT properly with an OR join', (done) => {
Parent.query()
.join('pets')
.where({pets__name: 'Ruby'}, {pets__name: 'Oliver'})
.orderBy('created_at', 'DESC')
.limit(0, 5)
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(5);
done();
});
});
it('Should LIMIT properly with an OR join and limit in OR', (done) => {
Parent.query()
.join('pets')
.where({pets__name: 'Ruby', __offset: 0, __count: 5}, {pets__name: 'Oliver', __offset: 0, __count: 5})
.orderBy('created_at', 'DESC')
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(5);
done();
});
});
it('Should filter a joined model properly', done => {
Child.query()
.join('parent', {name: 'Albert'})
.join('parent__pets')
.join('parent__partner')
.where({id__in: [1, 11, 22]})
.end((err, children) => {
let parentCount = 0;
expect(err).to.not.exist;
expect(children).to.exist;
expect(children.length).to.equal(3);
for (let i = 0; i < children.length; i++) {
let child = children[i];
let parent = child.joined('parent');
parentCount = parentCount + (parent ? 1 : 0);
parent && expect(parent.get('name')).to.equal('Albert');
}
expect(parentCount).to.equal(1);
done();
});
});
it('Should OR numerous nested fields together comprehensively', (done) => {
Parent.query()
.join('children')
.join('pets')
.join('careers')
.where([
{
children__is_favorite: true,
children__license: null,
pets__name: 'Oliver',
pets__alive: true,
name: 'Zoolander',
pets__animal__in: ['Cat']
},
{
children__is_favorite: true,
children__license__not_null: true,
pets__name: 'Oliver',
pets__alive: true,
name: 'Zoolander',
pets__animal__in: ['Cat']
},
{
careers__title: 'Freelancer',
careers__is_active: true,
pets__name: 'Oliver',
pets__alive: true,
name: 'Zoolander',
pets__animal__in: ['Cat']
},
])
.limit(20)
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents.length).to.equal(1);
expect(parents[0].get('name')).to.equal('Zoolander');
done();
});
});
/**
*
* ADDING AND INSERTING RECORDS
* DO NOT DEPEND ON UPSTREAM SET VALUES
*
*/
it('Should update all parents names', (done) => {
Parent.query()
.update({name: 'Dave'}, (err, parents) => {
expect(parents.length).to.equal(10);
parents.forEach(parent => {
expect(parent.get('name')).to.equal('Dave');
});
done();
});
});
it('Should update all childrens ages', (done) => {
Child.query().orderBy('id').end((err, children) => {
let ages = children.map(c => c.get('age'));
Child.query()
.orderBy('id')
.update({age: age => `${age} + 10`}, (err, children) => {
children.forEach((child, i) => {
expect(child.get('age')).to.equal(ages[i] + 10);
});
done();
});
});
});
it('Should update all childrens ages and license', (done) => {
Child.query().orderBy('id').end((err, children) => {
let ages = children.map(c => c.get('age'));
Child.query()
.orderBy('id')
.update({license: 'DL_APPROVED_HOORAY', age: age => `${age} + 10`}, (err, children) => {
children.forEach((child, i) => {
expect(child.get('age')).to.equal(ages[i] + 10);
expect(child.get('license')).to.equal('DL_APPROVED_HOORAY');
});
done();
});
});
});
it('Should update all parents names and join children', (done) => {
Parent.query()
.join('children')
.update({name: 'Bertrand'}, (err, parents) => {
expect(parents.length).to.equal(10);
parents.forEach(parent => {
expect(parent.joined('children').length).to.equal(10);
expect(parent.get('name')).to.equal('Bertrand');
});
done();
});
});
it('Should update all parents names and join children, and order by id DESC', (done) => {
Parent.query()
.join('children')
.orderBy('id', 'DESC')
.update({name: 'Bertrand'}, (err, parents) => {
expect(parents.length).to.equal(10);
parents.forEach((parent, i) => {
expect(parent.joined('children').length).to.equal(10);
expect(parent.get('name')).to.equal('Bertrand');
expect(parent.get('id')).to.equal(10 - i);
});
done();
});
});
it('Should query the readonly and see all parents with their original names', (done) => {
Parent.query(readonlyDb)
.orderBy('name', 'ASC')
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents.length).to.equal(10);
parents.forEach((parent, i) => {
expect(parent.get('name')).to.equal(originalParentNames[i]);
});
done();
});
});
it('Should throw an error when trying to update with a readonly database', (done) => {
Parent.query(readonlyDb)
.update({name: 'Cobb'}, (err, parents) => {
expect(err).to.exist;
done();
});
});
it('Should join children to pets', done => {
Pet.query()
.join('parent__children')
.first((err, pet) => {
expect(err).to.not.exist;
expect(pet).to.exist;
expect(pet.joined('parent').joined('children')).to.exist;
expect(pet.joined('parent').joined('children').length).to.equal(10);
done();
});
});
it('Should join pets to children', done => {
Child.query()
.join('parent__pets')
.first((err, child) => {
expect(err).to.not.exist;
expect(child).to.exist;
expect(child.joined('parent').joined('pets')).to.exist;
expect(child.joined('parent').joined('pets').length).to.equal(3);
done();
});
});
it('Should join parent and children to pets', done => {
Pet.query()
.join('parent')
.join('parent__children')
.first((err, pet) => {
expect(err).to.not.exist;
expect(pet).to.exist;
expect(pet.joined('parent').joined('children')).to.exist;
expect(pet.joined('parent').joined('children').length).to.equal(10);
expect(pet.joined('parent')).to.exist;
done();
});
});
it('Should join parent and children to pets with only lowest join', done => {
Pet.query()
.join('parent__children')
.first((err, pet) => {
expect(err).to.not.exist;
expect(pet).to.exist;
expect(pet.joined('parent').joined('children')).to.exist;
expect(pet.joined('parent').joined('children').length).to.equal(10);
expect(pet.joined('parent')).to.exist;
done();
});
});
it('Should query pet by children', done => {
Pet.query()
.where({parent__children__id__lte: 50})
.end((err, pets) => {
expect(err).to.not.exist;
expect(pets).to.exist;
expect(pets.length).to.equal(15);
done();
});
});
it('Should query pet by parent and by pet value', done => {
Pet.query()
.where({parent__id__gt: 1, created_at__lte: new Date()})
.end((err, pets) => {
expect(err).to.not.exist;
expect(pets).to.exist;
expect(pets.length).to.equal(27);
done();
});
});
it('Should query a pet based on json key existance', (done) => {
Pet.query()
.where({details__jsoncontains: 'language'})
.end((err, pets) => {
expect(err).to.not.exist;
expect(pets.length).to.equal(30);
done();
});
});
it('Should query a pet based on json key value', (done) => {
Pet.query()
.where({details__json: { language: true }})
.end((err, pets) => {
expect(err).to.not.exist;
expect(pets.length).to.equal(10);
done();
});
});
it('Should join multiple properties from a deeply joined property', done => {
Parent.query()
.join('incomingFriendships')
.join('incomingFriendships__fromParent')
.join('incomingFriendships__fromParent__pets')
.join('incomingFriendships__fromParent__children')
.first((err, parent) => {
expect(err).to.not.exist;
expect(parent).to.exist;
expect(parent.joined('incomingFriendships')[0].joined('fromParent').joined('pets')).to.exist;
expect(parent.joined('incomingFriendships')[0].joined('fromParent').joined('children')).to.exist;
done();
});
});
it('Should group by shirt', done => {
Parent.query()
.groupBy('shirt')
.end((err, groups) => {
expect(err).to.not.exist;
expect(groups.length).to.equal(3);
done();
});
});
it('Should group and order by shirt', done => {
Parent.query()
.groupBy('shirt')
.orderBy('shirt', 'ASC')
.end((err, groups) => {
expect(err).to.not.exist;
expect(groups.length).to.equal(3);
expect(groups[0].shirt).to.equal('blue');
done();
});
});
it('Should group by shirt, and get a count alias and another mapping', done => {
Parent.query()
.groupBy('shirt')
.aggregate('count', id => `COUNT(${id})`)
.aggregate('red_or_blue', shirt => `CASE WHEN ${shirt} IN ('red', 'blue') THEN TRUE ELSE FALSE END`)
.orderBy('shirt', 'ASC')
.end((err, groups) => {
expect(err).to.not.exist;
expect(groups.length).to.equal(3);
expect(groups[0].shirt).to.equal('blue');
expect(groups[0].count).to.equal(3);
expect(groups[0].red_or_blue).to.equal(true);
done();
});
});
it('Should group by shirt, and get a count alias, order by transformation', done => {
Parent.query()
.groupBy('shirt')
.aggregate('count', id => `COUNT(${id})`)
.orderBy(id => `COUNT(${id})`, 'DESC')
.end((err, groups) => {
expect(err).to.not.exist;
expect(groups.length).to.equal(3);
expect(groups[0].count).to.equal(4);
done();
});
});
it('Should apply filter, group by shirt, and get a count alias, order by transformation', done => {
Parent.query()
.where({id__gt: 2})
.groupBy('shirt')
.aggregate('count', id => `COUNT(${id})`)
.orderBy(id => `COUNT(${id})`, 'DESC')
.end((err, groups) => {
expect(err).to.not.exist;
expect(groups.length).to.equal(3);
expect(groups[0].count).to.equal(3);
done();
});
});
it('Should apply filter, group by shirt and pantaloons', done => {
Parent.query()
.groupBy('shirt')
.groupBy('pantaloons')
.aggregate('count', id => `COUNT(${id})`)
.orderBy(id => `COUNT(${id})`, 'DESC')
.end((err, groups) => {
expect(err).to.not.exist;
expect(groups.length).to.equal(6);
expect(groups[0]).to.haveOwnProperty('shirt');
expect(groups[0]).to.haveOwnProperty('pantaloons');
expect(groups[0]).to.haveOwnProperty('count');
done();
});
});
it('Should not fetch parents if they don\'t exist', done => {
Child.create({name: 'Ada'}, (err, child) => {
Child.query()
.join('parent')
.where({name: 'Ada'})
.first((err, child) => {
expect(err).to.not.exist;
expect(child).to.exist;
expect(child.joined('parent')).to.not.exist;
done();
});
});
});
it('Should AND nested subfields together from tables', (done) => {
Parent.query()
.join('pets')
.where({pets__name: 'Ruby', pets__animal: 'Cat'})
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(0);
done();
});
});
it('Should add nested subfield correctly', (done) => {
Parent.query()
.join('partner')
.where({shirt: 'red', partner__job: 'Plumber'})
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(1);
expect(parents[0].get('id')).to.equal(1);
done();
});
});
it('Should AND nested subfields together from tables', (done) => {
Parent.query()
.join('pets')
.where({pets__name: 'Ruby', pets__animal: 'Cat'})
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(0);
done();
});
});
it('Should join two models adequately', done => {
Parent.query()
.join('children')
.join('partner')
.join('pets')
.end((err, parents) => {
expect(err).to.not.exist;
expect(parents).to.exist;
expect(parents.length).to.equal(10);
done();
});
});
it('Should start a transaction, insert a child, then select for that child', done => {
Child.transaction((err, txn) => {
Child.create({name: 'Alec'}, (err, child) => {
Child.query()
.transact(txn)
.where({id: child.get('id')})
.first((err, child) => {
txn.commit(() => {
expect(err).to.not.exist;
expect(child).to.exist;
expect(child.get('name')).to.equal('Alec');
done();
});
});
}, txn);
});
});
// IMPORTANT: Do npt place any tests after the `Should do a destroy cascade`
// test since all models will be gone
it('Should do a destroy cascade', (done) => {
Parent.query()
.end((err, parents) => {
parents.destroyCascade(err => {
expect(err).to.not.exist;
done();
});
})
});
});
};