Skip to content

Commit

Permalink
Make coercion happen earlier in the validation
Browse files Browse the repository at this point in the history
Fixes #960.
  • Loading branch information
Marsup committed Jul 24, 2016
1 parent e68e741 commit 1ea86e6
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 16 deletions.
11 changes: 11 additions & 0 deletions lib/any.js
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,17 @@ module.exports = internals.Any = class {
};
};

if (this._coerce) {
const coerced = this._coerce.call(this, value, state, options);
if (coerced.errors) {
value = coerced.value;
errors = errors.concat(coerced.errors);
return finish(); // Coerced error always aborts early
}

value = coerced.value;
}

// Check presence requirements

const presence = this._flags.presence || options.presence;
Expand Down
39 changes: 23 additions & 16 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,19 +213,30 @@ internals.root = function () {

};

if (extension.coerce || extension.pre) {
type.prototype._base = function (value, state, options) {
if (extension.coerce) {
type.prototype._coerce = function (value, state, options) {

if (ctor.prototype._coerce) {
const baseRet = ctor.prototype._coerce.call(this, value, state, options);

let ret;
if (extension.coerce) {
ret = extension.coerce.call(this, value, state, options);
if (ret instanceof Errors.Err) {
return { value, errors: ret };
if (baseRet.errors) {
return baseRet;
}

value = ret;
value = baseRet.value;
}

const ret = extension.coerce.call(this, value, state, options);
if (ret instanceof Errors.Err) {
return { value, errors: ret };
}

return { value: ret };
};
}
if (extension.pre) {
type.prototype._base = function (value, state, options) {

if (ctor.prototype._base) {
const baseRet = ctor.prototype._base.call(this, value, state, options);

Expand All @@ -236,16 +247,12 @@ internals.root = function () {
value = baseRet.value;
}

if (extension.pre) {
ret = extension.pre.call(this, value, state, options);
if (ret instanceof Errors.Err) {
return { value, errors: ret };
}

return { value: ret };
const ret = extension.pre.call(this, value, state, options);
if (ret instanceof Errors.Err) {
return { value, errors: ret };
}

return { value };
return { value: ret };
};
}

Expand Down
76 changes: 76 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2329,6 +2329,82 @@ describe('Joi', () => {
done();
});

it('defines a custom type coercing its input value that runs early enough', (done) => {

const customJoi = Joi.extend({
base: Joi.string(),
coerce(value, state, options) {

return 'foobar';
},
name: 'myType'
});

const schema = customJoi.myType();
const result = schema.validate('');
expect(result.error).to.be.null();
expect(result.value).to.equal('foobar');

done();
});

it('defines multiple levels of coercion', (done) => {

const customJoi = Joi.extend({
base: Joi.string(),
coerce(value, state, options) {

return 'foobar';
},
name: 'myType'
});

const customJoi2 = customJoi.extend({
base: customJoi.myType(),
coerce(value, state, options) {

expect(value).to.equal('foobar');
return 'baz';
},
name: 'myType'
});

const schema = customJoi2.myType();
const result = schema.validate('');
expect(result.error).to.be.null();
expect(result.value).to.equal('baz');

done();
});

it('defines multiple levels of coercion where base fails', (done) => {

const customJoi = Joi.extend({
base: Joi.string(),
coerce(value, state, options) {

return this.createError('any.invalid', null, state, options);
},
name: 'myType'
});

const customJoi2 = customJoi.extend({
base: customJoi.myType(),
coerce(value, state, options) {

expect(value).to.equal('foobar');
return 'baz';
},
name: 'myType'
});

const schema = customJoi2.myType();
const result = schema.validate('');
expect(result.error).to.an.error('"value" contains an invalid value');

done();
});

it('defines a custom type casting its input value', (done) => {

const customJoi = Joi.extend({
Expand Down

0 comments on commit 1ea86e6

Please sign in to comment.