Skip to content

Commit

Permalink
feat: String exactLength validator
Browse files Browse the repository at this point in the history
  • Loading branch information
the-darc committed Mar 19, 2015
1 parent 2333f76 commit 1f4cf09
Show file tree
Hide file tree
Showing 4 changed files with 181 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
module.exports = function(mongoose) {
require('./lib/string-ext/max-length.js')(mongoose);
require('./lib/string-ext/min-length.js')(mongoose);
require('./lib/string-ext/exact-length.js')(mongoose);
};
55 changes: 55 additions & 0 deletions lib/string-ext/exact-length.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module.exports = function(mongoose) {
var SchemaString = mongoose.SchemaTypes.String,
errorMessages = mongoose.Error.messages;

/**
* Sets a exactlength string validator.
*
* ####Example:
*
* var s = new Schema({ n: { type: String, exactlength: 4 })
* var M = db.model('M', s)
* var m = new M({ n: 'teste' })
* m.save(function (err) {
* console.error(err) // validator error
* m.n = 'test;
* m.save() // success
* })
*
* // custom error messages
* // We can also use the special {EXACT_LENGTH} token which will be replaced with the invalid value
* var max = [4, 'The length of path `{PATH}` ({VALUE}) is beneath the limit ({EXACT_LENGTH}).'];
* var schema = new Schema({ n: { type: String, exactlength: max })
* var M = mongoose.model('Measurement', schema);
* var s= new M({ n: 'teste' });
* s.validate(function (err) {
* console.log(String(err)) // ValidationError: The length of path `n` (5) is beneath the limit (4).
* })
*
* @param {Number} max length value
* @param {String} [message] optional custom error message
* @return {SchemaType} this
* @see Customized Error Messages #error_messages_MongooseError-messages
* @api public
*/

SchemaString.prototype.exactlength = function(value, message) {
if (this.exactlengthValidator) {
this.validators = this.validators.filter(function (v) {
return v[0] !== this.exactlengthValidator;
}, this);
}

if (null !== value) {
var msg = message || errorMessages.String.exactlength;
msg = msg.replace(/{EXACT_LENGTH}/, value);
this.validators.push([this.exactlengthValidator = function (v) {
return v === undefined || v === null || v.length === value;
}, msg, 'exactlength']);
}

return this;
};

errorMessages.String.exactlength = 'Path `{PATH}` ({VALUE}) has length different of the expected ({EXACT_LENGTH}).';
};
124 changes: 124 additions & 0 deletions test/exact-length.string.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
var db = require('db'),
mongoose = db.mongoose,
should = require('should');

require('../index');
require('../lib/string-ext/max-length');

describe('String.minLength:', function() {
var TestDoc;

before('init db', db.init);
before('load extensions', db.loadExtensions);
before('load test model', function(done) {
var TestDocSchema = new mongoose.Schema({
field01: String,
field02: {
type: String,
exactlength: 5
},
field03: {
type: String,
exactlength: [10, 'Invalid text length']
},
field04: {
type: String,
exactlength: [1, 'Path {PATH} ({VALUE}) has length different of {EXACT_LENGTH}']
}
});
TestDoc = mongoose.model('TestDoc', TestDocSchema);
done();
});

it('should not impact normal string types', function(done) {
this.timeout(5000);
var tst = new TestDoc({field01: '12345678'});
tst.save(function(err, tst) {
if(err) {
return done(err);
}
should(tst.field01).be.eql('12345678');
done();
});
});
it('should not throw maxLength error for exact length strings', function(done) {
var tst = new TestDoc({field02: '12345'});
tst.save(function(err, tst) {
if(err) {
return done(err);
}
should(tst.field02).be.eql('12345');
done();
});
});
it('should not throw maxLength error for empty values', function(done) {
var tst = new TestDoc({field01: 'some value'});
tst.save(function(err, tst) {
if(err) {
return done(err);
}
should(tst.field01).be.eql('some value');
should(tst.field02).be.not.ok;
done();
});
});
it('should throw exactLength error for shorter strings', function(done) {
var tst = new TestDoc({field02: '1234'});
tst.save(function(err) {
should(err).be.ok;
should(err.message).be.eql('Validation failed');
should(err.name).be.eql('ValidationError');
should(err.errors.field02).be.ok;
should(err.errors.field02.message).be.eql(
'Path `field02` (1234) has length different of the expected (5).'
);
done();
});
});
it('should throw exactLength default for bigger strings', function(done) {
var tst = new TestDoc({field02: '123456'});
tst.save(function(err) {
should(err).be.ok;
should(err.message).be.eql('Validation failed');
should(err.name).be.eql('ValidationError');
should(err.errors.field02).be.ok;
should(err.errors.field02.message).be.eql(
'Path `field02` (123456) has length different of the expected (5).'
);
done();
});
});
it('should throw exactLength custom error message', function(done) {
var tst = new TestDoc({
field02: '123456',
field03: '123456789112345'
});
tst.save(function(err) {
should(err).be.ok;
should(err.message).be.eql('Validation failed');
should(err.name).be.eql('ValidationError');
should(err.errors.field02).be.ok;
should(err.errors.field02.message).be.eql(
'Path `field02` (123456) has length different of the expected (5).'
);
should(err.errors.field03).be.ok;
should(err.errors.field03.message).be.eql('Invalid text length');
done();
});
});
it('should throw maxLength custom error with special tokens replaced', function(done) {
var tst = new TestDoc({field04: 'test'});
tst.save(function(err) {
should(err).be.ok;
should(err.message).be.eql('Validation failed');
should(err.name).be.eql('ValidationError');
should(err.errors.field04).be.ok;
should(err.errors.field04.message).be.eql(
'Path field04 (test) has length different of 1'
);
done();
});
});

after('finish db', db.finish);
});
1 change: 1 addition & 0 deletions test/max-length.string.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ describe('String.maxLength:', function() {
});

it('should not impact normal string types', function(done) {
this.timeout(5000);
var tst = new TestDoc({field01: '12345678'});
tst.save(function(err, tst) {
if(err) {
Expand Down

0 comments on commit 1f4cf09

Please sign in to comment.