replace exception thrown for invalid dates

This commit is contained in:
Diana Lau 2017-04-21 14:12:04 -04:00
parent bcc5b559a3
commit a488a71dbd
5 changed files with 93 additions and 30 deletions

View File

@ -426,6 +426,7 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
var requiredOptions = typeof prop.required === 'object' ? prop.required : undefined; var requiredOptions = typeof prop.required === 'object' ? prop.required : undefined;
ModelClass.validatesPresenceOf(propertyName, requiredOptions); ModelClass.validatesPresenceOf(propertyName, requiredOptions);
} }
if (DataType === Date) ModelClass.validatesDateOf(propertyName);
Object.defineProperty(ModelClass.prototype, propertyName, { Object.defineProperty(ModelClass.prototype, propertyName, {
get: function() { get: function() {
@ -526,10 +527,8 @@ ModelBuilder.prototype.define = function defineClass(className, properties, sett
// DataType for Date // DataType for Date
function DateType(arg) { function DateType(arg) {
if (arg === null) return null;
var d = new Date(arg); var d = new Date(arg);
if (isNaN(d.getTime())) {
throw new Error(g.f('Invalid date: %s', arg));
}
return d; return d;
} }

View File

@ -243,6 +243,7 @@ Validatable.validateAsync = getConfigurator('custom', {async: true});
*/ */
Validatable.validatesUniquenessOf = getConfigurator('uniqueness', {async: true}); Validatable.validatesUniquenessOf = getConfigurator('uniqueness', {async: true});
Validatable.validatesDateOf = getConfigurator('date');
// implementation of validators // implementation of validators
/*! /*!
@ -383,6 +384,16 @@ function validateUniqueness(attr, conf, err, options, done) {
}.bind(this)); }.bind(this));
} }
/*!
* Date validator
*/
function validateDate(attr, conf, err) {
if (this[attr] === null || this[attr] === undefined) return;
var date = new Date(this[attr]);
if (isNaN(date.getTime())) return err();
}
var validators = { var validators = {
presence: validatePresence, presence: validatePresence,
absence: validateAbsence, absence: validateAbsence,
@ -393,6 +404,7 @@ var validators = {
format: validateFormat, format: validateFormat,
custom: validateCustom, custom: validateCustom,
uniqueness: validateUniqueness, uniqueness: validateUniqueness,
date: validateDate,
}; };
function getConfigurator(name, opts) { function getConfigurator(name, opts) {
@ -631,6 +643,7 @@ var defaultMessages = {
inclusion: 'is not included in the list', inclusion: 'is not included in the list',
exclusion: 'is reserved', exclusion: 'is reserved',
uniqueness: 'is not unique', uniqueness: 'is not unique',
date: 'is not a valid date',
}; };
/** /**
@ -841,7 +854,7 @@ function formatPropertyError(propertyName, propertyValue, errorMessage) {
if (valueType === 'string') { if (valueType === 'string') {
formattedValue = JSON.stringify(truncatePropertyString(propertyValue)); formattedValue = JSON.stringify(truncatePropertyString(propertyValue));
} else if (propertyValue instanceof Date) { } else if (propertyValue instanceof Date) {
formattedValue = propertyValue.toISOString(); formattedValue = isNaN(propertyValue.getTime()) ? propertyValue.toString() : propertyValue.toISOString();
} else if (valueType === 'object') { } else if (valueType === 'object') {
// objects and arrays // objects and arrays
formattedValue = util.inspect(propertyValue, { formattedValue = util.inspect(propertyValue, {

View File

@ -54,17 +54,6 @@ describe('datatypes', function() {
done(); done();
}); });
it('throws an error when property of type Date is set to an invalid value',
function() {
var myModel = db.define('myModel', {
date: {type: Date},
});
(function() {
myModel.create({date: 'invalid'});
}).should.throw({message: 'Invalid date: invalid'});
});
it('should keep types when get read data from db', function(done) { it('should keep types when get read data from db', function(done) {
var d = new Date, id; var d = new Date, id;

View File

@ -687,15 +687,6 @@ describe('manipulation', function() {
}); });
}); });
it('should fail if field validation fails', function(done) {
person.updateAttributes({'name': 'John', dob: 'notadate'},
function(err, p) {
should.exist(err);
err.message.should.equal('Invalid date: notadate');
done();
});
});
it('has an alias "patchAttributes"', function(done) { it('has an alias "patchAttributes"', function(done) {
person.updateAttributes.should.equal(person.patchAttributes); person.updateAttributes.should.equal(person.patchAttributes);
done(); done();
@ -2085,12 +2076,9 @@ describe('manipulation', function() {
p1 = new Person({name: 'John', dob: undefined}); p1 = new Person({name: 'John', dob: undefined});
p1.should.have.property('dob', undefined); p1.should.have.property('dob', undefined);
try { p1 = new Person({name: 'John', dob: 'X'});
p1 = new Person({name: 'John', dob: 'X'}); p1.should.have.property('dob');
throw new Error('new Person() should have thrown'); p1.dob.toString().should.be.eql('Invalid Date');
} catch (e) {
e.should.be.eql(new Error('Invalid date: X'));
}
}); });
}); });

View File

@ -823,4 +823,78 @@ describe('validations', function() {
return err.message.replace(/^.*Details: /, ''); return err.message.replace(/^.*Details: /, '');
} }
}); });
describe('date', function() {
it('should validate a date object', function() {
User.validatesDateOf('updatedAt');
var u = new User({updatedAt: new Date()});
u.isValid().should.be.true;
});
it('should validate a date string', function() {
User.validatesDateOf('updatedAt');
var u = new User({updatedAt: '2000-01-01'});
u.isValid().should.be.true;
});
it('should validate a null date', function() {
User.validatesDateOf('updatedAt');
var u = new User({updatedAt: null});
u.isValid().should.be.true;
});
it('should validate an undefined date', function() {
User.validatesDateOf('updatedAt');
var u = new User({updatedAt: undefined});
u.isValid().should.be.true;
});
it('should validate an invalid date string', function() {
User.validatesDateOf('updatedAt');
var u = new User({updatedAt: 'invalid date string'});
u.isValid().should.not.be.true;
u.errors.should.eql({
updatedAt: ['is not a valid date'],
codes: {
updatedAt: ['date'],
},
});
});
it('should attach validation by default to all date properties', function() {
var AnotherUser = db.define('User', {
email: String,
name: String,
password: String,
state: String,
age: Number,
gender: String,
domain: String,
pendingPeriod: Number,
createdByAdmin: Boolean,
createdByScript: Boolean,
updatedAt: Date,
});
var u = new AnotherUser({updatedAt: 'invalid date string'});
u.isValid().should.not.be.true;
u.errors.should.eql({
updatedAt: ['is not a valid date'],
codes: {
updatedAt: ['date'],
},
});
});
it('should overwrite default blank message with custom format message', function() {
var CUSTOM_MESSAGE = 'custom validation message';
User.validatesDateOf('updatedAt', {message: CUSTOM_MESSAGE});
var u = new User({updatedAt: 'invalid date string'});
u.isValid().should.not.be.true;
u.errors.should.eql({
updatedAt: [CUSTOM_MESSAGE],
codes: {
updatedAt: ['date'],
},
});
});
});
}); });