Merge pull request #1310 from strongloop/add-cass-tests

Add test support for Cassandra connector
This commit is contained in:
Tetsuo Seto 2017-04-07 11:26:48 -07:00 committed by GitHub
commit bff4ea7fd5
5 changed files with 939 additions and 519 deletions

View File

@ -7,8 +7,11 @@
'use strict';
/* global getSchema:false, connectorCapabilities:false */
var should = require('./init.js');
var async = require('async');
var bdd = require('./helpers/bdd-if');
var should = require('./init.js');
var uid = require('./helpers/uid-generator');
var db, User;
describe('basic-querying', function() {
@ -54,11 +57,13 @@ describe('basic-querying', function() {
describe('findById', function() {
before(function(done) {
db = getSchema();
User.destroyAll(done);
});
it('should query by id: not found', function(done) {
User.findById(1, function(err, u) {
var unknownId = uid.fromConnector(db) || 1;
User.findById(unknownId, function(err, u) {
should.not.exist(u);
should.not.exist(err);
done();
@ -82,6 +87,7 @@ describe('basic-querying', function() {
describe('findByIds', function() {
var createdUsers;
before(function(done) {
db = getSchema();
var people = [
{name: 'a', vip: true},
{name: 'b'},
@ -168,7 +174,8 @@ describe('basic-querying', function() {
});
});
it('should query collection with skip & limit', function(done) {
bdd.itIf(connectorCapabilities.supportPagination !== false, 'should query collection with skip & ' +
'limit', function(done) {
User.find({skip: 1, limit: 4, order: 'seq'}, function(err, users) {
should.exists(users);
should.not.exists(err);
@ -178,7 +185,8 @@ describe('basic-querying', function() {
});
});
it('should query collection with offset & limit', function(done) {
bdd.itIf(connectorCapabilities.supportPagination !== false, 'should query collection with offset & ' +
'limit', function(done) {
User.find({offset: 2, limit: 3, order: 'seq'}, function(err, users) {
should.exists(users);
should.not.exists(err);
@ -197,7 +205,8 @@ describe('basic-querying', function() {
});
});
it('should query collection sorted by numeric field', function(done) {
bdd.itIf(connectorCapabilities.adhocSort !== false, 'should query collection sorted by numeric ' +
'field', function(done) {
User.find({order: 'order'}, function(err, users) {
should.exists(users);
should.not.exists(err);
@ -208,7 +217,8 @@ describe('basic-querying', function() {
});
});
it('should query collection desc sorted by numeric field', function(done) {
bdd.itIf(connectorCapabilities.adhocSort !== false, 'should query collection desc sorted by ' +
'numeric field', function(done) {
User.find({order: 'order DESC'}, function(err, users) {
should.exists(users);
should.not.exists(err);
@ -219,7 +229,8 @@ describe('basic-querying', function() {
});
});
it('should query collection sorted by string field', function(done) {
bdd.itIf(connectorCapabilities.adhocSort !== false, 'should query collection sorted by string ' +
'field', function(done) {
User.find({order: 'name'}, function(err, users) {
should.exists(users);
should.not.exists(err);
@ -230,7 +241,8 @@ describe('basic-querying', function() {
});
});
it('should query collection desc sorted by string field', function(done) {
bdd.itIf(connectorCapabilities.adhocSort !== false, 'should query collection desc sorted by ' +
'string field', function(done) {
User.find({order: 'name DESC'}, function(err, users) {
should.exists(users);
should.not.exists(err);
@ -241,11 +253,10 @@ describe('basic-querying', function() {
});
});
it('should query sorted desc by order integer field even though there' +
'is an async model loaded hook', function(done) {
bdd.itIf(connectorCapabilities.adhocSort !== false, 'should query sorted desc by order integer field' +
' even though there is an async model loaded hook', function(done) {
User.find({order: 'order DESC'}, function(err, users) {
if (err) return done(err);
should.exists(users);
var order = users.map(function(u) { return u.order; });
order.should.eql([6, 5, 4, 3, 2, 1]);
@ -275,7 +286,8 @@ describe('basic-querying', function() {
});
});
it('should support "or" that is satisfied', function(done) {
bdd.itIf(connectorCapabilities.supportOrOperator !== false, 'should support "or" that is ' +
'satisfied', function(done) {
User.find({where: {or: [
{name: 'John Lennon'},
{role: 'lead'},
@ -286,7 +298,8 @@ describe('basic-querying', function() {
});
});
it('should support "or" operator that is not satisfied', function(done) {
bdd.itIf(connectorCapabilities.supportOrOperator !== false, 'should support "or" operator that is ' +
'not satisfied', function(done) {
User.find({where: {or: [
{name: 'XYZ'},
{role: 'Hello1'},
@ -298,7 +311,7 @@ describe('basic-querying', function() {
});
it('should support date "gte" that is satisfied', function(done) {
User.find({order: 'seq', where: {birthday: {'gte': new Date('1980-12-08')},
User.find({where: {birthday: {'gte': new Date('1980-12-08')},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 1);
@ -308,7 +321,7 @@ describe('basic-querying', function() {
});
it('should support date "gt" that is not satisfied', function(done) {
User.find({order: 'seq', where: {birthday: {'gt': new Date('1980-12-08')},
User.find({where: {birthday: {'gt': new Date('1980-12-08')},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
@ -317,7 +330,7 @@ describe('basic-querying', function() {
});
it('should support date "gt" that is satisfied', function(done) {
User.find({order: 'seq', where: {birthday: {'gt': new Date('1980-12-07')},
User.find({where: {birthday: {'gt': new Date('1980-12-07')},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 1);
@ -327,7 +340,7 @@ describe('basic-querying', function() {
});
it('should support date "lt" that is satisfied', function(done) {
User.find({order: 'seq', where: {birthday: {'lt': new Date('1980-12-07')},
User.find({where: {birthday: {'lt': new Date('1980-12-07')},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 1);
@ -337,17 +350,18 @@ describe('basic-querying', function() {
});
it('should support number "gte" that is satisfied', function(done) {
User.find({order: 'seq', where: {order: {'gte': 3},
}}, function(err, users) {
User.find({where: {order: {'gte': 3}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 4);
users[0].name.should.equal('George Harrison');
users.map(u => u.name).should.containDeep([
'George Harrison', 'Ringo Starr', 'Pete Best', 'Stuart Sutcliffe',
]);
done();
});
});
it('should support number "gt" that is not satisfied', function(done) {
User.find({order: 'seq', where: {order: {'gt': 6},
User.find({where: {order: {'gt': 6},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
@ -356,7 +370,7 @@ describe('basic-querying', function() {
});
it('should support number "gt" that is satisfied', function(done) {
User.find({order: 'seq', where: {order: {'gt': 5},
User.find({where: {order: {'gt': 5},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 1);
@ -366,7 +380,7 @@ describe('basic-querying', function() {
});
it('should support number "lt" that is satisfied', function(done) {
User.find({order: 'seq', where: {order: {'lt': 2},
User.find({where: {order: {'lt': 2},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 1);
@ -375,27 +389,27 @@ describe('basic-querying', function() {
});
});
it('should support number "gt" that is satisfied by null value', function(done) {
User.find({order: 'seq', where: {order: {'gt': null},
}}, function(err, users) {
bdd.itIf(connectorCapabilities.ignoreUndefinedConditionValue !== false, 'should support number "gt" ' +
'that is satisfied by null value', function(done) {
User.find({order: 'seq', where: {order: {'gt': null}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
done();
});
});
it('should support number "lt" that is not satisfied by null value', function(done) {
User.find({order: 'seq', where: {order: {'lt': null},
}}, function(err, users) {
bdd.itIf(connectorCapabilities.ignoreUndefinedConditionValue !== false, 'should support number "lt" ' +
'that is not satisfied by null value', function(done) {
User.find({where: {order: {'lt': null}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
done();
});
});
it('should support string "gte" that is satisfied by null value', function(done) {
User.find({order: 'seq', where: {name: {'gte': null},
}}, function(err, users) {
bdd.itIf(connectorCapabilities.ignoreUndefinedConditionValue !== false, 'should support string "gte" ' +
'that is satisfied by null value', function(done) {
User.find({order: 'seq', where: {name: {'gte': null}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
done();
@ -403,17 +417,18 @@ describe('basic-querying', function() {
});
it('should support string "gte" that is satisfied', function(done) {
User.find({order: 'seq', where: {name: {'gte': 'Paul McCartney'},
}}, function(err, users) {
User.find({where: {name: {'gte': 'Paul McCartney'}}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 4);
users[0].name.should.equal('Paul McCartney');
for (var ix = 0; ix < users.length; ix++) {
users[ix].name.should.be.greaterThanOrEqual('Paul McCartney');
}
done();
});
});
it('should support string "gt" that is not satisfied', function(done) {
User.find({order: 'seq', where: {name: {'gt': 'xyz'},
User.find({where: {name: {'gt': 'xyz'},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
@ -422,37 +437,44 @@ describe('basic-querying', function() {
});
it('should support string "gt" that is satisfied', function(done) {
User.find({order: 'seq', where: {name: {'gt': 'Paul McCartney'},
User.find({where: {name: {'gt': 'Paul McCartney'},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 3);
users[0].name.should.equal('Ringo Starr');
for (var ix = 0; ix < users.length; ix++) {
users[ix].name.should.be.greaterThan('Paul McCartney');
}
done();
});
});
it('should support string "lt" that is satisfied', function(done) {
User.find({order: 'seq', where: {name: {'lt': 'Paul McCartney'},
User.find({where: {name: {'lt': 'Paul McCartney'},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 2);
users[0].name.should.equal('John Lennon');
for (var ix = 0; ix < users.length; ix++) {
users[ix].name.should.be.lessThan('Paul McCartney');
}
done();
});
});
it('should support boolean "gte" that is satisfied', function(done) {
User.find({order: 'seq', where: {vip: {'gte': true},
User.find({where: {vip: {'gte': true},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 3);
users[0].name.should.equal('John Lennon');
for (var ix = 0; ix < users.length; ix++) {
users[ix].name.should.be.oneOf(['John Lennon', 'Stuart Sutcliffe', 'Paul McCartney']);
users[ix].vip.should.be.true();
};
done();
});
});
it('should support boolean "gt" that is not satisfied', function(done) {
User.find({order: 'seq', where: {vip: {'gt': true},
User.find({where: {vip: {'gt': true},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 0);
@ -461,35 +483,41 @@ describe('basic-querying', function() {
});
it('should support boolean "gt" that is satisfied', function(done) {
User.find({order: 'seq', where: {vip: {'gt': false},
User.find({where: {vip: {'gt': false},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 3);
users[0].name.should.equal('John Lennon');
for (var ix = 0; ix < users.length; ix++) {
users[ix].name.should.be.oneOf(['John Lennon', 'Stuart Sutcliffe', 'Paul McCartney']);
users[ix].vip.should.be.true(users[ix].name + ' should be VIP');
}
done();
});
});
it('should support boolean "lt" that is satisfied', function(done) {
User.find({order: 'seq', where: {vip: {'lt': true},
User.find({where: {vip: {'lt': true},
}}, function(err, users) {
should.not.exist(err);
users.should.have.property('length', 2);
users[0].name.should.equal('George Harrison');
for (var ix = 0; ix < users.length; ix++) {
users[ix].name.should.be.oneOf(['Ringo Starr', 'George Harrison']);
users[ix].vip.should.be.false(users[ix].name + ' should not be VIP');
}
done();
});
});
it('supports non-empty inq', function() {
bdd.itIf(connectorCapabilities.supportInq, 'supports non-empty inq', function() {
// note there is no record with seq=100
return User.find({where: {seq: {inq: [0, 1, 100]}}})
.then(result => {
const seqsFound = result.map(r => r.seq);
should(seqsFound).be.oneOf([0, 1], [1, 0]);
should(seqsFound).eql([0, 1]);
});
});
it('supports empty inq', function() {
bdd.itIf(connectorCapabilities.supportInq, 'supports empty inq', function() {
return User.find({where: {seq: {inq: []}}})
.then(result => {
const seqsFound = result.map(r => r.seq);
@ -723,7 +751,7 @@ describe('basic-querying', function() {
});
});
it('should find first record', function(done) {
bdd.itIf(connectorCapabilities.adhocSort, 'should find first record', function(done) {
User.findOne({order: 'order'}, function(e, u) {
should.not.exist(e);
should.exist(u);
@ -733,7 +761,7 @@ describe('basic-querying', function() {
});
});
it('should find last record', function(done) {
bdd.itIf(connectorCapabilities.adhocSort, 'should find last record', function(done) {
User.findOne({order: 'order DESC'}, function(e, u) {
should.not.exist(e);
should.exist(u);
@ -743,7 +771,7 @@ describe('basic-querying', function() {
});
});
it('should find last record in filtered set', function(done) {
bdd.itIf(connectorCapabilities.adhocSort, 'should find last record in filtered set', function(done) {
User.findOne({
where: {role: 'lead'},
order: 'order DESC',
@ -782,8 +810,9 @@ describe('basic-querying', function() {
});
it('should check whether record not exist', function(done) {
var unknownId = uid.fromConnector(db) || 42;
User.destroyAll(function() {
User.exists(42, function(err, exists) {
User.exists(unknownId, function(err, exists) {
should.not.exist(err);
exists.should.not.be.ok;
done();
@ -815,7 +844,7 @@ describe.skip('queries', function() {
var Todo;
before(function prepDb(done) {
var db = getSchema();
db = getSchema();
Todo = db.define('Todo', {
id: false,
content: {type: 'string'},
@ -825,6 +854,7 @@ describe.skip('queries', function() {
db.automigrate(['Todo'], done);
});
beforeEach(function resetFixtures(done) {
db = getSchema();
Todo.destroyAll(function() {
Todo.create([
{content: 'Buy eggs'},

View File

@ -15,8 +15,7 @@ describe('datatypes', function() {
before(function(done) {
db = getSchema();
var Nested = db.define('Nested', {});
Model = db.define('Model', {
var modelTableSchema = {
str: String,
date: Date,
num: Number,
@ -24,7 +23,8 @@ describe('datatypes', function() {
list: {type: [String]},
arr: Array,
nested: Nested,
});
};
Model = db.define('Model', modelTableSchema);
db.automigrate(['Model'], done);
});
@ -136,10 +136,9 @@ describe('datatypes', function() {
function testUpdate(done) {
Model.findById(id, function(err, m) {
should.not.exist(err);
// update using updateAttributes
m.updateAttributes({
id: m.id, num: '10',
id: m.id, num: 10,
}, function(err, m) {
should.not.exist(err);
m.num.should.be.type('number');

View File

@ -19,3 +19,8 @@ exports.last = function() {
exports.reset = function() {
lastId = 0;
};
exports.fromConnector = function(db) {
return (db && db.connector && db.connector.generateUniqueId) ?
db.connector.generateUniqueId() : null;
};

View File

@ -6,13 +6,14 @@
// This test written in mocha+should.js
'use strict';
/* global getSchema:false */
/* global getSchema:false, connectorCapabilities:false */
var async = require('async');
var bdd = require('./helpers/bdd-if');
var should = require('./init.js');
var uid = require('./helpers/uid-generator');
var db, Person;
var ValidationError = require('..').ValidationError;
var bdd = require('./helpers/bdd-if.js');
var UUID_REGEXP = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
@ -82,9 +83,9 @@ describe('manipulation', function() {
it('should create instance', function(done) {
Person.create({name: 'Anatoliy'}, function(err, p) {
p.name.should.equal('Anatoliy');
if (err) return done(err);
should.exist(p);
p.name.should.equal('Anatoliy');
Person.findById(p.id, function(err, person) {
if (err) return done(err);
person.id.should.eql(p.id);
@ -313,7 +314,7 @@ describe('manipulation', function() {
Person.findById(created.id, function(err, found) {
if (err) return done(err);
var result = found.toObject();
result.should.have.properties({
result.should.containEql({
id: created.id,
name: 'a-name',
});
@ -324,7 +325,8 @@ describe('manipulation', function() {
});
});
it('should refuse to create object with duplicate id', function(done) {
bdd.itIf(connectorCapabilities.refuseDuplicateInsert !== false, 'should refuse to create ' +
'object with duplicate id', function(done) {
// NOTE(bajtos) We cannot reuse Person model here,
// `settings.forceId` aborts the CREATE request at the validation step.
var Product = db.define('ProductTest', {name: String}, {forceId: false});
@ -333,7 +335,7 @@ describe('manipulation', function() {
Product.create({name: 'a-name'}, function(err, p) {
if (err) return done(err);
Product.create({id: p.id, name: 'duplicate'}, function(err) {
Product.create({id: p.id, name: 'duplicate'}, function(err, result) {
if (!err) {
return done(new Error('Create should have rejected duplicate id.'));
}
@ -348,6 +350,7 @@ describe('manipulation', function() {
describe('save', function() {
it('should save new object', function(done) {
var p = new Person;
should.not.exist(p.id);
p.save(function(err) {
if (err) return done(err);
should.exist(p.id);
@ -357,6 +360,7 @@ describe('manipulation', function() {
it('should save new object (promise variant)', function(done) {
var p = new Person;
should.not.exist(p.id);
p.save()
.then(function() {
should.exist(p.id);
@ -459,12 +463,15 @@ describe('manipulation', function() {
// "User.hasPassword() should match a password after it is changed"
StubUser.create({password: 'foo'}, function(err, created) {
if (err) return done(err);
created.password.should.equal('foo-FOO');
created.password = 'bar';
created.save(function(err, saved) {
if (err) return done(err);
created.id.should.eql(saved.id);
saved.password.should.equal('bar-BAR');
StubUser.findById(created.id, function(err, found) {
if (err) return done(err);
created.id.should.eql(found.id);
found.password.should.equal('bar-BAR');
done();
});
@ -477,7 +484,8 @@ describe('manipulation', function() {
var person;
before(function(done) {
Person.destroyAll(function() {
Person.destroyAll(function(err) {
if (err) return done(err);
Person.create({name: 'Mary', age: 15}, function(err, p) {
if (err) return done(err);
person = p;
@ -486,11 +494,6 @@ describe('manipulation', function() {
});
});
it('has an alias "patchAttributes"', function(done) {
person.updateAttributes.should.equal(person.patchAttributes);
done();
});
it('should have updated password hashed with updateAttribute',
function(done) {
StubUser.create({password: 'foo'}, function(err, created) {
@ -553,6 +556,7 @@ describe('manipulation', function() {
function(err, p) {
// if uknownVar was defined, it would return validationError
if (err) return done(err);
person.id.should.eql(p.id);
Person.findById(p.id, function(e, p) {
if (e) return done(e);
p.name.should.equal('John');
@ -692,6 +696,11 @@ describe('manipulation', function() {
});
});
it('has an alias "patchAttributes"', function(done) {
person.updateAttributes.should.equal(person.patchAttributes);
done();
});
it('should allow model instance on updateAttributes', function(done) {
person.updateAttributes(new Person({'name': 'John', age: undefined}),
function(err, p) {
@ -775,7 +784,7 @@ describe('manipulation', function() {
should.exist(data);
should.exist(data.id);
data.id.should.equal(todo.id);
data.id.should.eql(todo.id);
should.exist(data.content);
data.content.should.equal('b');
@ -827,22 +836,20 @@ describe('manipulation', function() {
{name: 'a-name', gender: undefined},
function(err, instance) {
if (err) return done(err);
instance.toObject().should.have.properties({
id: instance.id,
name: 'a-name',
gender: undefined,
});
var result = instance.toObject();
result.id.should.eql(instance.id);
should.equal(result.name, 'a-name');
should.equal(result.gender, undefined);
Person.updateOrCreate(
{id: instance.id, name: 'updated name'},
function(err, updated) {
if (err) return done(err);
var result = updated.toObject();
result.should.have.properties({
id: instance.id,
name: 'updated name',
});
result.id.should.eql(instance.id);
should.equal(result.name, 'updated name');
should.equal(result.gender, null);
done();
});
});
@ -880,8 +887,9 @@ describe('manipulation', function() {
});
it('should allow save() of the created instance', function(done) {
var unknownId = uid.fromConnector(db) || 999;
Person.updateOrCreate(
{id: 999 /* a new id */, name: 'a-name'},
{id: unknownId, name: 'a-name'},
function(err, inst) {
if (err) return done(err);
inst.save(done);
@ -893,30 +901,31 @@ describe('manipulation', function() {
describe.skip('replaceById - not implemented', function() {});
} else {
describe('replaceOrCreate', function() {
var Post;
var ds = getSchema();
var Post, unknownId;
before(function(done) {
Post = ds.define('Post', {
db = getSchema();
unknownId = uid.fromConnector(db) || 123;
Post = db.define('Post', {
title: {type: String, length: 255, index: true},
content: {type: String},
comments: [String],
}, {forceId: false});
ds.automigrate('Post', done);
db.automigrate('Post', done);
});
it('works without options on create (promise variant)', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'};
var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post)
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.be.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
return Post.findById(p.id)
.then(function(p) {
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.id.should.not.have.property('_id');
p.title.should.equal(p.title);
p.content.should.equal(p.content);
@ -927,18 +936,18 @@ describe('manipulation', function() {
});
it('works with options on create (promise variant)', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'};
var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post, {validate: false})
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.be.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
return Post.findById(p.id)
.then(function(p) {
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.id.should.not.have.property('_id');
p.title.should.equal(p.title);
p.content.should.equal(p.content);
@ -960,11 +969,12 @@ describe('manipulation', function() {
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.equal(created.id);
p.id.should.eql(created.id);
p.should.not.have.property('_id');
p.title.should.equal('b');
p.should.have.property('content', undefined);
p.should.have.property('comments', undefined);
return Post.findById(created.id)
.then(function(p) {
p.should.not.have.property('_id');
@ -990,11 +1000,12 @@ describe('manipulation', function() {
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Post);
p.id.should.equal(created.id);
p.id.should.eql(created.id);
p.should.not.have.property('_id');
p.title.should.equal('b');
p.should.have.property('content', undefined);
p.should.have.property('comments', undefined);
return Post.findById(created.id)
.then(function(p) {
p.should.not.have.property('_id');
@ -1018,11 +1029,12 @@ describe('manipulation', function() {
post.title = 'b';
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal('b');
p.should.have.property('content', undefined);
p.should.have.property('comments', undefined);
Post.findById(post.id, function(err, p) {
if (err) return done(err);
p.id.should.eql(post.id);
@ -1047,11 +1059,12 @@ describe('manipulation', function() {
post.title = 'b';
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal('b');
p.should.have.property('content', undefined);
p.should.have.property('comments', undefined);
Post.findById(post.id, function(err, p) {
if (err) return done(err);
p.id.should.eql(post.id);
@ -1066,16 +1079,17 @@ describe('manipulation', function() {
});
it('works without options on create (callback variant)', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'};
var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
Post.findById(p.id, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
@ -1085,16 +1099,17 @@ describe('manipulation', function() {
});
it('works with options on create (callback variant)', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'};
var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post, {validate: false}, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
Post.findById(p.id, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
p.id.should.eql(post.id);
p.should.not.have.property('_id');
p.title.should.equal(post.title);
p.content.should.equal(post.content);
@ -1106,19 +1121,23 @@ describe('manipulation', function() {
}
var hasReplaceById = !!getSchema().connector.replaceById;
bdd.describeIf(hasReplaceById, 'replaceOrCreate when forceId is true', function() {
var Post;
bdd.describeIf(hasReplaceById && connectorCapabilities.supportForceId !== false, 'replaceOrCreate ' +
'when forceId is true', function() {
var Post, unknownId;
before(function(done) {
var ds = getSchema();
Post = ds.define('Post', {
db = getSchema();
unknownId = uid.fromConnector(db) || 123;
Post = db.define('Post', {
title: {type: String, length: 255},
content: {type: String},
}, {forceId: true});
ds.automigrate('Post', done);
db.automigrate('Post', done);
});
it('fails when id does not exist in db', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'};
var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceOrCreate(post, function(err, p) {
err.statusCode.should.equal(404);
done();
@ -1137,17 +1156,17 @@ describe('manipulation', function() {
it('works on update if the request includes an existing id in db', function(done) {
Post.create({title: 'a', content: 'AAA'},
function(err, post) {
if (err) return done(err);
post = post.toObject();
delete post.content;
post.title = 'b';
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err);
p.id.should.equal(post.id);
done();
});
});
function(err, post) {
if (err) return done(err);
post = post.toObject();
delete post.content;
post.title = 'b';
Post.replaceOrCreate(post, function(err, p) {
if (err) return done(err);
p.id.should.eql(post.id);
done();
});
});
});
});
@ -1182,8 +1201,7 @@ describe('manipulation', function() {
function(done) {
StubUser.create({password: 'foo'}, function(err, created) {
if (err) return done(err);
created.replaceAttributes({password: 'test'},
function(err, created) {
created.replaceAttributes({password: 'test'}, function(err, created) {
if (err) return done(err);
created.password.should.equal('test-TEST');
StubUser.findById(created.id, function(err, found) {
@ -1201,8 +1219,8 @@ describe('manipulation', function() {
if (err) return done(err);
changePostIdInHook('before save');
p.replaceAttributes({title: 'b'}, function(err, data) {
data.id.should.eql(postInstance.id);
if (err) return done(err);
data.id.should.eql(postInstance.id);
Post.find(function(err, p) {
if (err) return done(err);
p[0].id.should.eql(postInstance.id);
@ -1303,11 +1321,13 @@ describe('manipulation', function() {
});
it('should fail when changing id', function(done) {
var unknownId = uid.fromConnector(db) || 999;
Post.findById(postInstance.id, function(err, p) {
if (err) return done(err);
p.replaceAttributes({title: 'b', id: 999}, function(err, p) {
p.replaceAttributes({title: 'b', id: unknownId}, function(err, p) {
should.exist(err);
var expectedErrMsg = 'id property (id) cannot be updated from ' + postInstance.id + ' to 999';
var expectedErrMsg = 'id property (id) cannot be updated from ' +
postInstance.id + ' to ' + unknownId;
err.message.should.equal(expectedErrMsg);
done();
});
@ -1351,16 +1371,18 @@ describe('manipulation', function() {
bdd.describeIf(hasReplaceById, 'replaceById', function() {
var Post;
before(function(done) {
var ds = getSchema();
Post = ds.define('Post', {
db = getSchema();
Post = db.define('Post', {
title: {type: String, length: 255},
content: {type: String},
}, {forceId: true});
ds.automigrate('Post', done);
db.automigrate('Post', done);
});
it('fails when id does not exist in db using replaceById', function(done) {
var post = {id: 123, title: 'a', content: 'AAA'};
bdd.itIf(connectorCapabilities.supportForceId !== false, 'fails when id does not exist in db ' +
'using replaceById', function(done) {
var unknownId = uid.fromConnector(db) || 123;
var post = {id: unknownId, title: 'a', content: 'AAA'};
Post.replaceById(post.id, post, function(err, p) {
err.statusCode.should.equal(404);
done();
@ -1501,7 +1523,8 @@ describe('manipulation', function() {
it('should destroy filtered set of records');
});
describe('deleteAll/destroyAll', function() {
bdd.describeIf(connectorCapabilities.reportDeletedCount !== false &&
connectorCapabilities.deleteWithOtherThanId !== false, 'deleteAll/destroyAll', function() {
beforeEach(function clearOldData(done) {
Person.deleteAll(done);
});
@ -1511,7 +1534,10 @@ describe('manipulation', function() {
name: 'John',
}, {
name: 'Jane',
}], done);
}], function(err, data) {
should.not.exist(err);
done();
});
});
it('should be defined as function', function() {
@ -1563,6 +1589,81 @@ describe('manipulation', function() {
});
});
bdd.describeIf(connectorCapabilities.reportDeletedCount === false &&
connectorCapabilities.deleteWithOtherThanId === false, 'deleteAll/destroyAll case 2', function() {
var idJohn, idJane;
beforeEach(function clearOldData(done) {
Person.deleteAll(done);
});
beforeEach(function createTestData(done) {
Person.create([{
name: 'John',
}, {
name: 'Jane',
}], function(err, data) {
should.not.exist(err);
data.forEach(function(person) {
if (person.name === 'John') idJohn = person.id;
if (person.name === 'Jane') idJane = person.id;
});
should.exist(idJohn);
should.exist(idJane);
done();
});
});
it('should be defined as function', function() {
Person.deleteAll.should.be.a.Function;
Person.destroyAll.should.be.a.Function;
});
it('should only delete instances that satisfy the where condition',
function(done) {
Person.deleteAll({id: idJohn}, function(err, info) {
if (err) return done(err);
should.not.exist(info.count);
Person.find({where: {name: 'John'}}, function(err, data) {
if (err) return done(err);
should.not.exist(data.count);
data.should.have.length(0);
Person.find({where: {name: 'Jane'}}, function(err, data) {
if (err) return done(err);
data.should.have.length(1);
done();
});
});
});
});
it('should report zero deleted instances when no matches are found',
function(done) {
var unknownId = uid.fromConnector(db) || 1234567890;
Person.deleteAll({id: unknownId}, function(err, info) {
if (err) return done(err);
should.not.exist(info.count);
Person.count(function(err, count) {
if (err) return done(err);
count.should.equal(2);
done();
});
});
});
it('should delete all instances when the where condition is not provided',
function(done) {
Person.deleteAll(function(err, info) {
if (err) return done(err);
should.not.exist(info.count);
Person.count(function(err, count) {
if (err) return done(err);
count.should.equal(0);
done();
});
});
});
});
describe('deleteById', function() {
beforeEach(givenSomePeople);
afterEach(function() {
@ -1573,26 +1674,37 @@ describe('manipulation', function() {
Person.findOne(function(e, p) {
Person.deleteById(p.id, function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 1);
} else {
should.not.exist(info.count);
}
done();
});
});
});
it('should allow deleteById(id) - fail', function(done) {
var unknownId = uid.fromConnector(db) || 9999;
Person.settings.strictDelete = false;
Person.deleteById(9999, function(err, info) {
Person.deleteById(unknownId, function(err, info) {
if (err) return done(err);
info.should.have.property('count', 0);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 0);
} else {
should.not.exist(info.count);
}
done();
});
});
it('should allow deleteById(id) - fail with error', function(done) {
var unknownId = uid.fromConnector(db) || 9999;
var errMsg = 'No instance with id ' + unknownId.toString() + ' found for Person';
Person.settings.strictDelete = true;
Person.deleteById(9999, function(err) {
Person.deleteById(unknownId, function(err) {
should.exist(err);
err.message.should.equal('No instance with id 9999 found for Person');
err.message.should.equal(errMsg);
err.should.have.property('code', 'NOT_FOUND');
err.should.have.property('statusCode', 404);
done();
@ -1611,7 +1723,11 @@ describe('manipulation', function() {
if (e) return done(e);
p.delete(function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 1);
} else {
should.not.exist(info.count);
}
done();
});
});
@ -1623,17 +1739,26 @@ describe('manipulation', function() {
if (e) return done(e);
p.delete(function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 1);
} else {
should.not.exist(info.count);
}
p.delete(function(err, info) {
if (err) return done(err);
info.should.have.property('count', 0);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 0);
} else {
should.not.exist(info.count);
}
done();
});
});
});
});
it('should allow delete(id) - fail with error', function(done) {
bdd.itIf(connectorCapabilities.supportStrictDelete !== false, 'should allow delete(id) - ' +
'fail with error', function(done) {
Person.settings.strictDelete = true;
Person.findOne(function(err, u) {
if (err) return done(err);
@ -1888,7 +2013,11 @@ describe('manipulation', function() {
});
describe('update/updateAll', function() {
var idBrett, idCarla, idDonna, idFrank, idGrace, idHarry;
var filterBrett, filterHarry;
beforeEach(function clearOldData(done) {
db = getSchema();
Person.destroyAll(done);
});
@ -1908,7 +2037,22 @@ describe('manipulation', function() {
}, {
name: 'Grace Goe',
age: 23,
}], done);
}], function(err, data) {
should.not.exist(err);
data.forEach(function(person) {
if (person.name === 'Brett Boe') idBrett = person.id;
if (person.name === 'Carla Coe') idCarla = person.id;
if (person.name === 'Donna Doe') idDonna = person.id;
if (person.name === 'Frank Foe') idFrank = person.id;
if (person.name === 'Grace Goe') idGrace = person.id;
});
should.exist(idBrett);
should.exist(idCarla);
should.exist(idDonna);
should.exist(idFrank);
should.exist(idGrace);
done();
});
});
it('should be defined as a function', function() {
@ -1918,10 +2062,17 @@ describe('manipulation', function() {
it('should not update instances that do not satisfy the where condition',
function(done) {
Person.update({name: 'Harry Hoe'}, {name: 'Marta Moe'}, function(err,
idHarry = uid.fromConnector(db) || undefined;
var filter = connectorCapabilities.updateWithOtherThanId === false ?
{id: idHarry} : {name: 'Harry Hoe'};
Person.update(filter, {name: 'Marta Moe'}, function(err,
info) {
if (err) return done(err);
info.should.have.property('count', 0);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 0);
} else {
should.not.exist(info.count);
}
Person.find({where: {name: 'Harry Hoe'}}, function(err, people) {
if (err) return done(err);
people.should.be.empty;
@ -1932,10 +2083,16 @@ describe('manipulation', function() {
it('should only update instances that satisfy the where condition',
function(done) {
Person.update({name: 'Brett Boe'}, {name: 'Harry Hoe'}, function(err,
var filter = connectorCapabilities.deleteWithOtherThanId === false ?
{id: idBrett} : {name: 'Brett Boe'};
Person.update(filter, {name: 'Harry Hoe'}, function(err,
info) {
if (err) return done(err);
info.should.have.property('count', 1);
if (connectorCapabilities.reportDeletedCount !== false) {
info.should.have.property('count', 1);
} else {
should.not.exist(info.count);
}
Person.find({where: {age: 19}}, function(err, people) {
if (err) return done(err);
people.should.have.length(1);
@ -1945,46 +2102,49 @@ describe('manipulation', function() {
});
});
it('should update all instances when the where condition is not provided',
function(done) {
Person.update({name: 'Harry Hoe'}, function(err, info) {
bdd.itIf(connectorCapabilities.updateWithoutId !== false, 'should update all instances when ' +
'the where condition is not provided', function(done) {
filterHarry = connectorCapabilities.deleteWithOtherThanId === false ?
{id: idHarry} : {name: 'Harry Hoe'};
filterBrett = connectorCapabilities.deleteWithOtherThanId === false ?
{id: idBrett} : {name: 'Brett Boe'};
Person.update(filterHarry, function(err, info) {
if (err) return done(err);
info.should.have.property('count', 5);
Person.find({where: filterBrett}, function(err, people) {
if (err) return done(err);
people.should.be.empty();
Person.find({where: filterHarry}, function(err, people) {
if (err) return done(err);
info.should.have.property('count', 5);
Person.find({where: {name: 'Brett Boe'}}, function(err, people) {
if (err) return done(err);
people.should.be.empty;
Person.find({where: {name: 'Harry Hoe'}}, function(err, people) {
if (err) return done(err);
people.should.have.length(5);
done();
});
});
});
});
it('should ignore where conditions with undefined values',
function(done) {
Person.update({name: 'Brett Boe'}, {name: undefined, gender: 'male'},
function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
Person.find({where: {name: 'Brett Boe'}}, function(err, people) {
if (err) return done(err);
people.should.have.length(1);
people[0].name.should.equal('Brett Boe');
done();
});
});
});
it('should not coerce invalid values provided in where conditions',
function(done) {
Person.update({name: 'Brett Boe'}, {dob: 'Carla Coe'}, function(err) {
should.exist(err);
err.message.should.equal('Invalid date: Carla Coe');
people.should.have.length(5);
done();
});
});
});
});
bdd.itIf(connectorCapabilities.ignoreUndefinedConditionValue !== false, 'should ignore where ' +
'conditions with undefined values', function(done) {
Person.update(filterBrett, {name: undefined, gender: 'male'},
function(err, info) {
if (err) return done(err);
info.should.have.property('count', 1);
Person.find({where: filterBrett}, function(err, people) {
if (err) return done(err);
people.should.have.length(1);
people[0].name.should.equal('Brett Boe');
done();
});
});
});
it('should not coerce invalid values provided in where conditions', function(done) {
Person.update({name: 'Brett Boe'}, {dob: 'notadate'}, function(err) {
should.exist(err);
err.message.should.equal('Invalid date: notadate');
done();
});
});
});
describe('upsertWithWhere', function() {
@ -2073,13 +2233,13 @@ describe('manipulation', function() {
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Person);
p.id.should.be.equal(person.id);
p.id.should.eql(person.id);
p.should.not.have.property('_id');
p.name.should.equal(person.name);
p.city.should.equal(person.city);
return Person.findById(p.id)
.then(function(p) {
p.id.should.equal(person.id);
p.id.should.eql(person.id);
p.id.should.not.have.property('_id');
p.name.should.equal(person.name);
p.city.should.equal(person.city);
@ -2095,13 +2255,13 @@ describe('manipulation', function() {
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Person);
p.id.should.be.equal(person.id);
p.id.should.eql(person.id);
p.should.not.have.property('_id');
p.name.should.equal(person.name);
p.city.should.equal(person.city);
return Person.findById(p.id)
.then(function(p) {
p.id.should.equal(person.id);
p.id.should.eql(person.id);
p.id.should.not.have.property('_id');
p.name.should.equal(person.name);
p.city.should.equal(person.city);
@ -2122,7 +2282,7 @@ describe('manipulation', function() {
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Person);
p.id.should.equal(created.id);
p.id.should.eql(created.id);
p.should.not.have.property('_id');
p.name.should.equal('BBB');
p.should.have.property('city', 'city AAA');
@ -2149,7 +2309,7 @@ describe('manipulation', function() {
.then(function(p) {
should.exist(p);
p.should.be.instanceOf(Person);
p.id.should.equal(created.id);
p.id.should.eql(created.id);
p.should.not.have.property('_id');
p.name.should.equal('Carlton');
p.should.have.property('city', 'city CCC');
@ -2217,7 +2377,7 @@ describe('manipulation', function() {
if (err) return done(err);
Person.findById(5, function(err, data) {
if (err) return done(err);
data.id.should.equal(5);
should.equal(data.id, 5);
data.name.should.equal('Brian');
data.city.should.equal('Kentucky');
done();

File diff suppressed because it is too large Load Diff