fix: resolve 'now' token in Joi.date().default() consistently with comparison rules - #3117
fix: resolve 'now' token in Joi.date().default() consistently with comparison rules#3117sapirbaruch wants to merge 4 commits into
Conversation
AbdelrahmanHafez
left a comment
There was a problem hiding this comment.
Would probably be nice to add some test to prevent regressions
AbdelrahmanHafez
left a comment
There was a problem hiding this comment.
One nitpick about an extra Date.now() in runtime, otherwise LGTM. Thanks 👍
| // treated in the min/max/greater/less rules. | ||
|
|
||
| if (value === 'now') { | ||
| return this.$_parent('default', () => new Date(Date.now()), options); |
There was a problem hiding this comment.
| return this.$_parent('default', () => new Date(Date.now()), options); | |
| return this.$_parent('default', () => new Date(), options); |
No reason to use Date.now() with new Date()
Edit: Turns out this is a workaround for testing, probably better to find a way to mock the constructor just for those tests that need it.
|
Hey @AbdelrahmanHafez — just pushed an update. The test suite now has 4 cases covering the default 'now' behavior (resolves to Date, doesn't touch non-undefined input, doesn't touch non-now string defaults, doesn't touch function defaults). All 1806 tests pass at 100% coverage. Regarding the overlap with #3122 — I noticed it opened after this one. Our approach is identical; happy to close this in favor of that PR if you'd prefer to keep things tidy, or to merge whichever you think is ready. |
|
Thanks @sapirbaruch. Just to clarify, I'm not a maintainer in this repo, there's a discussion in #3112 on whether or not this is the desired behavior. It's up to @Marsup to decide whether or not |
Ran into an unexpected inconsistency while using
Joi.date().default('now')— the'now'token that works as a dynamic "current time" reference in.min('now'),.max('now'),.greater('now'), and.less('now')is treated as a plain string literal when used as a default.The root cause: defaults are applied in
internals.finalizeafter coercion, and a string default is returned as-is byinternals.default. The comparison rules work around this by storing'now'as-is and resolving it dynamically at validation time, but the default path has no such special handling.The fix intercepts
default('now')in anoverrides.defaultmethod on the date type — the same pattern used bykeys.jsfordeepDefault— and converts it to a function() => new Date(). Sinceinternals.defaultalready calls function-typed defaults at validation time, this makes'now'resolve dynamically per-validation-call, consistent with the comparison rules.All 1802 existing tests pass.
Fixes #3112.