From 0b5c9624635d7a9cf8f1084f99b1871951ef5e9e Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Thu, 28 Nov 2019 16:10:00 +0000 Subject: [PATCH 1/8] added date validator, Moment shim and basic testing --- addon/validators/date.js | 16 ++++++ package.json | 7 ++- tests/unit/validators/date-test.js | 21 +++++++ yarn.lock | 90 +++++++++++++++++++++--------- 4 files changed, 106 insertions(+), 28 deletions(-) create mode 100644 addon/validators/date.js create mode 100644 tests/unit/validators/date-test.js diff --git a/addon/validators/date.js b/addon/validators/date.js new file mode 100644 index 0000000..c25e720 --- /dev/null +++ b/addon/validators/date.js @@ -0,0 +1,16 @@ +import buildMessage from 'ember-changeset-validations/utils/validation-errors'; +import withDefaults from 'ember-changeset-validations/utils/with-defaults'; +import { validate } from 'ember-validators'; + +export default function validateNumber(options = {}) { + // options = withDefaults(options, { allowString: true, allowNone: false }); + + if (options.allowBlank) { + options.allowNone = true; + } + + return (key, value) => { + let result = validate('date', value, options, null, key); + return (result === true) ? true : buildMessage(key, result); + }; +} diff --git a/package.json b/package.json index 40598be..598277c 100644 --- a/package.json +++ b/package.json @@ -47,12 +47,12 @@ "ember-cli-blueprint-test-helpers": "^0.19.2", "ember-cli-dependency-checker": "^3.1.0", "ember-cli-eslint": "^5.1.0", - "ember-cli-htmlbars-inline-precompile": "^1.0.3", "ember-cli-inject-live-reload": "^2.0.1", + "ember-cli-moment-shim": "^3.7.1", "ember-cli-sri": "^2.1.1", "ember-cli-uglify": "^3.0.0", "ember-disable-prototype-extensions": "^1.1.3", - "ember-export-application-global": "^2.0.0", + "ember-export-application-global": "^2.0.1", "ember-load-initializers": "^2.1.0", "ember-maybe-import-regenerator": "^0.1.6", "ember-qunit": "^4.5.1", @@ -63,7 +63,8 @@ "eslint-plugin-ember": "^7.1.0", "eslint-plugin-node": "^10.0.0", "loader.js": "^4.7.0", - "mocha": "^5.0.0" + "mocha": "^5.0.0", + "moment": "^2.24.0" }, "engines": { "node": "8.* || >= 10.*" diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js new file mode 100644 index 0000000..3bb5407 --- /dev/null +++ b/tests/unit/validators/date-test.js @@ -0,0 +1,21 @@ +import validateDate from 'ember-changeset-validations/validators/date'; +import buildMessage from 'ember-changeset-validations/utils/validation-errors'; +import { module, test } from 'qunit'; + +module('Unit | Validator | date', function() { + test('it accepts an `allowBlank` option', function(assert) { + let key = 'birth_date'; + let options = { allowBlank: true }; + let validator = validateDate(options); + + assert.equal(validator(key, ''), true, 'empty string is allowed'); + assert.equal(validator(key, null), true, 'null is allowed'); + assert.equal(validator(key, undefined), true, 'undefined is allowed'); + assert.equal(validator(key, '1992-03-30'), true, 'date string is allowed'); + + assert.equal(validator(key, 'not a date'), buildMessage(key, { type: 'date', value: 'not a date', context: options }), + 'non-date string is not allowed'); + assert.equal(validator(key, NaN), buildMessage(key, { type: 'date', value: NaN, context: options }), + 'NaN is not allowed'); + }); +}); diff --git a/yarn.lock b/yarn.lock index 90dd977..559a7f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1678,11 +1678,6 @@ babel-plugin-filter-imports@^3.0.0: "@babel/types" "^7.4.0" lodash "^4.17.11" -babel-plugin-htmlbars-inline-precompile@^0.2.5: - version "0.2.6" - resolved "https://registry.yarnpkg.com/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-0.2.6.tgz#c00b8a3f4b32ca04bf0f0d5169fcef3b5a66d69d" - integrity sha512-H4H75TKGUFij8ukwEYWEERAgrUf16R8NSK1uDPe3QwxT8mnE1K8+/s6DVjUqbM5Pv6lSIcE4XufXdlSX+DTB6g== - babel-plugin-htmlbars-inline-precompile@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/babel-plugin-htmlbars-inline-precompile/-/babel-plugin-htmlbars-inline-precompile-1.0.0.tgz#a9d2f6eaad8a3f3d361602de593a8cbef8179c22" @@ -2376,7 +2371,7 @@ broccoli-config-replace@^1.1.2: debug "^2.2.0" fs-extra "^0.24.0" -broccoli-debug@^0.6.4, broccoli-debug@^0.6.5: +broccoli-debug@^0.6.1, broccoli-debug@^0.6.4, broccoli-debug@^0.6.5: version "0.6.5" resolved "https://registry.yarnpkg.com/broccoli-debug/-/broccoli-debug-0.6.5.tgz#164a5cdafd8936e525e702bf8f91f39d758e2e78" integrity sha512-RIVjHvNar9EMCLDW/FggxFRXqpjhncM/3qq87bn/y+/zR9tqEkHvTqbyOc4QnB97NO2m6342w4wGkemkaeOuWg== @@ -2668,6 +2663,26 @@ broccoli-sri-hash@^2.1.0: sri-toolbox "^0.2.0" symlink-or-copy "^1.0.1" +broccoli-stew@^1.5.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-1.6.0.tgz#01f6d92806ed6679ddbe48d405066a0e164dfbef" + integrity sha512-sUwCJNnYH4Na690By5xcEMAZqKgquUQnMAEuIiL3Z2k63mSw9Xg+7Ew4wCrFrMmXMcLpWjZDOm6Yqnq268N+ZQ== + dependencies: + broccoli-debug "^0.6.1" + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^2.0.0" + broccoli-persistent-filter "^1.1.6" + broccoli-plugin "^1.3.0" + chalk "^2.4.1" + debug "^3.1.0" + ensure-posix-path "^1.0.1" + fs-extra "^5.0.0" + minimatch "^3.0.4" + resolve "^1.8.1" + rsvp "^4.8.3" + symlink-or-copy "^1.2.0" + walk-sync "^0.3.0" + broccoli-stew@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/broccoli-stew/-/broccoli-stew-3.0.0.tgz#fd1d19d162ad9490b42e5c563b78c26eb1e80b95" @@ -3903,7 +3918,7 @@ ember-cli-babel-plugin-helpers@^1.0.0, ember-cli-babel-plugin-helpers@^1.1.0: resolved "https://registry.yarnpkg.com/ember-cli-babel-plugin-helpers/-/ember-cli-babel-plugin-helpers-1.1.0.tgz#de3baedd093163b6c2461f95964888c1676325ac" integrity sha512-Zr4my8Xn+CzO0gIuFNXji0eTRml5AxZUTDQz/wsNJ5AJAtyFWCY4QtKdoELNNbiCVGt1lq5yLiwTm4scGKu6xA== -ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.0.0-beta.7, ember-cli-babel@^6.16.0, ember-cli-babel@^6.3.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.9.2: +ember-cli-babel@^6.0.0-beta.4, ember-cli-babel@^6.16.0, ember-cli-babel@^6.3.0, ember-cli-babel@^6.6.0, ember-cli-babel@^6.8.1, ember-cli-babel@^6.9.2: version "6.18.0" resolved "https://registry.yarnpkg.com/ember-cli-babel/-/ember-cli-babel-6.18.0.tgz#3f6435fd275172edeff2b634ee7b29ce74318957" integrity sha512-7ceC8joNYxY2wES16iIBlbPSxwKDBhYwC8drU3ZEvuPDMwVv1KzxCNu1fvxyFEBWhwaRNTUxSCsEVoTd9nosGA== @@ -4000,17 +4015,6 @@ ember-cli-get-component-path-option@^1.0.0: resolved "https://registry.yarnpkg.com/ember-cli-get-component-path-option/-/ember-cli-get-component-path-option-1.0.0.tgz#0d7b595559e2f9050abed804f1d8eff1b08bc771" integrity sha1-DXtZVVni+QUKvtgE8djv8bCLx3E= -ember-cli-htmlbars-inline-precompile@^1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-1.0.5.tgz#312e050c9e3dd301c55fb399fd706296cd0b1d6a" - integrity sha512-/CNEqPxroIcbY6qejrt704ZaghHLCntZKYLizFfJ2esirXoJx6fuYKBY1YyJ8GOgjfbHHKjBZuK4vFFJpkGqkQ== - dependencies: - babel-plugin-htmlbars-inline-precompile "^0.2.5" - ember-cli-version-checker "^2.1.2" - hash-for-dep "^1.2.3" - heimdalljs-logger "^0.1.9" - silent-error "^1.1.0" - ember-cli-htmlbars-inline-precompile@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ember-cli-htmlbars-inline-precompile/-/ember-cli-htmlbars-inline-precompile-2.1.0.tgz#61b91ff1879d44ae504cadb46fb1f2604995ae08" @@ -4043,6 +4047,11 @@ ember-cli-htmlbars@^4.0.5: strip-bom "^4.0.0" walk-sync "^2.0.2" +ember-cli-import-polyfill@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ember-cli-import-polyfill/-/ember-cli-import-polyfill-0.2.0.tgz#c1a08a8affb45c97b675926272fe78cf4ca166f2" + integrity sha1-waCKiv+0XJe2dZJicv54z0yhZvI= + ember-cli-inject-live-reload@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ember-cli-inject-live-reload/-/ember-cli-inject-live-reload-2.0.2.tgz#95edb543b386239d35959e5ea9579f5382976ac7" @@ -4079,6 +4088,22 @@ ember-cli-lodash-subset@^2.0.1: resolved "https://registry.yarnpkg.com/ember-cli-lodash-subset/-/ember-cli-lodash-subset-2.0.1.tgz#20cb68a790fe0fde2488ddfd8efbb7df6fe766f2" integrity sha1-IMtop5D+D94kiN39jvu332/nZvI= +ember-cli-moment-shim@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/ember-cli-moment-shim/-/ember-cli-moment-shim-3.7.1.tgz#3ad691c5027c1f38a4890fe47d74b5224cc98e32" + integrity sha512-U3HHuEU7sXQ78v25ifmIa9w4nQPQ7vK/LZ2bt18pN3aKNvIDYiLe/MDeXGmqfFIq3OfruKG+CF+7dOLqxuzSlQ== + dependencies: + broccoli-funnel "^2.0.0" + broccoli-merge-trees "^2.0.0" + broccoli-source "^1.1.0" + broccoli-stew "^1.5.0" + chalk "^1.1.3" + ember-cli-babel "^6.6.0" + ember-cli-import-polyfill "^0.2.0" + lodash.defaults "^4.2.0" + moment "^2.19.3" + moment-timezone "^0.5.13" + ember-cli-normalize-entity-name@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/ember-cli-normalize-entity-name/-/ember-cli-normalize-entity-name-1.0.0.tgz#0b14f7bcbc599aa117b5fddc81e4fd03c4bad5b7" @@ -4265,12 +4290,10 @@ ember-disable-prototype-extensions@^1.1.3: resolved "https://registry.yarnpkg.com/ember-disable-prototype-extensions/-/ember-disable-prototype-extensions-1.1.3.tgz#1969135217654b5e278f9fe2d9d4e49b5720329e" integrity sha1-GWkTUhdlS14nj5/i2dTkm1cgMp4= -ember-export-application-global@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ember-export-application-global/-/ember-export-application-global-2.0.0.tgz#8d6d7619ac8a1a3f8c43003549eb21ebed685bd2" - integrity sha1-jW12GayKGj+MQwA1Sesh6+1oW9I= - dependencies: - ember-cli-babel "^6.0.0-beta.7" +ember-export-application-global@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ember-export-application-global/-/ember-export-application-global-2.0.1.tgz#b120a70e322ab208defc9e2daebe8d0dfc2dcd46" + integrity sha512-B7wiurPgsxsSGzJuPFkpBWnaeuCu2PGpG2BjyrfA1VcL7//o+5RSnZqiCEY326y7qmxb2GoCgo0ft03KBU0rRw== ember-get-config@^0.2.4: version "0.2.4" @@ -6740,6 +6763,11 @@ lodash.debounce@^3.1.1: dependencies: lodash._getnative "^3.0.0" +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + lodash.defaults@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-2.3.0.tgz#a832b001f138f3bb9721c2819a2a7cc5ae21ed25" @@ -7283,6 +7311,18 @@ mocha@^5.0.0: mkdirp "0.5.1" supports-color "5.4.0" +moment-timezone@^0.5.13: + version "0.5.27" + resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.27.tgz#73adec8139b6fe30452e78f210f27b1f346b8877" + integrity sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw== + dependencies: + moment ">= 2.9.0" + +"moment@>= 2.9.0", moment@^2.19.3, moment@^2.24.0: + version "2.24.0" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" + integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== + morgan@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.9.1.tgz#0a8d16734a1d9afbc824b99df87e738e58e2da59" @@ -8595,7 +8635,7 @@ rsvp@^3.0.14, rsvp@^3.0.17, rsvp@^3.0.18, rsvp@^3.0.21, rsvp@^3.0.6, rsvp@^3.1.0 resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-3.6.2.tgz#2e96491599a96cde1b515d5674a8f7a91452926a" integrity sha512-OfWGQTb9vnwRjwtA2QwpG2ICclHC3pgXZO5xt8H2EfgDquO0qVdSb5T88L4qJVAEugbS56pAuV4XZM58UX8ulw== -rsvp@^4.6.1, rsvp@^4.7.0, rsvp@^4.8.1, rsvp@^4.8.2, rsvp@^4.8.4, rsvp@^4.8.5: +rsvp@^4.6.1, rsvp@^4.7.0, rsvp@^4.8.1, rsvp@^4.8.2, rsvp@^4.8.3, rsvp@^4.8.4, rsvp@^4.8.5: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== From 186090218812049699b84002b95d61261b4b17a9 Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Fri, 29 Nov 2019 15:21:39 +0000 Subject: [PATCH 2/8] did date option testing --- README.md | 14 ++++++ addon/validators/date.js | 2 +- tests/unit/validators/date-test.js | 70 +++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e0fa84c..c5c5783 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,20 @@ Validates the length of a `String` or an `Array`. **[⬆️ back to top](#validator-api)** +#### `date` + +Validates various properties of a date. + +👉 [All Options](https://offirgolan.github.io/ember-validators/docs/classes/Date.html#method_validate) + +```js +{ + propertyName: validateDate({ before: '3000-01-01' }), // must be before 1st Jan. 3000 +} +``` + +**[⬆️ back to top](#validator-api)** + #### `number` Validates various properties of a number. diff --git a/addon/validators/date.js b/addon/validators/date.js index c25e720..b4f109e 100644 --- a/addon/validators/date.js +++ b/addon/validators/date.js @@ -3,7 +3,7 @@ import withDefaults from 'ember-changeset-validations/utils/with-defaults'; import { validate } from 'ember-validators'; export default function validateNumber(options = {}) { - // options = withDefaults(options, { allowString: true, allowNone: false }); + options = withDefaults(options, { allowBlank: false }); if (options.allowBlank) { options.allowNone = true; diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js index 3bb5407..0489907 100644 --- a/tests/unit/validators/date-test.js +++ b/tests/unit/validators/date-test.js @@ -1,21 +1,87 @@ +import moment from 'moment'; import validateDate from 'ember-changeset-validations/validators/date'; import buildMessage from 'ember-changeset-validations/utils/validation-errors'; import { module, test } from 'qunit'; +const inputFormat = "YYYY-MM-DD"; +const errorOutputFormat = "MMM Do, YYYY"; // Jan 1st, 1999 + module('Unit | Validator | date', function() { test('it accepts an `allowBlank` option', function(assert) { let key = 'birth_date'; let options = { allowBlank: true }; let validator = validateDate(options); - - assert.equal(validator(key, ''), true, 'empty string is allowed'); + assert.equal(validator(key, null), true, 'null is allowed'); assert.equal(validator(key, undefined), true, 'undefined is allowed'); + assert.equal(validator(key, 123), true, 'number value is is allowed'); // valid for momentjs ¯\_(ツ)_/¯ assert.equal(validator(key, '1992-03-30'), true, 'date string is allowed'); + assert.equal(validator(key, 'now'), true, '"now" value is is allowed'); assert.equal(validator(key, 'not a date'), buildMessage(key, { type: 'date', value: 'not a date', context: options }), 'non-date string is not allowed'); assert.equal(validator(key, NaN), buildMessage(key, { type: 'date', value: NaN, context: options }), 'NaN is not allowed'); + assert.equal(validator(key, {}), buildMessage(key, { type: 'date', value: {}, context: options }), + 'empty object is not allowed'); + }); + + test('it accepts empty strings, null & undefined', function(assert) { + const key = 'test_date'; + const options = {}; + const validator = validateDate(options); + + // assumes current moment + assert.equal(validator(key, ''), true, 'empty string is allowed'); + assert.equal(validator(key, null), true); + assert.equal(validator(key, undefined), true); + }); + + test('it accepts a `before` option', function(assert) { + const futureDate = '3000-01-01'; + const pastDate = '1900-01-01'; + + const key = 'test_date'; + const options = { before: futureDate }; + + let validator = validateDate(options); + + // Testing with before date in the future + assert.equal(validator(key, moment(futureDate).add(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'before', value: moment(futureDate).add(1, 'days').format(inputFormat), + context: {before: moment(options.before).format(errorOutputFormat)}, + }, 'date after the "before" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, futureDate), + buildMessage(key, { + type: 'before', value: futureDate, + context: {before: moment(options.before).format(errorOutputFormat)}, + }, 'date same as the "before" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, moment(futureDate).subtract(1, 'days').format(inputFormat)), true); + + + // Testing with before date in the past + options.before = pastDate; + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'before', value: moment(pastDate).add(1, 'days').format(inputFormat), + context: {before: moment(options.before).format(errorOutputFormat)}, + }, 'date after the "before" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, pastDate), + buildMessage(key, { + type: 'before', value: pastDate, + context: {before: moment(options.before).format(errorOutputFormat)}, + }, 'date same as the "before" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), true); + }); }); From 0d1d3a431af75663d7b7bffb45450b3260e1fa07 Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Mon, 2 Dec 2019 09:39:13 +0000 Subject: [PATCH 3/8] added onOrBefore date test --- README.md | 1 + addon/validators/date.js | 4 ---- tests/unit/validators/date-test.js | 37 ++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c5c5783..d4d36be 100644 --- a/README.md +++ b/README.md @@ -176,6 +176,7 @@ Validates various properties of a date. ```js { propertyName: validateDate({ before: '3000-01-01' }), // must be before 1st Jan. 3000 + propertyName: validateDate({ onOrBefore: '3000-01-01' }), // must be not after 1st Jan. 3000 } ``` diff --git a/addon/validators/date.js b/addon/validators/date.js index b4f109e..48e46b8 100644 --- a/addon/validators/date.js +++ b/addon/validators/date.js @@ -5,10 +5,6 @@ import { validate } from 'ember-validators'; export default function validateNumber(options = {}) { options = withDefaults(options, { allowBlank: false }); - if (options.allowBlank) { - options.allowNone = true; - } - return (key, value) => { let result = validate('date', value, options, null, key); return (result === true) ? true : buildMessage(key, result); diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js index 0489907..0e1df76 100644 --- a/tests/unit/validators/date-test.js +++ b/tests/unit/validators/date-test.js @@ -82,6 +82,43 @@ module('Unit | Validator | date', function() { ); validator = validateDate(options); assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), true); + }); + + test('it accepts a `onOrBefore` option', function(assert) { + const futureDate = '3000-01-01'; + const pastDate = '1900-01-01'; + + const key = 'test_date'; + const options = { onOrBefore: futureDate }; + + let validator = validateDate(options); + + // Testing with before date in the future + assert.equal(validator(key, moment(futureDate).add(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'onOrBefore', value: moment(futureDate).add(1, 'days').format(inputFormat), + context: {onOrBefore: moment(options.onOrBefore).format(errorOutputFormat)}, + }, 'date after the "onOrBefore" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, futureDate), true, 'date same as the "onOrBefore" date is allowed'); + validator = validateDate(options); + assert.equal(validator(key, moment(futureDate).subtract(1, 'days').format(inputFormat)), true); + + // Testing with before date in the past + options.onOrBefore = pastDate; + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'onOrBefore', value: moment(pastDate).add(1, 'days').format(inputFormat), + context: {onOrBefore: moment(options.onOrBefore).format(errorOutputFormat)}, + }, 'date after the "onOrBefore" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, pastDate), true, 'date same as the "onOrBefore" date is allowed'); + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), true); }); + }); From a34cccd988fcdedca2e493d5cddf8c8493ec767e Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Mon, 2 Dec 2019 09:46:22 +0000 Subject: [PATCH 4/8] added after and onOrAfter date tests --- README.md | 2 + tests/unit/validators/date-test.js | 86 +++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d4d36be..b8fd0ae 100644 --- a/README.md +++ b/README.md @@ -177,6 +177,8 @@ Validates various properties of a date. { propertyName: validateDate({ before: '3000-01-01' }), // must be before 1st Jan. 3000 propertyName: validateDate({ onOrBefore: '3000-01-01' }), // must be not after 1st Jan. 3000 + propertyName: validateDate({ after: '3000-01-01' }), // must be after 1st Jan. 3000 + propertyName: validateDate({ onOrAfter: '3000-01-01' }), // must be not before 1st Jan. 3000 } ``` diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js index 0e1df76..3c79ad1 100644 --- a/tests/unit/validators/date-test.js +++ b/tests/unit/validators/date-test.js @@ -84,7 +84,7 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), true); }); - test('it accepts a `onOrBefore` option', function(assert) { + test('it accepts an `onOrBefore` option', function(assert) { const futureDate = '3000-01-01'; const pastDate = '1900-01-01'; @@ -121,4 +121,88 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), true); }); + test('it accepts an `after` option', function(assert) { + const futureDate = '3000-01-01'; + const pastDate = '1900-01-01'; + + const key = 'test_date'; + const options = { after: futureDate }; + + let validator = validateDate(options); + + // Testing with after date in the future + assert.equal(validator(key, moment(futureDate).subtract(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'after', value: moment(futureDate).subtract(1, 'days').format(inputFormat), + context: {after: moment(options.after).format(errorOutputFormat)}, + }, 'date after the "after" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, futureDate), + buildMessage(key, { + type: 'after', value: futureDate, + context: {after: moment(options.after).format(errorOutputFormat)}, + }, 'date same as the "after" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, moment(futureDate).add(1, 'days').format(inputFormat)), true); + + + // Testing with after date in the past + options.after = pastDate; + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'after', value: moment(pastDate).subtract(1, 'days').format(inputFormat), + context: {after: moment(options.after).format(errorOutputFormat)}, + }, 'date after the "after" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, pastDate), + buildMessage(key, { + type: 'after', value: pastDate, + context: {after: moment(options.after).format(errorOutputFormat)}, + }, 'date same as the "after" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), true); + }); + + test('it accepts an `onOrAfter` option', function(assert) { + const futureDate = '3000-01-01'; + const pastDate = '1900-01-01'; + + const key = 'test_date'; + const options = { onOrAfter: futureDate }; + + let validator = validateDate(options); + + // Testing with after date in the future + assert.equal(validator(key, moment(futureDate).subtract(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'onOrAfter', value: moment(futureDate).subtract(1, 'days').format(inputFormat), + context: {onOrAfter: moment(options.onOrAfter).format(errorOutputFormat)}, + }, 'date after the "onOrAfter" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, futureDate), true, 'date same as the "onOrAfter" date is allowed'); + validator = validateDate(options); + assert.equal(validator(key, moment(futureDate).add(1, 'days').format(inputFormat)), true); + + + // Testing with after date in the past + options.onOrAfter = pastDate; + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), + buildMessage(key, { + type: 'onOrAfter', value: moment(pastDate).subtract(1, 'days').format(inputFormat), + context: {onOrAfter: moment(options.onOrAfter).format(errorOutputFormat)}, + }, 'date after the "onOrAfter" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, pastDate), true, 'date same as the "onOrAfter" date is allowed'); + validator = validateDate(options); + assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), true); + }); + }); From 0b018da09795e12024839cde6f55809a1a6e75c3 Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Mon, 2 Dec 2019 09:56:55 +0000 Subject: [PATCH 5/8] minor test structure change --- tests/unit/validators/date-test.js | 35 ++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js index 3c79ad1..f48e9f1 100644 --- a/tests/unit/validators/date-test.js +++ b/tests/unit/validators/date-test.js @@ -18,15 +18,18 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, '1992-03-30'), true, 'date string is allowed'); assert.equal(validator(key, 'now'), true, '"now" value is is allowed'); - assert.equal(validator(key, 'not a date'), buildMessage(key, { type: 'date', value: 'not a date', context: options }), - 'non-date string is not allowed'); - assert.equal(validator(key, NaN), buildMessage(key, { type: 'date', value: NaN, context: options }), - 'NaN is not allowed'); - assert.equal(validator(key, {}), buildMessage(key, { type: 'date', value: {}, context: options }), - 'empty object is not allowed'); + assert.equal(validator(key, 'not a date'), + buildMessage(key, { type: 'date', value: 'not a date', context: options }), 'non-date string is not allowed' + ); + assert.equal(validator(key, NaN), + buildMessage(key, { type: 'date', value: NaN, context: options }), 'NaN is not allowed' + ); + assert.equal(validator(key, {}), + buildMessage(key, { type: 'date', value: {}, context: options }), 'empty object is not allowed' + ); }); - test('it accepts empty strings, null & undefined', function(assert) { + test('it accepts valid values', function(assert) { const key = 'test_date'; const options = {}; const validator = validateDate(options); @@ -35,6 +38,24 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, ''), true, 'empty string is allowed'); assert.equal(validator(key, null), true); assert.equal(validator(key, undefined), true); + assert.equal(validator(key, '1992-03-30'), true, 'date string is allowed'); + assert.equal(validator(key, 'now'), true, '"now" value is is allowed'); + }); + + test('it rejectes invalid values', function(assert) { + const key = 'test_date'; + const options = {}; + const validator = validateDate(options); + + assert.equal(validator(key, 'not a date'), + buildMessage(key, { type: 'date', value: 'not a date', context: options }), 'non-date string is not allowed' + ); + assert.equal(validator(key, NaN), + buildMessage(key, { type: 'date', value: NaN, context: options }), 'NaN is not allowed' + ); + assert.equal(validator(key, {}), + buildMessage(key, { type: 'date', value: {}, context: options }), 'empty object is not allowed' + ); }); test('it accepts a `before` option', function(assert) { From d13307dcb115e2f614f768c99d61026ffedddad4 Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Mon, 2 Dec 2019 10:30:21 +0000 Subject: [PATCH 6/8] added date custom precision comparison test --- README.md | 1 + addon/validators/date.js | 6 +++++- tests/unit/validators/date-test.js | 20 ++++++++++++++++++-- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8fd0ae..d894e7a 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ Validates various properties of a date. propertyName: validateDate({ onOrBefore: '3000-01-01' }), // must be not after 1st Jan. 3000 propertyName: validateDate({ after: '3000-01-01' }), // must be after 1st Jan. 3000 propertyName: validateDate({ onOrAfter: '3000-01-01' }), // must be not before 1st Jan. 3000 + propertyName: validateDate({ precision: 'year', before: '1950-11-20' }), // must be no later than *1949* } ``` diff --git a/addon/validators/date.js b/addon/validators/date.js index 48e46b8..82c562d 100644 --- a/addon/validators/date.js +++ b/addon/validators/date.js @@ -2,11 +2,15 @@ import buildMessage from 'ember-changeset-validations/utils/validation-errors'; import withDefaults from 'ember-changeset-validations/utils/with-defaults'; import { validate } from 'ember-validators'; +const errorFormat = "MMM Do, YYYY"; + export default function validateNumber(options = {}) { - options = withDefaults(options, { allowBlank: false }); + options = withDefaults(options, { allowBlank: false, errorFormat: errorFormat}); return (key, value) => { let result = validate('date', value, options, null, key); return (result === true) ? true : buildMessage(key, result); }; } + +export {errorFormat}; diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js index f48e9f1..d21b9ce 100644 --- a/tests/unit/validators/date-test.js +++ b/tests/unit/validators/date-test.js @@ -1,10 +1,9 @@ import moment from 'moment'; -import validateDate from 'ember-changeset-validations/validators/date'; +import validateDate, {errorFormat as errorOutputFormat } from 'ember-changeset-validations/validators/date'; import buildMessage from 'ember-changeset-validations/utils/validation-errors'; import { module, test } from 'qunit'; const inputFormat = "YYYY-MM-DD"; -const errorOutputFormat = "MMM Do, YYYY"; // Jan 1st, 1999 module('Unit | Validator | date', function() { test('it accepts an `allowBlank` option', function(assert) { @@ -226,4 +225,21 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), true); }); + test('it accepts a `precision` option', function(assert) { + const beforeTarget = '1950-11-20'; + const key = 'test_date'; + const options = { before: beforeTarget, precision: 'year' }; + let validator = validateDate(options); + + validator = validateDate(options); + assert.equal(validator(key, moment(beforeTarget).subtract(1, 'month').format(inputFormat)), + buildMessage(key, { + type: 'before', value: beforeTarget, + context: {before: moment(options.before).format(errorOutputFormat)}, + }, 'date within the same year as the "before" date is not allowed') + ); + validator = validateDate(options); + assert.equal(validator(key, moment(beforeTarget).subtract(1, 'year').format(inputFormat)), true); + }); + }); From 09143251be7653fdd133d0fbf099047a0c75f26f Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Mon, 2 Dec 2019 10:55:38 +0000 Subject: [PATCH 7/8] added date format testing --- README.md | 1 + tests/unit/validators/date-test.js | 48 +++++++++++++++++++++--------- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 22e7bf5..3ef3ed5 100644 --- a/README.md +++ b/README.md @@ -180,6 +180,7 @@ Validates various properties of a date. propertyName: validateDate({ after: '3000-01-01' }), // must be after 1st Jan. 3000 propertyName: validateDate({ onOrAfter: '3000-01-01' }), // must be not before 1st Jan. 3000 propertyName: validateDate({ precision: 'year', before: '1950-11-20' }), // must be no later than *1949* + propertyName: validateDate({ format: 'MMM || Do || YYYY' }), // dates must be formatted like "Jan || 1st || 1999" } ``` diff --git a/tests/unit/validators/date-test.js b/tests/unit/validators/date-test.js index d21b9ce..a43564a 100644 --- a/tests/unit/validators/date-test.js +++ b/tests/unit/validators/date-test.js @@ -1,5 +1,5 @@ import moment from 'moment'; -import validateDate, {errorFormat as errorOutputFormat } from 'ember-changeset-validations/validators/date'; +import validateDate, { errorFormat as errorOutputFormat } from 'ember-changeset-validations/validators/date'; import buildMessage from 'ember-changeset-validations/utils/validation-errors'; import { module, test } from 'qunit'; @@ -70,14 +70,14 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(futureDate).add(1, 'days').format(inputFormat)), buildMessage(key, { type: 'before', value: moment(futureDate).add(1, 'days').format(inputFormat), - context: {before: moment(options.before).format(errorOutputFormat)}, + context: { before: moment(options.before).format(errorOutputFormat) }, }, 'date after the "before" date is not allowed') ); validator = validateDate(options); assert.equal(validator(key, futureDate), buildMessage(key, { type: 'before', value: futureDate, - context: {before: moment(options.before).format(errorOutputFormat)}, + context: { before: moment(options.before).format(errorOutputFormat) }, }, 'date same as the "before" date is not allowed') ); validator = validateDate(options); @@ -90,14 +90,14 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), buildMessage(key, { type: 'before', value: moment(pastDate).add(1, 'days').format(inputFormat), - context: {before: moment(options.before).format(errorOutputFormat)}, + context: { before: moment(options.before).format(errorOutputFormat) }, }, 'date after the "before" date is not allowed') ); validator = validateDate(options); assert.equal(validator(key, pastDate), buildMessage(key, { type: 'before', value: pastDate, - context: {before: moment(options.before).format(errorOutputFormat)}, + context: { before: moment(options.before).format(errorOutputFormat) }, }, 'date same as the "before" date is not allowed') ); validator = validateDate(options); @@ -117,7 +117,7 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(futureDate).add(1, 'days').format(inputFormat)), buildMessage(key, { type: 'onOrBefore', value: moment(futureDate).add(1, 'days').format(inputFormat), - context: {onOrBefore: moment(options.onOrBefore).format(errorOutputFormat)}, + context: { onOrBefore: moment(options.onOrBefore).format(errorOutputFormat) }, }, 'date after the "onOrBefore" date is not allowed') ); validator = validateDate(options); @@ -132,7 +132,7 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).add(1, 'days').format(inputFormat)), buildMessage(key, { type: 'onOrBefore', value: moment(pastDate).add(1, 'days').format(inputFormat), - context: {onOrBefore: moment(options.onOrBefore).format(errorOutputFormat)}, + context: { onOrBefore: moment(options.onOrBefore).format(errorOutputFormat) }, }, 'date after the "onOrBefore" date is not allowed') ); validator = validateDate(options); @@ -154,14 +154,14 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(futureDate).subtract(1, 'days').format(inputFormat)), buildMessage(key, { type: 'after', value: moment(futureDate).subtract(1, 'days').format(inputFormat), - context: {after: moment(options.after).format(errorOutputFormat)}, + context: { after: moment(options.after).format(errorOutputFormat) }, }, 'date after the "after" date is not allowed') ); validator = validateDate(options); assert.equal(validator(key, futureDate), buildMessage(key, { type: 'after', value: futureDate, - context: {after: moment(options.after).format(errorOutputFormat)}, + context: { after: moment(options.after).format(errorOutputFormat) }, }, 'date same as the "after" date is not allowed') ); validator = validateDate(options); @@ -174,14 +174,14 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), buildMessage(key, { type: 'after', value: moment(pastDate).subtract(1, 'days').format(inputFormat), - context: {after: moment(options.after).format(errorOutputFormat)}, + context: { after: moment(options.after).format(errorOutputFormat) }, }, 'date after the "after" date is not allowed') ); validator = validateDate(options); assert.equal(validator(key, pastDate), buildMessage(key, { type: 'after', value: pastDate, - context: {after: moment(options.after).format(errorOutputFormat)}, + context: { after: moment(options.after).format(errorOutputFormat) }, }, 'date same as the "after" date is not allowed') ); validator = validateDate(options); @@ -201,7 +201,7 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(futureDate).subtract(1, 'days').format(inputFormat)), buildMessage(key, { type: 'onOrAfter', value: moment(futureDate).subtract(1, 'days').format(inputFormat), - context: {onOrAfter: moment(options.onOrAfter).format(errorOutputFormat)}, + context: { onOrAfter: moment(options.onOrAfter).format(errorOutputFormat) }, }, 'date after the "onOrAfter" date is not allowed') ); validator = validateDate(options); @@ -216,7 +216,7 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(pastDate).subtract(1, 'days').format(inputFormat)), buildMessage(key, { type: 'onOrAfter', value: moment(pastDate).subtract(1, 'days').format(inputFormat), - context: {onOrAfter: moment(options.onOrAfter).format(errorOutputFormat)}, + context: { onOrAfter: moment(options.onOrAfter).format(errorOutputFormat) }, }, 'date after the "onOrAfter" date is not allowed') ); validator = validateDate(options); @@ -235,11 +235,31 @@ module('Unit | Validator | date', function() { assert.equal(validator(key, moment(beforeTarget).subtract(1, 'month').format(inputFormat)), buildMessage(key, { type: 'before', value: beforeTarget, - context: {before: moment(options.before).format(errorOutputFormat)}, + context: { before: moment(options.before).format(errorOutputFormat) }, }, 'date within the same year as the "before" date is not allowed') ); validator = validateDate(options); assert.equal(validator(key, moment(beforeTarget).subtract(1, 'year').format(inputFormat)), true); }); + test('it accepts a `format` option', function(assert) { + const key = 'test_date'; + const options = {}; + let validator = validateDate(options); + + options.format = 'YYYY' + validator = validateDate(options); + assert.equal(validator(key, '1-1-1999'), + buildMessage(key, { type: 'wrongDateFormat', value: '1-1-1999', context: options }), 'format should be just year' + ); + assert.equal(validator(key, '1999'), true); + + options.format = 'MMM || Do || YYYY' + validator = validateDate(options); + assert.equal(validator(key, '11-3-1998'), + buildMessage(key, { type: 'wrongDateFormat', value: '1-1-1999', context: options }), 'format should be "MMM || Do || YYYY"' + ); + assert.equal(validator(key, 'Nov || 3rd || 1998'), true); + }); + }); From 1837d9b95eee5ece83af42faef520d81c02aee53 Mon Sep 17 00:00:00 2001 From: jathanasiou Date: Tue, 3 Dec 2019 09:38:47 +0000 Subject: [PATCH 8/8] minor formatting --- addon/validators/date.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/addon/validators/date.js b/addon/validators/date.js index 82c562d..08c5769 100644 --- a/addon/validators/date.js +++ b/addon/validators/date.js @@ -5,7 +5,7 @@ import { validate } from 'ember-validators'; const errorFormat = "MMM Do, YYYY"; export default function validateNumber(options = {}) { - options = withDefaults(options, { allowBlank: false, errorFormat: errorFormat}); + options = withDefaults(options, { allowBlank: false, errorFormat: errorFormat }); return (key, value) => { let result = validate('date', value, options, null, key); @@ -13,4 +13,4 @@ export default function validateNumber(options = {}) { }; } -export {errorFormat}; +export { errorFormat };