diff --git a/API.md b/API.md index 5f35059f8..ecabf13ae 100644 --- a/API.md +++ b/API.md @@ -136,7 +136,7 @@ - [`string.normalize([form])`](#stringnormalizeform) - [`string.lowercase()`](#stringlowercase) - [`string.uppercase()`](#stringuppercase) - - [`string.trim()`](#stringtrim) + - [`string.trim([enabled])`](#stringtrimenabled) - [`string.isoDate()`](#stringisodate) - [`alternatives` - inherits from `Any`](#alternatives---inherits-from-any) - [`alternatives.try(schemas)`](#alternativestryschemas) @@ -2155,13 +2155,17 @@ will be forced to uppercase. const schema = Joi.string().uppercase(); ``` -#### `string.trim()` +#### `string.trim([enabled])` Requires the string value to contain no whitespace before or after. If the validation `convert` option is on (enabled by default), the string will be trimmed. +Parameters are: +- `enabled` - optional parameter defaulting to `true` which allows you to reset the behavior of trim by providing a falsy value. + ```js const schema = Joi.string().trim(); +const schema = Joi.string().trim(false); // disable trim flag ``` #### `string.isoDate()` diff --git a/lib/types/string/index.js b/lib/types/string/index.js index 94bbfc9d8..374a27d01 100755 --- a/lib/types/string/index.js +++ b/lib/types/string/index.js @@ -572,20 +572,30 @@ internals.String = class extends Any { return obj; } - trim() { + trim(enabled) { - const obj = this._test('trim', undefined, function (value, state, options) { + enabled = enabled === undefined ? true : enabled; + Hoek.assert(typeof enabled === 'boolean', 'option must be a boolean'); - if (options.convert || - value === value.trim()) { + let obj; + if (enabled) { + obj = this._test('trim', undefined, function (value, state, options) { - return value; - } + if (options.convert || + value === value.trim()) { - return this.createError('string.trim', { value }, state, options); - }); + return value; + } + + return this.createError('string.trim', { value }, state, options); + }); + } + else { + obj = this.clone(); + obj._tests = obj._tests.filter((test) => test.name !== 'trim'); + } - obj._flags.trim = true; + obj._flags.trim = enabled; return obj; } diff --git a/test/types/string.js b/test/types/string.js index 2da81f4b7..e5afcadcf 100644 --- a/test/types/string.js +++ b/test/types/string.js @@ -1531,6 +1531,27 @@ describe('string', () => { ], { convert: false }); }); + it('disable existing trim flag when passing enabled: false', () => { + + const trimEnabledSchema = Joi.string().trim(true); + Helper.validateOptions(trimEnabledSchema, [ + [' something', false, null, { + message: '"value" must not have leading or trailing whitespace', + details: [{ + message: '"value" must not have leading or trailing whitespace', + path: [], + type: 'string.trim', + context: { value: ' something', label: 'value', key: undefined } + }] + }] + ], { convert: false }); + + const trimDisabledSchema = trimEnabledSchema.trim(false); + Helper.validateOptions(trimDisabledSchema, [ + [' something', true] + ], { convert: false }); + }); + it('removes leading and trailing whitespace before validation', async () => { const schema = Joi.string().trim(); @@ -1654,6 +1675,14 @@ describe('string', () => { ['ABC', true] ]); }); + + it('throws when option is not a boolean', () => { + + expect(() => { + + Joi.string().trim(42); + }).to.throw('option must be a boolean'); + }); }); describe('replace()', () => {