From 61ac09d548584aa2a15e9ad8bb1973a00e44343f Mon Sep 17 00:00:00 2001 From: Nuno Sousa Date: Mon, 4 Jul 2016 16:44:31 +0100 Subject: [PATCH 1/4] Add optional format to `NullOrDate` assert --- README.md | 8 +++++- src/asserts/null-or-date-assert.js | 35 ++++++++++++++++++++++- test/asserts/null-or-date-assert_test.js | 36 ++++++++++++++++++++++-- 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1a87e31..5436913 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ The following set of extra asserts are provided by this package: - [Iso3166Country](#iso3166country) (requires `isoc`) - [Json](#json) - [NotEmpty](#notempty) -- [NullOrDate](#nullordate) +- [NullOrDate](#nullordate) (requires `moment` for format validation only) - [NullOrString](#nullorstring) - [Phone](#phone) (requires `google-libphonenumber`) - [PlainObject](#plainobject) @@ -152,6 +152,12 @@ Tests if the value is valid json. ### NotEmpty Tests if the value is not an empty (empty object, empty array, empty string, etc). +### NullOrDate +Tests if the value is `null` or a valid date. + +#### Arguments +- `format` (optional) - the format in which the date must be in. + ### NullOrString Tests if the value is a `null` or `string`, optionally within some boundaries. diff --git a/src/asserts/null-or-date-assert.js b/src/asserts/null-or-date-assert.js index 43db5ec..d91cc11 100644 --- a/src/asserts/null-or-date-assert.js +++ b/src/asserts/null-or-date-assert.js @@ -4,18 +4,43 @@ */ import { Violation } from 'validator.js'; +import { isString } from 'lodash'; /** * Export `NullOrDateAssert`. */ -export default function nullOrDateAssert() { +export default function nullOrDateAssert({ format } = {}) { /** * Class name. */ this.__class__ = 'NullOrDate'; + /** + * Optional peer dependency. + */ + + let moment; + + /** + * Validate format. + */ + + if (format) { + if (!isString(format)) { + throw new Error(`Unsupported format ${format} given`); + } + + moment = require('moment'); + } + + /** + * Format to match the input. + */ + + this.format = format; + /** * Validation algorithm. */ @@ -29,6 +54,14 @@ export default function nullOrDateAssert() { return true; } + if (this.format) { + if (!moment(value, this.format, true).isValid()) { + throw new Violation(this, value); + } + + return true; + } + if (isNaN(Date.parse(value)) === true) { throw new Violation(this, value); } diff --git a/test/asserts/null-or-date-assert_test.js b/test/asserts/null-or-date-assert_test.js index ea2780b..e748a16 100644 --- a/test/asserts/null-or-date-assert_test.js +++ b/test/asserts/null-or-date-assert_test.js @@ -35,14 +35,40 @@ describe('NullOrDateAssert', () => { }); }); - it('should throw an error if the input value is not a valid date', () => { + it('should throw an error if an invalid format is given', () => { + const formats = [[], {}, 123]; + + formats.forEach(format => { + try { + new Assert().NullOrDate({ format }).validate(); + + should.fail(); + } catch (e) { + e.should.be.instanceOf(Error); + e.message.should.equal(`Unsupported format ${format} given`); + } + }); + }); + + it('should throw an error if value is not correctly formatted', () => { try { - new Assert().NullOrDate().validate('2015-99-01'); + new Assert().NullOrDate({ format: 'YYYY-MM-DD' }).validate('20003112'); should.fail(); } catch (e) { e.should.be.instanceOf(Violation); - e.show().value.should.equal('2015-99-01'); + e.show().assert.should.equal('NullOrDate'); + } + }); + + it('should throw an error if value does not pass strict validation', () => { + try { + new Assert().NullOrDate({ format: 'YYYY-MM-DD' }).validate('2000.12.30'); + + should.fail(); + } catch (e) { + e.should.be.instanceOf(Violation); + e.show().assert.should.equal('NullOrDate'); } }); @@ -64,6 +90,10 @@ describe('NullOrDateAssert', () => { new Assert().NullOrDate().validate(new Date()); }); + it('should accept a correctly formatted date', () => { + new Assert().NullOrDate({ format: 'MM/YYYY' }).validate('12/2000'); + }); + it('should accept a string', () => { new Assert().NullOrDate().validate('2014-10-16'); }); From bfc1fb5e09b2845f1cc327be41223d6eac5434c4 Mon Sep 17 00:00:00 2001 From: Nuno Sousa Date: Mon, 4 Jul 2016 16:45:15 +0100 Subject: [PATCH 2/4] Improve README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5436913..67dc47f 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,7 @@ Tests if the value is `null` or a valid date. - `format` (optional) - the format in which the date must be in. ### NullOrString -Tests if the value is a `null` or `string`, optionally within some boundaries. +Tests if the value is `null` or a string, optionally within some boundaries. #### Arguments - `boundaries` (optional) - `max` and/or `min` boundaries to test the string for. From b2bb87fc73c4231a0a550582dda4f19796dfa5c4 Mon Sep 17 00:00:00 2001 From: Nuno Sousa Date: Mon, 4 Jul 2016 16:45:29 +0100 Subject: [PATCH 3/4] Fix moment format parsing in date assert --- src/asserts/date-assert.js | 10 +++++----- test/asserts/date-assert_test.js | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/asserts/date-assert.js b/src/asserts/date-assert.js index 97743ee..4c65eaa 100644 --- a/src/asserts/date-assert.js +++ b/src/asserts/date-assert.js @@ -50,15 +50,15 @@ export default function dateAssert({ format } = {}) { throw new Violation(this, value, { value: 'must_be_a_date_or_a_string' }); } - if (isNaN(Date.parse(value)) === true) { - throw new Violation(this, value); - } + if (this.format) { + if (!moment(value, this.format, true).isValid()) { + throw new Violation(this, value); + } - if (!this.format) { return true; } - if (!moment(value, this.format, true).isValid()) { + if (isNaN(Date.parse(value)) === true) { throw new Violation(this, value); } diff --git a/test/asserts/date-assert_test.js b/test/asserts/date-assert_test.js index 0ee7086..00b96a7 100644 --- a/test/asserts/date-assert_test.js +++ b/test/asserts/date-assert_test.js @@ -82,15 +82,15 @@ describe('DateAssert', () => { } }); - it('should accept a `Date`', () => { + it('should accept a date', () => { new Assert().Date().validate(new Date()); }); it('should accept a correctly formatted date', () => { - new Assert().Date({ format: 'YYYY-MM-DD' }).validate('2000-12-30'); + new Assert().Date({ format: 'MM/YYYY' }).validate('12/2000'); }); - it('should accept a `string`', () => { + it('should accept a string', () => { new Assert().Date().validate('2014-10-16'); }); }); From 9696f112357ca7a8333a6be3051c895f9e9acf13 Mon Sep 17 00:00:00 2001 From: Nuno Sousa Date: Mon, 4 Jul 2016 16:45:56 +0100 Subject: [PATCH 4/4] Improve date validation in date diff asserts --- src/asserts/date-diff-greater-than-assert.js | 2 +- src/asserts/date-diff-less-than-assert.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/asserts/date-diff-greater-than-assert.js b/src/asserts/date-diff-greater-than-assert.js index 2d3c0bd..9d515c0 100644 --- a/src/asserts/date-diff-greater-than-assert.js +++ b/src/asserts/date-diff-greater-than-assert.js @@ -57,7 +57,7 @@ export default function dateDiffGreaterThanAssert(threshold, options) { throw new Violation(this, value, { value: 'must_be_a_date_or_a_string' }); } - if (isNaN(Date.parse(value)) === true) { + if (!moment(value).isValid()) { throw new Violation(this, value, { absolute: this.absolute, asFloat: this.asFloat, fromDate: this.fromDate, threshold: this.threshold, unit: this.unit }); } diff --git a/src/asserts/date-diff-less-than-assert.js b/src/asserts/date-diff-less-than-assert.js index 533c002..2a42418 100644 --- a/src/asserts/date-diff-less-than-assert.js +++ b/src/asserts/date-diff-less-than-assert.js @@ -57,7 +57,7 @@ export default function dateDiffLessThanAssert(threshold, options) { throw new Violation(this, value, { value: 'must_be_a_date_or_a_string' }); } - if (isNaN(Date.parse(value)) === true) { + if (!moment(value).isValid()) { throw new Violation(this, value, { absolute: this.absolute, asFloat: this.asFloat, fromDate: this.fromDate, threshold: this.threshold, unit: this.unit }); }