Skip to content

Commit

Permalink
Merge pull request #8 from gsmithun4/development
Browse files Browse the repository at this point in the history
Removed lodash and moments dependency
  • Loading branch information
gsmithun4 authored Dec 15, 2021
2 parents 8e4862d + 87a7517 commit 6fdd98a
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 45 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ Request field validator for expressjs
$ npm install expressjs-field-validator
```

## Dependencies
- [lodash](https://www.npmjs.com/package/lodash)
- [moment](https://www.npmjs.com/package/moment)

## How To Use

```js
Expand Down Expand Up @@ -85,13 +81,23 @@ validator([{param : 'id', location : 'params', isRequired : true}], { mode : 're
|isEmail |`Boolean` |The value is `Email` or not (default `false`)|
|isBoolean |`Boolean` |The value is `Boolean` or not (default `false`)|
|isDate |`Boolean` |The value is `Date` or not (default `false`)|
|format |`String` |Date format. Please reffer https://momentjs.com/docs/ for date formats|
|format |`String` |Date format. (default `YYYY-MM-DD`)|
|mobileNumber |`Object` |Object `{countryCode : '91', isCountryCodeMandatory : true, length: {min : 1, max : 10}}` ,describes characteristics of mobile number, length is the length range of mobile number excluding country code |
|length |`Object` |Object `{min : 1, max : 10}` describes minimum and maximum length|
|includes |`Object[]` |Value must be one of the element in the array|
|excludes |`Object[]` |Value must not be one of the element in the array|
|message |`String` |Error message thrown in case of test fails default : Invalid Field Error|

#### Supported date formats
If `isDate` is true you can pass `format`, Only supported the following
```
YYYY-MM-DD
DD-MM-YYYY'
MM-DD-YYYY'
YYYY/MM/DD'
DD/MM/YYYY'
MM/DD/YYYY'
```
#### Nested Objets
In case of `Object` or `Array`, `isArray` or `isObject` must be true
if json structure is
Expand Down
79 changes: 69 additions & 10 deletions lib/validator/validator.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
"use strict";

const _ = require('lodash');
const moment = require('moment');

module.exports = (validation = [], response = {}) => {
const validator = (() => {
const validate = (validation, req) => {
Expand All @@ -27,13 +24,13 @@ module.exports = (validation = [], response = {}) => {
}
const checkEmpty = (value) => {
//Checking if value is empty
if (_.isObject(value)) {
if (value instanceof Object) {
//Array or Object
if (!value || JSON.stringify(value).length === 2) {
return true;
}

} else if (isNaN(value) && !_.isBoolean(value) && (!value || value === 'undefined' || value.trim() === '')) {
} else if (isNaN(value) && value !== !!value && (!value || value === 'undefined' || value.trim() === '')) {
//Not Number Not Boolean => String
return true;
}
Expand Down Expand Up @@ -68,6 +65,53 @@ module.exports = (validation = [], response = {}) => {
}
}
}

const dateCheck = (dateString, format) => {
if (!dateString || !format) {
return false;
}
let regEx = /^\d{4}\/\d{2}\/\d{2}$/;
let YYYY,MM,DD;

switch (format) {
case 'YYYY-MM-DD':
regEx = /^\d{4}-\d{2}-\d{2}$/;
[YYYY, MM, DD] = dateString.split('-');
break;
case 'DD-MM-YYYY':
regEx = /^\d{2}-\d{2}-\d{4}$/;
[DD, MM, YYYY] = dateString.split('-');
break;
case 'MM-DD-YYYY':
regEx = /^\d{2}-\d{2}-\d{4}$/;
[MM, DD, YYYY] = dateString.split('-');
break;
case 'YYYY/MM/DD':
regEx = /^\d{4}\/\d{2}\/\d{2}$/;
[YYYY, MM, DD] = dateString.split('/');
break;
case 'DD/MM/YYYY':
regEx = /^\d{2}\/\d{2}\/\d{4}$/;
[DD, MM, YYYY] = dateString.split('/');
break;
case 'MM/DD/YYYY':
regEx = /^\d{2}\/\d{2}\/\d{4}$/;
[MM, DD, YYYY] = dateString.split('/');
break;
default:
break;
}

if (!dateString.match(regEx)) { // Invalid format
return false;
}
var d = new Date(`${YYYY}-${MM}-${DD}`);
var dNum = d.getTime();
if(!dNum && dNum !== 0) { // NaN value, Invalid date
return false;
}
return true;
}

try {
const isEmpty = checkEmpty(value);
Expand Down Expand Up @@ -100,16 +144,30 @@ module.exports = (validation = [], response = {}) => {
if (isArray && !Array.isArray(value)) {
throw new Error('Must Be An Array');
}
if (isObject && !_.isObject(value) && Array.isArray(value)) {
if (isObject && !(value instanceof Object) && Array.isArray(value)) {
throw new Error('Must Be An Object');
}
if (isDate) {
if (!moment(value, format || 'YYYY-MM-DD', true).isValid()) {
throw new Error(`Must Be A Date With Format ${format || 'YYYY-MM-DD'}`);
const supportedFormats = [
'YYYY-MM-DD',
'DD-MM-YYYY',
'MM-DD-YYYY',
'YYYY/MM/DD',
'DD/MM/YYYY',
'MM/DD/YYYY',
]
const checkFormat = format || 'YYYY-MM-DD';

if (!supportedFormats.includes(checkFormat)) {
throw new Error(`Configured format not supported ${checkFormat}`);
}

if (!dateCheck(value, checkFormat)) {
throw new Error(`Must Be A Date With Format ${checkFormat}`);
}
}
if (isBoolean) {
if (!_.isBoolean(value) && value.toLowerCase() !== "true" && value.toLowerCase() !== "false") {
if (value !== !!value && value.toLowerCase() !== "true" && value.toLowerCase() !== "false") {
throw new Error('Must Be A Boolean');
}
}
Expand Down Expand Up @@ -187,7 +245,8 @@ module.exports = (validation = [], response = {}) => {
return errorList;
}
const validateFields = (req, res, next) => {
const error = _.reject(_.flattenDeep(validation.map(validateObj => validate(validateObj, req))), _.isNil);
const isNull = val => val === null
const error = validation.map(validateObj => validate(validateObj, req)).flat(Infinity).filter(obj => obj);
if (error && error.length > 0) {

if (response.mode === 'forward') {
Expand Down
131 changes: 127 additions & 4 deletions lib/validator/validator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,11 +550,11 @@ describe('Test for body params', () => {
})
});

test('Test nested objects Success case - Date test', () => {
test('Test nested objects Success case - Date test Format defauly YYYY-MM-DD', () => {
const req = {
body: {
page: {
sorted: '2012-09-09'
sorted: '2012-09-19'
}
}
}
Expand All @@ -573,11 +573,11 @@ describe('Test for body params', () => {
expect(resp.send).toHaveBeenCalledTimes(0)
});

test('Test nested objects Success case - Date test - Format', () => {
test('Test nested objects Success case - Date test - Format DD-MM-YYYY', () => {
const req = {
body: {
page: {
sorted: '09-08-2019'
sorted: '19-08-2019'
}
}
}
Expand All @@ -596,6 +596,98 @@ describe('Test for body params', () => {
expect(resp.send).toHaveBeenCalledTimes(0)
});

test('Test nested objects Success case - Date test - Format MM-DD-YYYY', () => {
const req = {
body: {
page: {
sorted: '08-18-2019'
}
}
}
const validation = [
{param : 'page', location : 'body', isObject : true, children : [
{param : 'sorted', location : 'body.page', isRequired : true, isDate: true, format: 'MM-DD-YYYY' },
]}
]
const response = {
mode: 'reject'
}
const validatorfn = validaor(validation, response);
validatorfn(req, resp, next);
expect(next).toHaveBeenCalledTimes(1);
expect(resp.status).toHaveBeenCalledTimes(0);
expect(resp.send).toHaveBeenCalledTimes(0)
});

test('Test nested objects Success case - Date test - Format MM/DD/YYYY', () => {
const req = {
body: {
page: {
sorted: '12/18/2019'
}
}
}
const validation = [
{param : 'page', location : 'body', isObject : true, children : [
{param : 'sorted', location : 'body.page', isRequired : true, isDate: true, format: 'MM/DD/YYYY' },
]}
]
const response = {
mode: 'reject'
}
const validatorfn = validaor(validation, response);
validatorfn(req, resp, next);
expect(next).toHaveBeenCalledTimes(1);
expect(resp.status).toHaveBeenCalledTimes(0);
expect(resp.send).toHaveBeenCalledTimes(0)
});

test('Test nested objects Success case - Date test - Format DD/MM/YYYY', () => {
const req = {
body: {
page: {
sorted: '12/07/2019'
}
}
}
const validation = [
{param : 'page', location : 'body', isObject : true, children : [
{param : 'sorted', location : 'body.page', isRequired : true, isDate: true, format: 'DD/MM/YYYY' },
]}
]
const response = {
mode: 'reject'
}
const validatorfn = validaor(validation, response);
validatorfn(req, resp, next);
expect(next).toHaveBeenCalledTimes(1);
expect(resp.status).toHaveBeenCalledTimes(0);
expect(resp.send).toHaveBeenCalledTimes(0)
});

test('Test nested objects Success case - Date test - Format YYYY/MM/DD', () => {
const req = {
body: {
page: {
sorted: '2901/07/19'
}
}
}
const validation = [
{param : 'page', location : 'body', isObject : true, children : [
{param : 'sorted', location : 'body.page', isRequired : true, isDate: true, format: 'YYYY/MM/DD' },
]}
]
const response = {
mode: 'reject'
}
const validatorfn = validaor(validation, response);
validatorfn(req, resp, next);
expect(next).toHaveBeenCalledTimes(1);
expect(resp.status).toHaveBeenCalledTimes(0);
expect(resp.send).toHaveBeenCalledTimes(0)
});

test('Test nested objects Error case - Date test', () => {
const req = {
body: {
Expand Down Expand Up @@ -658,6 +750,37 @@ describe('Test for body params', () => {
})
});

test('Test nested objects Error case - Date test - Invalid Format', () => {
const req = {
body: {
page: {
sorted: '2019-23-02'
}
}
}
const validation = [
{param : 'page', location : 'body', isObject : true, children : [
{param : 'sorted', location : 'body.page', isRequired : true, isDate : true, format: 'YYYY/DD/MM' },
]}
]
const response = {
mode: 'reject'
}
const validatorfn = validaor(validation, response);
validatorfn(req, resp, next);
expect(next).toHaveBeenCalledTimes(0);
expect(resp.status).toHaveBeenCalledTimes(1);
expect(resp.send).toHaveBeenCalledWith({
error: [
{
location: 'body.page',
message: 'Invalid Field Error',
param: 'sorted',
}
]
})
});

test('Test nested objects Success case - Mobile number test', () => {
const req = {
body: {
Expand Down
32 changes: 11 additions & 21 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 6fdd98a

Please sign in to comment.