Skip to content

Commit 7fc8069

Browse files
vankopevilebottnawi
authored andcommitted
fix: support all cases with one number in range (#64)
1 parent 9cf11ad commit 7fc8069

File tree

6 files changed

+98
-52
lines changed

6 files changed

+98
-52
lines changed

src/ValidationError.js

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,51 @@ function getSchemaNonTypes(schema) {
247247
return '';
248248
}
249249

250+
function numberHints(schema) {
251+
const hints = [];
252+
const range = new Range();
253+
254+
if (typeof schema.minimum === 'number') {
255+
range.left(schema.minimum);
256+
}
257+
258+
if (typeof schema.exclusiveMinimum === 'number') {
259+
range.left(schema.exclusiveMinimum, true);
260+
}
261+
262+
if (typeof schema.maximum === 'number') {
263+
range.right(schema.maximum);
264+
}
265+
266+
if (typeof schema.exclusiveMaximum === 'number') {
267+
range.right(schema.exclusiveMaximum, true);
268+
}
269+
270+
const rangeFormat = range.format();
271+
272+
if (rangeFormat) {
273+
hints.push(rangeFormat);
274+
}
275+
276+
if (typeof schema.multipleOf === 'number') {
277+
hints.push(`should be multiple of ${schema.multipleOf}`);
278+
}
279+
280+
return hints;
281+
}
282+
283+
function formatHints(hints) {
284+
return hints.length > 0 ? `(${hints.join(', ')})` : '';
285+
}
286+
287+
function getHints(schema) {
288+
if (likeNumber(schema) || likeInteger(schema)) {
289+
return formatHints(numberHints(schema));
290+
}
291+
292+
return '';
293+
}
294+
250295
class ValidationError extends Error {
251296
constructor(errors, schema, configuration = {}) {
252297
super();
@@ -349,38 +394,10 @@ class ValidationError extends Error {
349394
}
350395

351396
if (likeNumber(schema) || likeInteger(schema)) {
352-
const hints = [];
353-
const range = new Range();
354-
355-
if (typeof schema.minimum === 'number') {
356-
range.left(schema.minimum);
357-
}
358-
359-
if (typeof schema.exclusiveMinimum === 'number') {
360-
range.left(schema.exclusiveMinimum, true);
361-
}
362-
363-
if (typeof schema.maximum === 'number') {
364-
range.right(schema.maximum);
365-
}
366-
367-
if (typeof schema.exclusiveMaximum === 'number') {
368-
range.right(schema.exclusiveMaximum, true);
369-
}
370-
371-
const rangeFormat = range.format();
372-
373-
if (rangeFormat) {
374-
hints.push(rangeFormat);
375-
}
376-
377-
if (typeof schema.multipleOf === 'number') {
378-
hints.push(`should be multiple of ${schema.multipleOf}`);
379-
}
380-
381397
const type = schema.type === 'integer' ? 'integer' : 'number';
398+
const hints = getHints(schema);
382399

383-
return `${type}${hints.length > 0 ? ` (${hints.join(', ')})` : ''}`;
400+
return `${type}${hints.length > 0 ? ` ${hints}` : ''}`;
384401
}
385402

386403
if (likeString(schema)) {
@@ -743,12 +760,19 @@ class ValidationError extends Error {
743760
case 'minimum':
744761
case 'maximum':
745762
case 'exclusiveMinimum':
746-
case 'exclusiveMaximum':
747-
return `${dataPath} should be ${error.params.comparison} ${
748-
error.params.limit
749-
}${getSchemaNonTypes(
763+
case 'exclusiveMaximum': {
764+
const hints = numberHints(error.parentSchema);
765+
766+
if (hints.length === 0) {
767+
hints.push(
768+
`should be ${error.params.comparison} ${error.params.limit}`
769+
);
770+
}
771+
772+
return `${dataPath} ${hints.join(' ')}${getSchemaNonTypes(
750773
error.parentSchema
751774
)}.${this.getSchemaPartDescription(error.parentSchema)}`;
775+
}
752776
case 'multipleOf':
753777
return `${dataPath} should be multiple of ${
754778
error.params.multipleOf

src/util/Range.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,16 +118,12 @@ class Range {
118118
return '';
119119
}
120120

121-
if (leftExclusive === rightExclusive) {
122-
// e.g. 5 <= x <= 5
123-
if (leftExclusive === false && start === end) {
124-
return `should be ${logic ? '' : '!'}= ${start}`;
125-
}
121+
const realStart = leftExclusive ? start + 1 : start;
122+
const realEnd = rightExclusive ? end - 1 : end;
126123

127-
// e.g. 4 < x < 6
128-
if (leftExclusive === true && start + 1 === end - 1) {
129-
return `should be ${logic ? '' : '!'}= ${start + 1}`;
130-
}
124+
// e.g. 5 < x < 7, 5 < x <= 6, 6 <= x <= 6
125+
if (realStart === realEnd) {
126+
return `should be ${logic ? '' : '!'}= ${realStart}`;
131127
}
132128

133129
// e.g. 4 < x < ∞

test/__snapshots__/index.test.js.snap

Lines changed: 14 additions & 9 deletions
Large diffs are not rendered by default.

test/fixtures/schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2925,6 +2925,11 @@
29252925
"minLength": 2
29262926
}
29272927
},
2928+
"integerEqualsTo5": {
2929+
"type": "integer",
2930+
"minimum": 5,
2931+
"exclusiveMaximum": 6
2932+
},
29282933
"integerWithMinimum": {
29292934
"type": "integer",
29302935
"minimum": 5,

test/index.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,14 @@ describe('Validation', () => {
16391639
(msg) => expect(msg).toMatchSnapshot()
16401640
);
16411641

1642+
createFailedTestCase(
1643+
'integer equals to 5',
1644+
{
1645+
integerEqualsTo5: 6,
1646+
},
1647+
(msg) => expect(msg).toMatchSnapshot()
1648+
);
1649+
16421650
createFailedTestCase(
16431651
'integer with minimum',
16441652
{

test/range.test.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@ it('not 5 <= x <= 5', () => {
1616
expect(range.format(false)).toEqual('should be != 5');
1717
});
1818

19+
it('5 < x <= 6', () => {
20+
const range = new Range();
21+
range.left(5, true);
22+
range.right(6);
23+
24+
expect(range.format()).toEqual('should be = 6');
25+
});
26+
1927
it('-1 < x < 1', () => {
2028
const range = new Range();
2129
range.left(-1, true);

0 commit comments

Comments
 (0)