TOC
Associations
Model
A One referenced model has the correct foreign key.
expect(Address._core).to.have.property('user_id');
done();
A Many referenced model has the correct foreign key.
expect(Photo._core).to.have.property('user_id');
done();
A Many to many referenced model should exists and have a both foreign keys.
var UserLanguage = ziti.get('UserLanguage');
expect(UserLanguage).to.be.ok;
expect(UserLanguage._core).to.have.property('user_id');
expect(UserLanguage._core).to.have.property('language_id');
done();
A Foreign key is properly defined.
expect(Phone._core).to.have.property('user_id');
expect(Phone._core.user_id._primaryKey).to.be.false;
expect(Phone._core.user_id._autoIncrement).to.be.false;
expect(Phone._core.user_id._typeName).to.equals(User._core.id._typeName);
done();
#save()
should insert multiple Model sources.
User.save([
{
firstname: 'dexter',
lastname: 'morgan',
nickname: 'butcher',
age: 35
},
{
firstname: 'walter',
lastname: 'white',
nickname: 'heisenberg',
age: 50
},
{
firstname: 'franck',
lastname: 'underwood',
nickname: 'francis',
age: 50
},
]).then(function (users) {
scope.users = [ ];
expect(users).to.be.an('array').and.to.have.length(3);
users.forEach(function (user) {
expect(user).to.be.an.instanceof(ModelInstance);
var raw = user.raw();
scope.users.push(raw);
});
}).finally(done).catch(done);
should insert One to One Model targets.
Address.save([
{
street: 'jump street',
number: 22,
user_id: scope.users[0].id
},
{
street: 'lombard street',
number: 42,
user_id: scope.users[1].id
},
{
street: 'champs elysees',
number: 42,
user_id: scope.users[2].id
},
]).then(function (addresses) {
scope.addr = [ ];
addresses.forEach(function (address) {
scope.addr.push(address.raw());
});
}).finally(done).catch(done);
should insert One to Many Model targets.
Photo.save([
{ path: 'am.jpg', user_id: scope.users[0].id },
{ path: 'stram.png', user_id: scope.users[0].id },
{ path: 'gram.jpg', user_id: scope.users[0].id },
{ path: 'hello.jpg', user_id: scope.users[1].id },
{ path: 'world.jpg', user_id: scope.users[1].id },
{ path: 'foo.jpg', user_id: scope.users[2].id },
{ path: 'bar.png', user_id: scope.users[2].id },
{ path: 'pipo.png', user_id: scope.users[2].id },
{ path: 'bimbo.jpg', user_id: scope.users[2].id }
]).then(function (photos) {
scope.photos = [ ];
photos.forEach(function (p) {
scope.photos.push(p.raw());
});
}).finally(done).catch(done);
should insert Many to Many Model targets.
var UserLanguage = ziti.get('UserLanguage');
Language.save([
{ name: 'english' },
{ name: 'french' },
{ name: 'portuguesh' },
{ name: 'italian' },
{ name: 'spanish' },
{ name: 'arabic' }
]).then(function(langs) {
scope.langs = langs;
var ul = [ ];
for (var i = 0, len = scope.users.length; i < len; ++i) {
for (var j = 0, jlen = langs.length; j < jlen; ++j) {
if ((i + j) % 3 === 2) { continue; }
ul.push({ user_id: scope.users[i].id, language_id: langs[j].get('id') });
}
}
return UserLanguage.save(ul);
}).then(function (ul) {
scope.userlangs = ul;
}).finally(done).catch(done);
should insert ForeignKey Model targets.
expect(Friend._pk).to.eql([ 'user_id', 'target_id' ]);
Friend.save([
{ user_id: scope.users[0].id, target_id: scope.users[1].id },
{ user_id: scope.users[1].id, target_id: scope.users[0].id },
{ user_id: scope.users[0].id, target_id: scope.users[2].id },
{ user_id: scope.users[2].id, target_id: scope.users[0].id },
]).then(function (friends) {
expect(friends).to.be.an('array').and.to.have.length(4);
}).finally(done).catch(done);
should insert ForeignKey Model targets (2nd form).
expect(Friend._pk).to.eql([ 'user_id', 'target_id' ]);
Friend.save([
{ user: scope.users[1], target: scope.users[2] },
{ user: scope.users[2], target: scope.users[1] },
]).then(function (friends) {
expect(friends).to.be.an('array').and.to.have.length(2);
return Friend.at({ user_id: scope.users[1].id, target_id: scope.users[2].id });
}).then(function (friend) {
expect(friend).not.to.be.null;
}).finally(done).catch(done);
#at()
should find the source and all its associations as a Model instance.
User.at({ id: scope.users[0].id })
.then(function (user) {
expect(user).to.be.an.instanceof(ModelInstance);
var raw = user.raw();
expect(raw).to.have.property('firstname', 'dexter');
expect(raw).to.have.property('address');
expect(raw.address.street).to.equals('jump street');
expect(raw).to.have.property('photos');
expect(raw.photos[0].path).to.equals('am.jpg');
expect(raw).to.have.property('langs');
expect(raw.langs[0].name).to.equals('english');
expect(raw.friends).to.be.an('array').and.to.have.length(2);
expect(raw.friends[0]).to.have.property('nickname');
expect(raw.friends[1]).to.have.property('nickname');
}).finally(done).catch(done);
should find the source and all its associations as raw data.
User.at({ id: scope.users[0].id }).raw()
.then(function (user) {
expect(user).to.have.property('firstname', 'dexter');
expect(user).to.have.property('address');
expect(user.address.street).to.equals('jump street');
expect(user).to.have.property('photos');
expect(user.photos[0].path).to.equals('am.jpg');
expect(user).to.have.property('langs');
expect(user.langs[0].name).to.equals('english');
}).finally(done).catch(done);
should find the source by pk and some of its associations filtered.
User.at({
id: scope.users[0].id,
photos: { path: { $like: '%.png' } },
langs: { name: 'french' }
}).then(function (user) {
expect(user).to.be.an.instanceof(ModelInstance);
var raw = user.raw();
expect(raw).to.have.property('firstname', 'dexter');
expect(raw).to.have.property('address');
expect(raw.address.street).to.equals('jump street');
expect(raw).to.have.property('photos');
expect(raw.photos).to.be.an('array').and.to.have.length(1);
expect(raw.photos[0].path).to.equals('stram.png');
expect(raw).to.have.property('langs');
expect(raw.langs).to.be.an('array').and.to.have.length(1);
expect(raw.langs[0].name).to.equals('french');
expect(raw.friends).to.be.an('array').and.to.have.length(2);
expect(raw.friends[0]).to.have.property('nickname');
expect(raw.friends[1]).to.have.property('nickname');
}).finally(done).catch(done);
#all
should find multiple sources and all their associations as Model instances.
User.all()
.then(function (users) {
expect(users).to.be.an('array').and.to.have.length(3);
expect(users[0]).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(users[1]).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(users[2]).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(users[0].get('address')).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(users[1].get('address')).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(users[2].get('address')).to.be.ok.and.to.be.an.instanceof(ModelInstance);
}).finally(done).catch(done);
should find multiple sources and all their associations as raw data.
User.all().raw().asc('id')
.then(function (users) {
expect(users).to.be.an('array').and.to.have.length(3);
expect(users[0]).to.be.ok.and.to.be.an('object');
expect(users[1]).to.be.ok.and.to.be.an('object');
expect(users[2]).to.be.ok.and.to.be.an('object');
expect(users[0].address).to.be.ok.and.to.be.an('object');
expect(users[1].address).to.be.ok.and.to.be.an('object');
expect(users[2].address).to.be.ok.and.to.be.an('object');
expect(users[0].photos).to.be.ok.and.to.be.an('array');
expect(users[1].photos).to.be.ok.and.to.be.an('array');
expect(users[2].photos).to.be.ok.and.to.be.an('array');
}).finally(done).catch(done);
should set unique associations to null.
Phone.save({ number: 12345678, user: scope.users[0] })
.then(function () {
return User.all().raw().asc('id');
}).then(function (users) {
expect(users[0].phone).to.be.ok.and.to.be.an('object');
expect(users[0].phone.number).to.equals(12345678);
expect(users[1].phone).to.be.null;
expect(users[2].phone).to.be.null;
}).finally(done).catch(done);
should set multiple associations to empty array.
Photo.remove()
.then(function () {
return Photo.save({ path: 'am.jpg', user_id: scope.users[0].id });
}).then(function () {
return User.all().raw().asc('id');
}).then(function (users) {
expect(users[0].photos).to.be.an('array').and.to.have.length(1);
expect(users[0].photos[0].path).to.equals('am.jpg');
expect(users[1].photos).to.be.an('array').and.to.have.length(0);
expect(users[2].photos).to.be.an('array').and.to.have.length(0);
}).finally(done).catch(done);
Functions
Increment
should increment a column.
Pasta.update({ numero: ziti.$inc('numero', 2) }, { name: 'penne' })
.then(function (res) {
return Pasta.at({ name: 'penne' });
}).then(function (pasta) {
expect(pasta.get('numero')).to.equals(2);
}).finally(done).catch(done);
should increment a column (2nd form).
Pasta.update({ numero: ziti.$inc }, { name: 'penne' })
.then(function (res) {
return Pasta.at({ name: 'penne' });
}).then(function (pasta) {
expect(pasta.get('numero')).to.equals(3);
}).finally(done).catch(done);
should increment a column (3rd form).
Pasta.update({ numero: [ '?? + ?', 'numero', 1 ] }, { name: 'penne' })
.then(function (res) {
return Pasta.at({ name: 'penne' });
}).then(function (pasta) {
expect(pasta.get('numero')).to.equals(4);
}).finally(done).catch(done);
Decrement
should decrement a column.
Pasta.update({ numero: ziti.$dec('numero') }, { name: 'spaghetti' })
.then(function (res) {
return Pasta.at({ name: 'spaghetti' });
}).then(function (pasta) {
expect(pasta.get('numero')).to.equals(4);
}).finally(done).catch(done);
should decrement a column (2nd form).
Pasta.update({ numero: ziti.$dec }, { name: 'spaghetti' })
.then(function (res) {
return Pasta.at({ name: 'spaghetti' });
}).then(function (pasta) {
expect(pasta.get('numero')).to.equals(3);
}).finally(done).catch(done);
should decrement a column (3rd form).
Pasta.update({ numero: [ '?? - ?', 'numero', 1 ] }, { name: 'spaghetti' })
.then(function (res) {
return Pasta.at({ name: 'spaghetti' });
}).then(function (pasta) {
expect(pasta.get('numero')).to.equals(2);
}).finally(done).catch(done);
Function with 1 argument
should set a column to uppercase.
Pasta.update({ name: ziti.$upper }, { numero: 7 })
.then(function (res) {
return Pasta.at({ numero: 7 });
}).then(function (pasta) {
expect(pasta.get('name')).to.equals('SPAGHETTONI');
}).finally(done).catch(done);
should set a column to the hexadecimal representation of another column.
Pasta.update({ name: ziti.$hex('numero') }, { numero: 42 })
.then(function (res) {
return Pasta.at({ numero: 42 });
}).then(function (pasta) {
expect(pasta.get('name')).to.equals('2A');
}).finally(done).catch(done);
Function chaining
should increment by 3 and decrement by 1.
Pasta.update({ numero: ziti.$inc(ziti.$dec('numero', 1), 3) }, { numero: 42 })
.then(function () {
return Pasta.at({ numero: 44 });
}).then(function (pasta) {
expect(pasta).not.to.be.null;
}).finally(done).catch(done);
should sets a column to uppercase and trim spaces.
Pasta.update({ name: ziti.$trim(ziti.$upper('name')) }, { numero: 51 })
.then(function () {
return Pasta.at({ numero: 51 });
}).then(function (pasta) {
expect(pasta.get('name')).to.equals('PASTISI');
}).finally(done).catch(done);
Instance
#set()
should check instance fields are correctly set at build.
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.getValue('price')).to.equals(10);
done();
should set a field.
torti.set('price', 12);
expect(torti.getValue('price')).to.equals(12);
done();
should set a field using a setter.
torti.set('name', 'penne');
expect(torti.getValue('name')).to.equals('PENNE');
done();
#get()
should check instance fields are correctly set at build.
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('price')).to.equals(10);
done();
should set & get a field.
torti.setValue('price', 12);
expect(torti.get('price')).to.equals(12);
done();
should get a field using a getter.
expect(torti.get('name')).to.equals('TORTI:12');
done();
#raw()
should get instance raw data.
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.raw()).to.deep.equals({ price: 10, name: 'TORTI' });
done();
#toJSON()
should get instance JSON representation.
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.toJSON()).to.equals('{"price":10,"name":"TORTI"}');
done();
#save()
should build and insert an instance into database.
var torti = Product.build({ price: 10, name: 'torti', origin: productCountry });
expect(torti.get('origin_id')).to.be.above(0);
torti.save().then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('id')).to.be.above(0);
expect(torti.get('price')).to.equals(10);
expect(torti.get('name')).to.equals('TORTI:10');
expect(torti.get('origin_id')).to.be.above(0);
}).finally(done).catch(done);
should retrieve an instance and save should have no effect.
Product.at({ price: 10 }).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('id')).to.be.above(0);
expect(torti.get('price')).to.equals(10);
expect(torti.get('name')).to.equals('TORTI:10');
return torti.save();
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
}).finally(done).catch(done);
should retrieve an instance, set a field and update database.
Product.at({ price: 10 }).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('id')).to.be.above(0);
expect(torti.get('price')).to.equals(10);
expect(torti.get('name')).to.equals('TORTI:10');
torti.set('price', torti.get('price') + 1);
return torti.save();
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('price')).to.equals(11);
return Product.at({ price: 11 });
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('price')).to.equals(11);
}).finally(done).catch(done);
#update()
should update a field into database.
Product.at({ price: 11 }).then(function (torti) {
return torti.update({ price: 12 })
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('price')).to.equals(12);
return Product.at({ price: 12 })
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('price')).to.equals(12);
}).finally(done).catch(done);
#remove()
should remove an instance from database.
Product.at({ price: 12 }).then(function (torti) {
return torti.remove();
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti._isNew).to.be.true;
return Product.at({ price: 12 });
}).then(function (torti) {
expect(torti).to.be.null;
}).finally(done).catch(done);
#refresh()
should set a field and refresh the instance data.
Product.save({ price: 10, name: 'torti', origin_id: productCountry.get('id') }).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
torti.set({ price: 11 });
return torti.refresh();
}).then(function (torti) {
expect(torti).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(torti.get('price')).to.equals(10);
}).finally(done).catch(done);
Model & model instance methods
Global methods
should use an internal Model property.
expect(Animal.has('kind')).to.be.true;
expect(Animal.has('weight')).to.be.false;
done();
should use an internal Model instance property.
Animal.at({ name: 'po' }).then(function (animal) {
expect(animal.isNew()).to.be.false;
var bugsbunny = Animal.build({ name: 'bugsbunny', kind: 'rabbit' });
expect(bugsbunny.isNew()).to.be.true;
}).finally(done).catch(done);
Model static methods
should return an internal property.
expect(Animal.myTable()).to.equals('animal');
done();
should use an internal method.
Animal.find({ name: 'abu' }).then(function (animal) {
expect(animal.get('kind')).to.equals('monkey');
}).finally(done).catch(done);
Model instance methods
should return an internal property.
Animal.at({ name: 'po' }).then(function (animal) {
expect(animal.myModelName()).to.equals('Animal');
}).finally(done).catch(done);
should use an internal method.
Animal.at({ name: 'abu' }).then(function (animal) {
animal.incAge();
expect(animal.get('age')).to.equals(11);
}).finally(done).catch(done);
Model
Structure
should check the primary key.
var keynames = scope.userStructure;
expect(keynames.PRIMARY).to.be.an('array').and.to.have.length(1);
expect(keynames.PRIMARY[0].Column_name).to.equals('id');
done();
should check a unique key with one field.
var keynames = scope.userStructure;
expect(keynames.nickname).to.be.an('array').and.to.have.length(1);
expect(keynames.nickname[0].Column_name).to.equals('nickname');
done();
should check a unique key with two fields.
var keynames = scope.userStructure;
expect(keynames.uq_name).to.be.an('array').and.to.have.length(2);
expect(keynames.uq_name[0].Column_name).to.equals('firstname');
expect(keynames.uq_name[1].Column_name).to.equals('lastname');
done();
#table
should get the model table name.
expect(Book.table).to.equals('book');
done();
#name
should get the model name.
expect(Animal.name).to.equals('Animal');
done();
#save()
should insert one Model data.
Animal.save({
kind: 'bear',
name: 'winnie',
age: 5
}).then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw.kind).to.equals('bear');
expect(raw.name).to.equals('winnie');
expect(raw.age).to.equals(5);
scope.animal = raw;
done();
}).catch(done);
should insert one Model data with multiple primary keys.
Book.save({ title: 'Les fourmis', author: 'Bernard Werber', year: 1991 })
.then(function (book) {
return book.remove();
}).finally(done).catch(done);
should insert one Model with a field default function.
Book.save({ title: 'Les fourmis', author: 'Bernard Werber' })
.then(function (book) {
var curYear = new Date().getFullYear();
expect(book.get('year')).to.equals(curYear);
return book.remove();
}).finally(done).catch(done);
should insert multiple Model data at once.
Animal.save([
{ kind: 'lion', name: 'simba' },
{ kind: 'lion', name: 'mufasa' },
{ kind: 'meerkat', name: 'timon' },
{ kind: 'warthog', name: 'pumba' },
{ kind: 'bird', name: 'zazu' },
{ kind: 'baboon', name: 'rafiki' },
{ kind: 'hyena', name: 'shenzi' },
{ kind: 'hyena', name: 'banzai' },
{ kind: 'hyena', name: 'ed' },
]).then(function (animals) {
scope.animals = [ ];
expect(animals).to.be.an('array').and.to.have.length(9);
animals.forEach(function (animal) {
expect(animal).to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw).to.have.property('kind');
expect(raw).to.have.property('name');
expect(raw).to.have.property('age');
scope.animals.push(raw);
});
done();
}).catch(done);
should successfully insert multiple Model data using a transaction.
Animal.save([
{ kind: 'Yellow Tang', name: 'Bubbles' },
{ kind: 'Starfish', name: 'Peach' },
{ kind: 'Octopus', name: 'Pearl' },
{ kind: 'Hippocampus', name: 'Sheldon' },
{ kind: 'Clownfish', name: 'Nemo' },
{ kind: 'Regal Blue Tang', name: 'Dory' },
{ kind: 'Shark', name: 'Bruce' },
], { multiple: true }).then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(7);
animals.forEach(function (animal) {
expect(animal).to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw).to.have.property('kind');
expect(raw).to.have.property('name');
expect(raw).to.have.property('age');
});
done();
}).catch(done);
should fail to insert multiple Model data using a transaction and rollback.
Animal.save([
{ kind: 'Shrimp', name: 'Jacques' },
{ kind: 'Shark', name: 'Chum' },
{ kind: 'Clownfish', name: 'Nemo' },
{ kind: 'Regal Blue Tang', name: 'Dory' },
{ kind: 'Shark', name: 'Bruce' },
], { multiple: true }).then(function (animals) {
done(new Error());
}).catch(function (err) {
done();
});
should insert two Model data using the same connection.
ziti.withConnection(function (co) {
Animal.save({ kind: 'rabbit', name: 'bugs bunny' }, { using: co })
.then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw.kind).to.equals('rabbit');
expect(raw.name).to.equals('bugs bunny');
expect(raw.age).to.equals(0);
return Animal.save({ kind: 'duck', name: 'daffy' }, { using: co });
}).then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw.kind).to.equals('duck');
expect(raw.name).to.equals('daffy');
expect(raw.age).to.equals(0);
}).finally(done);
}).catch(done);
#remove()
should remove multiple data.
Animal.remove({ kind: 'hyena' }).limit(2)
.then(function (res) {
expect(res).to.have.property('affectedRows', 2);
done();
}).catch(done);
should remove multiple data (2nd form).
Animal.remove({ kind: 'hyena' })
.then(function (res) {
expect(res).to.have.property('affectedRows', 1);
done();
}).catch(done);
#at()
should find a piece of data using one of its unique field and get a Model instance.
Animal.at({ name: scope.animal.name })
.then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(animal.get('name')).to.equals(scope.animal.name);
expect(animal.get('id')).to.equals(scope.animal.id);
done();
}).catch(done);
should find a piece of data using one of its unique field and get an object.
Animal.at({ name: scope.animal.name }).raw()
.then(function (animal) {
expect(animal).to.be.ok.and.to.be.an('object');
expect(animal.name).to.equals(scope.animal.name);
expect(animal.id).to.equals(scope.animal.id);
done();
}).catch(done);
should not find any data.
Animal.at({ name: 'alexandre' })
.then(function (animal) {
expect(animal).to.be.a('null');
done();
}).catch(done);
should find a piece of data using a unique field and a custom connection.
ziti.withConnection(function (co) {
Animal.at({ name: scope.animal.name }, { using: co })
.then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(animal.get('name')).to.equals(scope.animal.name);
expect(animal.get('id')).to.equals(scope.animal.id);
}).finally(done);
}).catch(done);
should retrieve all default attributes but one.
Animal.at({ name: scope.animal.name }).without('name')
.then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(animal.get('id')).to.equals(scope.animal.id);
expect(animal.get('name')).to.equals('');
done();
}).catch(done);
should retrieve a subset of attributes + 1.
Animal.at({ name: scope.animal.name }).only('id').with('name')
.then(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
expect(animal.get('id')).to.equals(scope.animal.id);
expect(animal.get('name')).to.equals('winnie');
expect(animal.get('age')).to.equals(0);
expect(animal.get('kind')).to.be.undefined;
done();
}).catch(done);
#all()
should find multiple data and get an array of Model instances.
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] })
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(3);
animals.forEach(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw).to.have.property('kind');
expect(raw).to.have.property('name');
expect(raw).to.have.property('age');
});
done();
}).catch(done);
should find multiple data and get an array of raw data.
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] }).raw()
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(3);
animals.forEach(function (animal) {
expect(animal).to.be.ok.and.to.be.an('object');
expect(animal).to.have.property('kind');
expect(animal).to.have.property('name');
expect(animal).to.have.property('age');
});
done();
}).catch(done);
should find multiple data with a limit.
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] }).limit(2)
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(2);
animals.forEach(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw).to.have.property('kind');
expect(raw).to.have.property('name');
expect(raw).to.have.property('age');
});
done();
}).catch(done);
should find multiple data with a subset of attributes.
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] },
{ attributes: [ 'id', 'name' ] })
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(3);
animals.forEach(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw).to.not.have.property('kind');
expect(raw).to.have.property('name');
expect(raw).to.have.property('age');
});
done();
}).catch(done);
should find multiple data with a subset of attributes (2nd form).
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] }).only('id', 'name')
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(3);
animals.forEach(function (animal) {
expect(animal).to.be.ok.and.to.be.an.instanceof(ModelInstance);
var raw = animal.raw();
expect(raw).to.not.have.property('kind');
expect(raw).to.have.property('name');
expect(raw).to.have.property('age');
});
done();
}).catch(done);
should find multiple data ordered by id desc.
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] })
.only('id', 'name')
.limit(3)
.desc('id')
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(3);
expect(animals[0].get('id')).to.be.above(animals[1].get('id'))
expect(animals[1].get('id')).to.be.above(animals[2].get('id'))
done();
}).catch(done);
should find multiple data ordered by id asc.
Animal.all({ $or: [ { kind: 'lion' }, { kind: 'shark' } ] })
.only('id', 'name')
.limit(3)
.asc('id')
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(3);
expect(animals[0].get('id')).to.be.below(animals[1].get('id'))
expect(animals[1].get('id')).to.be.below(animals[2].get('id'))
done();
}).catch(done);
should find multiple data grouped by column.
Animal.all().only('id', 'name', 'kind')
.group('kind')
.limit(5)
.asc('id')
.raw()
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(5);
// check the uniqueness of the `kind` attribute
var groups = _.groupBy(animals, 'kind');
_.forOwn(groups, function (group) {
expect(group).to.be.an('array').and.to.have.length(1);
});
done();
}).catch(done);
should not find any data.
Animal.all({ kind: 'spider' })
.then(function (animals) {
expect(animals).to.be.an('array').and.to.have.length(0);
done();
}).catch(done);
#upsert()
should insert one Model data with two primary keys.
Book.upsert({
title: 'La nuit des enfants rois',
author: 'Bernard Lenteric',
year: 1942
}).then(function (res) {
expect(res).to.have.property('affectedRows', 1);
}).finally(done).catch(done);
should update one Model data with two primary keys.
Book.upsert({
title: 'La nuit des enfants rois',
author: 'Bernard Lenteric',
year: 1981
}).then(function (res) {
expect(res).to.have.property('affectedRows', 2);
return Book.all();
}).then(function (books) {
expect(books).to.be.an('array').and.to.have.length(1);
expect(books[0].get('year')).to.equals(1981);
}).finally(done).catch(done);
#sum(), #min(), #max(), #count()
should get the sum of a column.
Pasta.sum('numero').then(function (res) {
expect(res).to.equals(16);
}).finally(done).catch(done);
should get the min of a column.
Pasta.min('numero').then(function (res) {
expect(res).to.equals(0);
}).finally(done).catch(done);
should get the max of a column.
Pasta.max('numero').then(function (res) {
expect(res).to.equals(7);
}).finally(done).catch(done);
should get the number of rows.
Pasta.count().then(function (res) {
expect(res).to.equals(6);
}).finally(done).catch(done);
Queries
Raw queries
should do a simple query using ziti.
ziti.query('SELECT `kind`, `name` FROM `animal`')
.spread(function(result) {
expect(result).to.be.an('array').and.to.have.length(2);
expect(result[0]).to.have.property('kind');
expect(result[0]).to.have.property('name');
expect(result[1]).to.have.property('kind');
expect(result[1]).to.have.property('name');
}).finally(done).catch(done);
should do a query with escaped values using ziti.
ziti.query({ sql: 'SELECT ?? FROM ?? WHERE ?? > ?',
values: [ [ 'kind', 'name' ], 'animal', 'age', 10 ] })
.spread(function (result) {
expect(result).to.be.an('array').and.to.have.length(1);
expect(result[0]).to.have.property('kind');
expect(result[0]).to.have.property('name');
}).finally(done).catch(done);
should do a query with escaped values using ziti (2nd form).
ziti.query([ 'SELECT ?? FROM ?? WHERE ?? > ?', [ 'kind', 'name' ],
'animal', 'age', 10 ])
.spread(function (result) {
expect(result).to.be.an('array').and.to.have.length(1);
expect(result[0]).to.have.property('kind');
expect(result[0]).to.have.property('name');
}).finally(done).catch(done);
should do a select using Model.
Animal.query('SELECT `kind`, `name` FROM `animal`')
.spread(function(result) {
expect(result).to.be.an('array').and.to.have.length(2);
expect(result[0]).to.have.property('kind');
expect(result[0]).to.have.property('name');
expect(result[1]).to.have.property('kind');
expect(result[1]).to.have.property('name');
}).finally(done).catch(done);
should do a query with escaped values using Model.
Animal.query({ sql: 'SELECT ?? FROM ?? WHERE ?? > ?',
values: [ [ 'kind', 'name' ], Animal.table, 'age', 10 ] })
.spread(function (result) {
expect(result).to.be.an('array').and.to.have.length(1);
expect(result[0]).to.have.property('kind');
expect(result[0]).to.have.property('name');
}).finally(done).catch(done);
should do a query with escaped values using Model (2nd form).
Animal.query([ 'SELECT ?? FROM ?? WHERE ?? > ?', [ 'kind', 'name' ],
Animal.table, 'age', 10 ])
.spread(function (result) {
expect(result).to.be.an('array').and.to.have.length(1);
expect(result[0]).to.have.property('kind');
expect(result[0]).to.have.property('name');
}).finally(done).catch(done);
Expressions
should build the expression: a = b.
var expr = Utils.parseExpr('foo', { id: 1 });
expect(expr.sql).to.equals('`foo`.?? = ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a = b AND c = d.
var expr = Utils.parseExpr('foo', { id: 1, name: 'bar' });
expect(expr.sql).to.equals('`foo`.?? = ? AND `foo`.?? = ?');
expect(expr.values).to.eql([ 'id', 1, 'name', 'bar' ]);
done();
should build the expression: a = b AND c = d (2nd form).
var expr = Utils.parseExpr('foo', { $and: [ { id: 1 }, { name: 'bar' } ] });
expect(expr.sql).to.equals('(`foo`.?? = ? AND `foo`.?? = ?)');
expect(expr.values).to.eql([ 'id', 1, 'name', 'bar' ]);
done();
should build the expression: a = b OR c = d.
var expr = Utils.parseExpr('foo', { $or: [ { id: 1 }, { name: 'bar' } ] });
expect(expr.sql).to.equals('(`foo`.?? = ? OR `foo`.?? = ?)');
expect(expr.values).to.eql([ 'id', 1, 'name', 'bar' ]);
done();
should build the expression: (a = b AND c = d) OR (e = f).
var expr = Utils.parseExpr('foo', {
$or: [ { $and: [ { id: 1 }, { name: 'bar' } ] }, { name: 'foo' } ]
});
expect(expr.sql).to.equals('((`foo`.?? = ? AND `foo`.?? = ?) OR `foo`.?? = ?)');
expect(expr.values).to.eql([ 'id', 1, 'name', 'bar', 'name', 'foo' ]);
done();
should build the expression: (a = b AND c = d) OR (e = f).
var expr = Utils.parseExpr('foo', {
$or: [ { $and: [ { id: 1 }, { name: 'bar' } ] }, { name: 'foo' } ]
});
expect(expr.sql).to.equals('((`foo`.?? = ? AND `foo`.?? = ?) OR `foo`.?? = ?)');
expect(expr.values).to.eql([ 'id', 1, 'name', 'bar', 'name', 'foo' ]);
done();
should build the expression: a = b (2nd form).
var expr = Utils.parseExpr('foo', { id: { $eq: 1 } });
expect(expr.sql).to.equals('`foo`.?? = ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a = b (3rd form).
var expr = Utils.parseExpr('foo', { $eq: { id: 1 } });
expect(expr.sql).to.equals('`foo`.?? = ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a > b.
var expr = Utils.parseExpr('foo', { id: { $gt: 1 } });
expect(expr.sql).to.equals('`foo`.?? > ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a >= b.
var expr = Utils.parseExpr('foo', { id: { $ge: 1 } });
expect(expr.sql).to.equals('`foo`.?? >= ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a < b.
var expr = Utils.parseExpr('foo', { id: { $lt: 1 } });
expect(expr.sql).to.equals('`foo`.?? < ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a <= b.
var expr = Utils.parseExpr('foo', { id: { $le: 1 } });
expect(expr.sql).to.equals('`foo`.?? <= ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a != b.
var expr = Utils.parseExpr('foo', { id: { $ne: 1 } });
expect(expr.sql).to.equals('`foo`.?? != ?');
expect(expr.values).to.eql([ 'id', 1 ]);
done();
should build the expression: a NOT NULL.
var expr = Utils.parseExpr('foo', { id: { $not: null } });
expect(expr.sql).to.equals('`foo`.?? NOT ?');
expect(expr.values).to.eql([ 'id', null ]);
done();
should build the expression: a IS NULL.
var expr = Utils.parseExpr('foo', { id: { $is: null } });
expect(expr.sql).to.equals('`foo`.?? IS ?');
expect(expr.values).to.eql([ 'id', null ]);
done();
should build the expression: a IS NOT NULL.
var expr = Utils.parseExpr('foo', { id: { $nis: null } });
expect(expr.sql).to.equals('`foo`.?? IS NOT ?');
expect(expr.values).to.eql([ 'id', null ]);
done();
should build the expression: a LIKE '%xxx%'.
var expr = Utils.parseExpr('foo', { name: { $like: '%xxx%' } });
expect(expr.sql).to.equals('`foo`.?? LIKE ?');
expect(expr.values).to.eql([ 'name', '%xxx%' ]);
done();
should build the expression: a NOT LIKE '%xxx%'.
var expr = Utils.parseExpr('foo', { name: { $nlike: '%xxx%' } });
expect(expr.sql).to.equals('`foo`.?? NOT LIKE ?');
expect(expr.values).to.eql([ 'name', '%xxx%' ]);
done();
should build the expression: a IN (x, y, z).
var expr = Utils.parseExpr('foo', { id: { $in: [ 1, 2, 3 ] } });
expect(expr.sql).to.equals('`foo`.?? IN (?)');
expect(expr.values).to.eql([ 'id', [ 1, 2, 3 ] ]);
done();
should build the expression: a NOT IN (x, y, z).
var expr = Utils.parseExpr('foo', { id: { $nin: [ 1, 2, 3 ] } });
expect(expr.sql).to.equals('`foo`.?? NOT IN (?)');
expect(expr.values).to.eql([ 'id', [ 1, 2, 3 ] ]);
done();
should build the expression: a REGEXP '^x.*x$'.
var expr = Utils.parseExpr('foo', { name: { $regexp: '^x.*x$' } });
expect(expr.sql).to.equals('`foo`.?? REGEXP ?');
expect(expr.values).to.eql([ 'name', '^x.*x$' ]);
done();
should build a raw expression from an array with parameters.
var expr = Utils.parseExpr('foo', [ '`name` = ??', 'bar' ]);
expect(expr.sql).to.equals('`name` = ??');
expect(expr.values).to.eql([ 'bar' ]);
done();
should build a raw expression from a string.
var expr = Utils.parseExpr('foo', '`name` = \'bar\'');
expect(expr.sql).to.equals('`name` = \'bar\'');
expect(expr.values).to.eql([ ]);
done();