607 lines
22 KiB
JavaScript
607 lines
22 KiB
JavaScript
// Copyright IBM Corp. 2015,2019. All Rights Reserved.
|
|
// Node module: loopback-datasource-juggler
|
|
// This file is licensed under the MIT License.
|
|
// License text available at https://opensource.org/licenses/MIT
|
|
|
|
// This test written in mocha+should.js
|
|
'use strict';
|
|
|
|
/* global getSchema:false */
|
|
const async = require('async');
|
|
const should = require('./init.js');
|
|
let db, User, options, ModelWithForceId, whereCount = 0;
|
|
const j = require('../');
|
|
const ValidationError = j.ValidationError;
|
|
|
|
const INITIAL_NAME = 'Bert';
|
|
const NEW_NAME = 'Ernie';
|
|
const INVALID_DATA = {name: null};
|
|
const VALID_DATA = {name: INITIAL_NAME};
|
|
|
|
describe('optional-validation', function() {
|
|
before(function(done) {
|
|
db = getSchema();
|
|
ModelWithForceId = db.createModel(
|
|
'ModelWithForceId',
|
|
{name: String},
|
|
{forceId: true},
|
|
);
|
|
User = db.define('User', {
|
|
seq: {type: Number, index: true},
|
|
name: {type: String, index: true, sort: true},
|
|
email: {type: String, index: true},
|
|
birthday: {type: Date, index: true},
|
|
role: {type: String, index: true},
|
|
order: {type: Number, index: true, sort: true},
|
|
vip: {type: Boolean},
|
|
}, {forceId: true, strict: true});
|
|
db.automigrate(['ModelWithForceId', 'User'], done);
|
|
});
|
|
|
|
beforeEach(function(done) {
|
|
User.destroyAll(function() {
|
|
delete User.validations;
|
|
User.validatesPresenceOf('name');
|
|
done();
|
|
});
|
|
});
|
|
|
|
function expectValidationError(done) {
|
|
return function(err, result) {
|
|
should.exist(err);
|
|
err.should.be.instanceOf(Error);
|
|
err.should.be.instanceOf(ValidationError);
|
|
done();
|
|
};
|
|
}
|
|
|
|
function expectCreateSuccess(data, done) {
|
|
if (done === undefined && typeof data === 'function') {
|
|
done = data;
|
|
data = {name: INITIAL_NAME};
|
|
}
|
|
return function(err, instance) {
|
|
if (err) return done(err);
|
|
instance.should.be.instanceOf(User);
|
|
if (data.name) {
|
|
instance.name.should.eql(data.name || INITIAL_NAME);
|
|
} else {
|
|
should.not.exist(instance.name);
|
|
}
|
|
done();
|
|
};
|
|
}
|
|
|
|
function expectChangeSuccess(data, done) {
|
|
if (done === undefined && typeof data === 'function') {
|
|
done = data;
|
|
data = {name: NEW_NAME};
|
|
}
|
|
return function(err, instance) {
|
|
if (err) return done(err);
|
|
instance.should.be.instanceOf(User);
|
|
if (data.name) {
|
|
instance.name.should.eql(data.name || NEW_NAME);
|
|
} else {
|
|
should.not.exist(instance.name);
|
|
}
|
|
done();
|
|
};
|
|
}
|
|
|
|
function createUserAndChangeName(name, cb) {
|
|
User.create(VALID_DATA, {validate: true}, function(err, d) {
|
|
d.name = name;
|
|
cb(err, d);
|
|
});
|
|
}
|
|
|
|
function createUser(cb) {
|
|
User.create(VALID_DATA, {validate: true}, cb);
|
|
}
|
|
|
|
function callUpdateOrCreateWithExistingUserId(name, options, cb) {
|
|
User.create({'name': 'Groover'}, function(err, user) {
|
|
if (err) return cb(err);
|
|
const data = {name: name};
|
|
data.id = user.id;
|
|
User.updateOrCreate(data, options, cb);
|
|
});
|
|
}
|
|
|
|
function getNewWhere() {
|
|
return {name: 'DoesNotExist' + (whereCount++)};
|
|
}
|
|
|
|
describe('forceId', function() {
|
|
context('replaceAttributes', function() {
|
|
it('should not fail if you do not pass the Primary key in data object',
|
|
function(done) {
|
|
ModelWithForceId.create({name: 'foo'}, function(err, created) {
|
|
if (err) return done(err);
|
|
created.replaceAttributes({name: 'bar'}, function(err, data) {
|
|
done(err);
|
|
});
|
|
});
|
|
});
|
|
|
|
it('should fail if you pass the Primary key in data object',
|
|
function(done) {
|
|
ModelWithForceId.create({name: 'foo'}, function(err, created) {
|
|
if (err) return done(err);
|
|
created.replaceAttributes({name: 'bar', id: 999},
|
|
function(err, data) {
|
|
should.exist(err);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('no model setting', function() {
|
|
describe('method create', function() {
|
|
it('should throw on create with validate:true with invalid data', function(done) {
|
|
User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:false with invalid data', function(done) {
|
|
User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:true with valid data', function(done) {
|
|
User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:false with valid data', function(done) {
|
|
User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should throw on create with invalid data', function(done) {
|
|
User.create(INVALID_DATA, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on create with valid data', function(done) {
|
|
User.create(VALID_DATA, expectCreateSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method findOrCreate', function() {
|
|
it('should throw on findOrCreate with validate:true with invalid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
|
|
expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:false with invalid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
|
|
expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:true with valid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
|
|
expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:false with valid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
|
|
expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should throw on findOrCreate with invalid data', function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with valid data', function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, expectCreateSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method updateOrCreate on existing data', function() {
|
|
it('should throw on updateOrCreate(id) with validate:true with invalid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, {validate: true},
|
|
expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, {validate: false},
|
|
expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
|
|
expectChangeSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
|
|
expectChangeSuccess(done));
|
|
});
|
|
|
|
// backwards compatible with validateUpsert
|
|
it('should NOT throw on updateOrCreate(id) with invalid data', function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with valid data', function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method save', function() {
|
|
it('should throw on save with {validate:true} with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save({validate: true}, expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:false} with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:true} with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save({validate: true}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:false} with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save({validate: false}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should throw on save(cb) with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save(expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save(cb) with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save(expectChangeSuccess(done));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('method updateAttributes', function() {
|
|
it('should throw on updateAttributes with {validate:true} with invalid data', function(done) {
|
|
createUser(function(err, d) {
|
|
d.updateAttributes(INVALID_DATA, {validate: true}, expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on updateAttributes with {validate:false} with invalid data', function(done) {
|
|
createUser(function(err, d) {
|
|
d.updateAttributes(INVALID_DATA, {validate: false}, expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on updateAttributes with {validate:true} with valid data', function(done) {
|
|
createUser(function(err, d) {
|
|
d.updateAttributes({'name': NEW_NAME}, {validate: true}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on updateAttributes with {validate:false} with valid data', function(done) {
|
|
createUser(function(err, d) {
|
|
d.updateAttributes({'name': NEW_NAME}, {validate: false}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should throw on updateAttributes(cb) with invalid data', function(done) {
|
|
createUser(function(err, d) {
|
|
d.updateAttributes(INVALID_DATA, expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on updateAttributes(cb) with valid data', function(done) {
|
|
createUser(function(err, d) {
|
|
d.updateAttributes({'name': NEW_NAME}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('returns an error when trying to update the id property when forceId is set to true',
|
|
function(done) {
|
|
ModelWithForceId.create({name: 'foo'}, function(err, model) {
|
|
if (err) return done(err);
|
|
model.updateAttributes({id: 123}, function(err) {
|
|
err.should.be.instanceOf(Error);
|
|
err.message.should.eql('id cannot be updated from ' + model.id +
|
|
' to 123 when forceId is set to true');
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('model setting: automaticValidation: false', function() {
|
|
before(function(done) {
|
|
User.settings.automaticValidation = false;
|
|
done();
|
|
});
|
|
|
|
describe('method create', function() {
|
|
it('should throw on create with validate:true with invalid data', function(done) {
|
|
User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:false with invalid data', function(done) {
|
|
User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:true with valid data', function(done) {
|
|
User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:false with valid data', function(done) {
|
|
User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on create with invalid data', function(done) {
|
|
User.create(INVALID_DATA, expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on create with valid data', function(done) {
|
|
User.create(VALID_DATA, expectCreateSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method findOrCreate', function() {
|
|
it('should throw on findOrCreate with validate:true with invalid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
|
|
expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:false with invalid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
|
|
expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:true with valid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
|
|
expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:false with valid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
|
|
expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with invalid data', function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA,
|
|
expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with valid data', function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, expectCreateSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method updateOrCreate on existing data', function() {
|
|
it('should throw on updateOrCreate(id) with validate:true with invalid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, {validate: true},
|
|
expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, {validate: false},
|
|
expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
|
|
expectChangeSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
|
|
expectChangeSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with invalid data', function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with valid data', function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method save', function() {
|
|
it('should throw on save with {validate:true} with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save({validate: true}, expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:false} with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:true} with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save({validate: true}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:false} with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save({validate: false}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save(cb) with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save(expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save(cb) with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save(expectChangeSuccess(done));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('model setting: automaticValidation: true', function() {
|
|
before(function(done) {
|
|
User.settings.automaticValidation = true;
|
|
done();
|
|
});
|
|
|
|
describe('method create', function() {
|
|
it('should throw on create with validate:true with invalid data', function(done) {
|
|
User.create(INVALID_DATA, {validate: true}, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:false with invalid data', function(done) {
|
|
User.create(INVALID_DATA, {validate: false}, expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:true with valid data', function(done) {
|
|
User.create(VALID_DATA, {validate: true}, expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on create with validate:false with valid data', function(done) {
|
|
User.create(VALID_DATA, {validate: false}, expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should throw on create with invalid data', function(done) {
|
|
User.create(INVALID_DATA, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on create with valid data', function(done) {
|
|
User.create(VALID_DATA, expectCreateSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method findOrCreate', function() {
|
|
it('should throw on findOrCreate with validate:true with invalid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: true},
|
|
expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:false with invalid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, {validate: false},
|
|
expectCreateSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:true with valid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: true},
|
|
expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with validate:false with valid data',
|
|
function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, {validate: false},
|
|
expectCreateSuccess(done));
|
|
});
|
|
|
|
it('should throw on findOrCreate with invalid data', function(done) {
|
|
User.findOrCreate(getNewWhere(), INVALID_DATA, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on findOrCreate with valid data', function(done) {
|
|
User.findOrCreate(getNewWhere(), VALID_DATA, expectCreateSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method updateOrCreate on existing data', function() {
|
|
it('should throw on updateOrCreate(id) with validate:true with invalid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, {validate: true},
|
|
expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:false with invalid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, {validate: false},
|
|
expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:true with valid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: true},
|
|
expectChangeSuccess(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with validate:false with valid data',
|
|
function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, {validate: false},
|
|
expectChangeSuccess(done));
|
|
});
|
|
|
|
it('should throw on updateOrCreate(id) with invalid data', function(done) {
|
|
callUpdateOrCreateWithExistingUserId(null, expectValidationError(done));
|
|
});
|
|
|
|
it('should NOT throw on updateOrCreate(id) with valid data', function(done) {
|
|
callUpdateOrCreateWithExistingUserId(NEW_NAME, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
describe('method save', function() {
|
|
it('should throw on save with {validate:true} with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save(options, expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:false} with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save({validate: false}, expectChangeSuccess(INVALID_DATA, done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:true} with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save({validate: true}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save with {validate:false} with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save({validate: false}, expectChangeSuccess(done));
|
|
});
|
|
});
|
|
|
|
it('should throw on save(cb) with invalid data', function(done) {
|
|
createUserAndChangeName(null, function(err, d) {
|
|
d.save(expectValidationError(done));
|
|
});
|
|
});
|
|
|
|
it('should NOT throw on save(cb) with valid data', function(done) {
|
|
createUserAndChangeName(NEW_NAME, function(err, d) {
|
|
d.save(expectChangeSuccess(done));
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|