-
-
Notifications
You must be signed in to change notification settings - Fork 100
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Date validator addition #208
Changes from 8 commits
0b5c962
1860902
0d1d3a4
a34cccd
0b018da
d13307d
598ef64
0914325
1837d9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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'; | ||
|
||
const errorFormat = "MMM Do, YYYY"; | ||
|
||
export default function validateNumber(options = {}) { | ||
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}; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
import moment from 'moment'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can/should avoid moment and use native JS functions or There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I used it in the unit tests since the dependency was needed anyway so might as well use the closest thing possible to the validator implementation. If ember-validators does remove There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the extremely simple cases ember-validators uses it for, it definitely should be optional and use the platform if so. This test would still be useful as the API would look like:
|
||
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"; | ||
|
||
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, 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 valid values', 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); | ||
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) { | ||
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); | ||
}); | ||
|
||
test('it accepts an `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); | ||
}); | ||
|
||
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); | ||
}); | ||
|
||
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); | ||
}); | ||
|
||
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); | ||
}); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wow. Phenomenal tests! |
||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... errorFormat: errorFormat }