Skip to content

Commit 90a5e3d

Browse files
authored
[bug]: don't mutate options to validator (#119)
* don't mutate * dont mutate fo real * add some tests * fix test
1 parent ed2fbeb commit 90a5e3d

File tree

4 files changed

+96
-30
lines changed

4 files changed

+96
-30
lines changed

addon/date.js

+37-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { set } from '@ember/object';
21
import validationError from 'ember-validators/utils/validation-error';
32

43
/**
@@ -45,42 +44,58 @@ export default function validateDate(value, options) {
4544
}
4645

4746
if (before) {
48-
before = parseAsDate(before, format, locale);
49-
50-
if (!isBefore(date, before)) {
51-
set(options, 'before', parseDateError(before, errorFormat, locale));
52-
return validationError('before', value, options);
47+
const beforeCompare = parseAsDate(before, format, locale);
48+
49+
if (!isBefore(date, beforeCompare)) {
50+
return validationError(
51+
'before',
52+
value,
53+
Object.assign({}, options, {
54+
before: parseDateError(beforeCompare, errorFormat, locale),
55+
})
56+
);
5357
}
5458
}
5559

5660
if (onOrBefore) {
57-
onOrBefore = parseAsDate(onOrBefore, format, locale);
61+
const onOrBeforeCompare = parseAsDate(onOrBefore, format, locale);
5862

59-
if (!isSameOrBefore(date, onOrBefore)) {
60-
set(
61-
options,
63+
if (!isSameOrBefore(date, onOrBeforeCompare)) {
64+
return validationError(
6265
'onOrBefore',
63-
parseDateError(onOrBefore, errorFormat, locale)
66+
value,
67+
Object.assign({}, options, {
68+
onOrBefore: parseDateError(onOrBeforeCompare, errorFormat, locale),
69+
})
6470
);
65-
return validationError('onOrBefore', value, options);
6671
}
6772
}
6873

6974
if (after) {
70-
after = parseAsDate(after, format, locale);
71-
72-
if (!isAfter(date, after)) {
73-
set(options, 'after', parseDateError(after, errorFormat, locale));
74-
return validationError('after', value, options);
75+
const afterCompare = parseAsDate(after, format, locale);
76+
77+
if (!isAfter(date, afterCompare)) {
78+
return validationError(
79+
'after',
80+
value,
81+
Object.assign({}, options, {
82+
after: parseDateError(afterCompare, errorFormat, locale),
83+
})
84+
);
7585
}
7686
}
7787

7888
if (onOrAfter) {
79-
onOrAfter = parseAsDate(onOrAfter, format, locale);
80-
81-
if (!isSameOrAfter(date, onOrAfter)) {
82-
set(options, 'onOrAfter', parseDateError(onOrAfter, errorFormat, locale));
83-
return validationError('onOrAfter', value, options);
89+
const onOrAfterCompare = parseAsDate(onOrAfter, format, locale);
90+
91+
if (!isSameOrAfter(date, onOrAfterCompare)) {
92+
return validationError(
93+
'onOrAfter',
94+
value,
95+
Object.assign({}, options, {
96+
onOrAfter: parseDateError(onOrAfterCompare, errorFormat, locale),
97+
})
98+
);
8499
}
85100
}
86101

addon/format.js

+12-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { isEmpty, isNone } from '@ember/utils';
22
import { assert } from '@ember/debug';
3-
import { set } from '@ember/object';
43

54
import Ember from 'ember';
65
import validationError from 'ember-validators/utils/validation-error';
@@ -44,27 +43,32 @@ export default function validateFormat(value, options, model, attribute) {
4443
!isEmpty(Object.keys(options))
4544
);
4645

46+
let regexTest = regex;
47+
4748
if (allowBlank && isEmpty(value)) {
4849
return true;
4950
}
5051

5152
if (type && !regex && regularExpressions[type]) {
52-
regex = regularExpressions[type];
53+
regexTest = regularExpressions[type];
5354
}
5455

5556
if (type === 'email') {
56-
if (regex === regularExpressions.email) {
57-
regex = formatEmailRegex(options);
57+
if (regexTest === regularExpressions.email) {
58+
regexTest = formatEmailRegex(options);
5859
}
59-
60-
set(options, 'regex', regex);
60+
Object.assign({}, options, { regex: regexTest });
6161
}
6262

6363
if (
6464
!canInvoke(value, 'match') ||
65-
(regex && isEmpty(value.match(regex)) !== inverse)
65+
(regexTest && isEmpty(value.match(regexTest)) !== inverse)
6666
) {
67-
return validationError(type || 'invalid', value, options);
67+
return validationError(
68+
type || 'invalid',
69+
value,
70+
Object.assign({}, options, { regex: regexTest })
71+
);
6872
}
6973

7074
return true;

tests/unit/validators/date-test.js

+34
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,40 @@ test('after now or on', function (assert) {
369369
assert.true(processResult(result));
370370
});
371371

372+
test("we don't mutate any option", function (assert) {
373+
const dateRef = new Date('1/1/2015');
374+
const onOrAfterOptions = {
375+
onOrAfter: dateRef,
376+
};
377+
const afterOptions = {
378+
after: dateRef,
379+
};
380+
const beforeOptions = {
381+
before: dateRef,
382+
};
383+
const onOrBeforeOptions = {
384+
onOrBefore: dateRef,
385+
};
386+
387+
validate('1/1/2020', afterOptions);
388+
validate('1/1/2020', onOrAfterOptions);
389+
validate('1/1/2010', beforeOptions);
390+
validate('1/1/2010', onOrBeforeOptions);
391+
392+
assert.strictEqual(afterOptions.after, dateRef, 'after option mutated');
393+
assert.strictEqual(
394+
onOrAfterOptions.onOrAfter,
395+
dateRef,
396+
'onOrAfter option mutated'
397+
);
398+
assert.strictEqual(beforeOptions.before, dateRef, 'before option mutated');
399+
assert.strictEqual(
400+
onOrBeforeOptions.onOrBefore,
401+
dateRef,
402+
'onOrBefore option mutated'
403+
);
404+
});
405+
372406
skip('after or on precision', function (assert) {
373407
let precisions = ['second', 'minute', 'hour', 'day', 'month', 'year'];
374408

tests/unit/validators/format-test.js

+13
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,16 @@ test('custom with g flag', function (assert) {
247247
result = validate('bar', options);
248248
assert.strictEqual(processResult(result), 'This field is invalid');
249249
});
250+
251+
test("we don't mutate any option", function (assert) {
252+
const type = 'email';
253+
254+
const options = {
255+
type,
256+
regex: 'hello!',
257+
};
258+
259+
validate('not an email', options);
260+
261+
assert.strictEqual(options.regex, 'hello!', 'regex option mutated');
262+
});

0 commit comments

Comments
 (0)