Skip to content

Commit 8ecf2f1

Browse files
authored
Fix prop type checking (#64)
* #61 thows error if the prop value is not supported * Add FluentSchemaError
1 parent ec74ef0 commit 8ecf2f1

18 files changed

+271
-144
lines changed

src/ArraySchema.js

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use strict'
22
const { BaseSchema } = require('./BaseSchema')
3-
const { setAttribute, isFluentSchema } = require('./utils')
3+
const { setAttribute, isFluentSchema, FluentSchemaError } = require('./utils')
44

55
const initialState = {
66
// $schema: 'http://json-schema.org/draft-07/schema#',
@@ -47,7 +47,7 @@ const ArraySchema = ({ schema = initialState, ...options } = {}) => {
4747
items.filter(v => isFluentSchema(v)).length > 0
4848
)
4949
)
50-
throw new Error("'items' must be a S or an array of S")
50+
throw new FluentSchemaError("'items' must be a S or an array of S")
5151
if (Array.isArray(items)) {
5252
const values = items.map(v => {
5353
const { $schema, ...rest } = v.valueOf()
@@ -73,7 +73,9 @@ const ArraySchema = ({ schema = initialState, ...options } = {}) => {
7373

7474
additionalItems: items => {
7575
if (typeof items !== 'boolean' && !isFluentSchema(items))
76-
throw new Error("'additionalItems' must be a boolean or a S")
76+
throw new FluentSchemaError(
77+
"'additionalItems' must be a boolean or a S"
78+
)
7779
if (items === false) {
7880
return setAttribute({ schema, ...options }, [
7981
'additionalItems',
@@ -98,7 +100,8 @@ const ArraySchema = ({ schema = initialState, ...options } = {}) => {
98100
*/
99101

100102
contains: value => {
101-
if (!isFluentSchema(value)) throw new Error("'contains' must be a S")
103+
if (!isFluentSchema(value))
104+
throw new FluentSchemaError("'contains' must be a S")
102105
const {
103106
$schema,
104107
definitions,
@@ -125,7 +128,7 @@ const ArraySchema = ({ schema = initialState, ...options } = {}) => {
125128

126129
uniqueItems: boolean => {
127130
if (typeof boolean !== 'boolean')
128-
throw new Error("'uniqueItems' must be a boolean")
131+
throw new FluentSchemaError("'uniqueItems' must be a boolean")
129132
return setAttribute({ schema, ...options }, [
130133
'uniqueItems',
131134
boolean,
@@ -144,7 +147,7 @@ const ArraySchema = ({ schema = initialState, ...options } = {}) => {
144147

145148
minItems: min => {
146149
if (!Number.isInteger(min))
147-
throw new Error("'minItems' must be a integer")
150+
throw new FluentSchemaError("'minItems' must be a integer")
148151
return setAttribute({ schema, ...options }, ['minItems', min, 'array'])
149152
},
150153

@@ -159,7 +162,7 @@ const ArraySchema = ({ schema = initialState, ...options } = {}) => {
159162

160163
maxItems: max => {
161164
if (!Number.isInteger(max))
162-
throw new Error("'maxItems' must be a integer")
165+
throw new FluentSchemaError("'maxItems' must be a integer")
163166
return setAttribute({ schema, ...options }, ['maxItems', max, 'array'])
164167
},
165168
}

src/ArraySchema.test.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,8 @@ describe('ArraySchema', () => {
4848
})
4949
})
5050
it('invalid', () => {
51-
expect(() => ArraySchema().items('')).toThrow(
52-
"'items' must be a S or an array of S"
51+
expect(() => ArraySchema().items('')).toThrowError(
52+
new S.FluentSchemaError("'items' must be a S or an array of S")
5353
)
5454
})
5555
})
@@ -80,8 +80,8 @@ describe('ArraySchema', () => {
8080
})
8181
})
8282
it('invalid', () => {
83-
expect(() => ArraySchema().additionalItems('')).toThrow(
84-
"'additionalItems' must be a boolean or a S"
83+
expect(() => ArraySchema().additionalItems('')).toThrowError(
84+
new S.FluentSchemaError("'additionalItems' must be a boolean or a S")
8585
)
8686
})
8787
})
@@ -102,7 +102,7 @@ describe('ArraySchema', () => {
102102
ArraySchema()
103103
.contains('')
104104
.valueOf()
105-
).toThrow("'contains' must be a S")
105+
).toThrowError(new S.FluentSchemaError("'contains' must be a S"))
106106
})
107107
})
108108

@@ -122,7 +122,9 @@ describe('ArraySchema', () => {
122122
ArraySchema()
123123
.uniqueItems('invalid')
124124
.valueOf()
125-
).toThrow("'uniqueItems' must be a boolean")
125+
).toThrowError(
126+
new S.FluentSchemaError("'uniqueItems' must be a boolean")
127+
)
126128
})
127129
})
128130

@@ -142,7 +144,7 @@ describe('ArraySchema', () => {
142144
ArraySchema()
143145
.minItems('3')
144146
.valueOf()
145-
).toThrow("'minItems' must be a integer")
147+
).toThrowError(new S.FluentSchemaError("'minItems' must be a integer"))
146148
})
147149
})
148150

@@ -162,7 +164,7 @@ describe('ArraySchema', () => {
162164
ArraySchema()
163165
.maxItems('5')
164166
.valueOf()
165-
).toThrow("'maxItems' must be a integer")
167+
).toThrowError(new S.FluentSchemaError("'maxItems' must be a integer"))
166168
})
167169
})
168170

src/BaseSchema.js

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const {
99
setAttribute,
1010
setRaw,
1111
setComposeType,
12+
FluentSchemaError,
1213
FLUENT_SCHEMA,
1314
} = require('./utils')
1415

@@ -44,7 +45,7 @@ const BaseSchema = (
4445

4546
id: id => {
4647
if (!id)
47-
throw new Error(
48+
throw new FluentSchemaError(
4849
`id should not be an empty fragment <#> or an empty string <> (e.g. #myId)`
4950
)
5051
return setAttribute({ schema, ...options }, ['$id', id, 'any'])
@@ -90,7 +91,9 @@ const BaseSchema = (
9091

9192
examples: examples => {
9293
if (!Array.isArray(examples))
93-
throw new Error("'examples' must be an array e.g. ['1', 'one', 'foo']")
94+
throw new FluentSchemaError(
95+
"'examples' must be an array e.g. ['1', 'one', 'foo']"
96+
)
9497
return setAttribute({ schema, ...options }, ['examples', examples, 'any'])
9598
},
9699

@@ -115,7 +118,7 @@ const BaseSchema = (
115118

116119
enum: values => {
117120
if (!Array.isArray(values))
118-
throw new Error(
121+
throw new FluentSchemaError(
119122
"'enums' must be an array with at least an element e.g. ['1', 'one', 'foo']"
120123
)
121124
return setAttribute({ schema, ...options }, ['enum', values, 'any'])
@@ -197,7 +200,8 @@ const BaseSchema = (
197200
},
198201

199202
not: not => {
200-
if (!isFluentSchema(not)) throw new Error("'not' must be a BaseSchema")
203+
if (!isFluentSchema(not))
204+
throw new FluentSchemaError("'not' must be a BaseSchema")
201205
const notSchema = omit(not.valueOf(), ['$schema', 'definitions'])
202206

203207
return BaseSchema({
@@ -270,9 +274,9 @@ const BaseSchema = (
270274

271275
ifThen: (ifClause, thenClause) => {
272276
if (!isFluentSchema(ifClause))
273-
throw new Error("'ifClause' must be a BaseSchema")
277+
throw new FluentSchemaError("'ifClause' must be a BaseSchema")
274278
if (!isFluentSchema(thenClause))
275-
throw new Error("'thenClause' must be a BaseSchema")
279+
throw new FluentSchemaError("'thenClause' must be a BaseSchema")
276280

277281
const ifClauseSchema = omit(ifClause.valueOf(), [
278282
'$schema',
@@ -316,11 +320,11 @@ const BaseSchema = (
316320

317321
ifThenElse: (ifClause, thenClause, elseClause) => {
318322
if (!isFluentSchema(ifClause))
319-
throw new Error("'ifClause' must be a BaseSchema")
323+
throw new FluentSchemaError("'ifClause' must be a BaseSchema")
320324
if (!isFluentSchema(thenClause))
321-
throw new Error("'thenClause' must be a BaseSchema")
325+
throw new FluentSchemaError("'thenClause' must be a BaseSchema")
322326
if (!isFluentSchema(elseClause))
323-
throw new Error(
327+
throw new FluentSchemaError(
324328
"'elseClause' must be a BaseSchema or a false boolean value"
325329
)
326330
const ifClauseSchema = omit(ifClause.valueOf(), [

src/BaseSchema.test.js

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,10 @@ describe('BaseSchema', () => {
7171
it('invalid', () => {
7272
expect(() => {
7373
BaseSchema().id('')
74-
}).toThrow(
75-
'id should not be an empty fragment <#> or an empty string <> (e.g. #myId)'
74+
}).toThrowError(
75+
new S.FluentSchemaError(
76+
'id should not be an empty fragment <#> or an empty string <> (e.g. #myId)'
77+
)
7678
)
7779
})
7880
})
@@ -116,7 +118,11 @@ describe('BaseSchema', () => {
116118
BaseSchema()
117119
.examples(value)
118120
.valueOf().examples
119-
).toThrow("'examples' must be an array e.g. ['1', 'one', 'foo']")
121+
).toThrowError(
122+
new S.FluentSchemaError(
123+
"'examples' must be an array e.g. ['1', 'one', 'foo']"
124+
)
125+
)
120126
})
121127
})
122128

@@ -185,8 +191,10 @@ describe('BaseSchema', () => {
185191
BaseSchema()
186192
.enum(value)
187193
.valueOf().examples
188-
).toThrow(
189-
"'enums' must be an array with at least an element e.g. ['1', 'one', 'foo']"
194+
).toThrowError(
195+
new S.FluentSchemaError(
196+
"'enums' must be an array with at least an element e.g. ['1', 'one', 'foo']"
197+
)
190198
)
191199
})
192200
})
@@ -300,15 +308,19 @@ describe('BaseSchema', () => {
300308
it('not an array', () => {
301309
expect(() => {
302310
return BaseSchema().allOf('test')
303-
}).toThrow(
304-
"'allOf' must be a an array of FluentSchema rather than a 'string'"
311+
}).toThrowError(
312+
new S.FluentSchemaError(
313+
"'allOf' must be a an array of FluentSchema rather than a 'string'"
314+
)
305315
)
306316
})
307317
it('not an array of FluentSchema', () => {
308318
expect(() => {
309319
return BaseSchema().allOf(['test'])
310-
}).toThrow(
311-
"'allOf' must be a an array of FluentSchema rather than a 'object'"
320+
}).toThrowError(
321+
new S.FluentSchemaError(
322+
"'allOf' must be a an array of FluentSchema rather than a 'object'"
323+
)
312324
)
313325
})
314326
})
@@ -355,15 +367,19 @@ describe('BaseSchema', () => {
355367
it('not an array', () => {
356368
expect(() => {
357369
return BaseSchema().anyOf('test')
358-
}).toThrow(
359-
"'anyOf' must be a an array of FluentSchema rather than a 'string'"
370+
}).toThrowError(
371+
new S.FluentSchemaError(
372+
"'anyOf' must be a an array of FluentSchema rather than a 'string'"
373+
)
360374
)
361375
})
362376
it('not an array of FluentSchema', () => {
363377
expect(() => {
364378
return BaseSchema().anyOf(['test'])
365-
}).toThrow(
366-
"'anyOf' must be a an array of FluentSchema rather than a 'object'"
379+
}).toThrowError(
380+
new S.FluentSchemaError(
381+
"'anyOf' must be a an array of FluentSchema rather than a 'object'"
382+
)
367383
)
368384
})
369385
})
@@ -383,15 +399,19 @@ describe('BaseSchema', () => {
383399
it('not an array', () => {
384400
expect(() => {
385401
return BaseSchema().oneOf('test')
386-
}).toThrow(
387-
"'oneOf' must be a an array of FluentSchema rather than a 'string'"
402+
}).toThrowError(
403+
new S.FluentSchemaError(
404+
"'oneOf' must be a an array of FluentSchema rather than a 'string'"
405+
)
388406
)
389407
})
390408
it('not an array of FluentSchema', () => {
391409
expect(() => {
392410
return BaseSchema().oneOf(['test'])
393-
}).toThrow(
394-
"'oneOf' must be a an array of FluentSchema rather than a 'object'"
411+
}).toThrowError(
412+
new S.FluentSchemaError(
413+
"'oneOf' must be a an array of FluentSchema rather than a 'object'"
414+
)
395415
)
396416
})
397417
})
@@ -425,7 +445,7 @@ describe('BaseSchema', () => {
425445
it('invalid', () => {
426446
expect(() => {
427447
BaseSchema().not(undefined)
428-
}).toThrow("'not' must be a BaseSchema")
448+
}).toThrowError(new S.FluentSchemaError("'not' must be a BaseSchema"))
429449
})
430450
})
431451
})
@@ -480,12 +500,16 @@ describe('BaseSchema', () => {
480500
undefined,
481501
BaseSchema().description('A User desc')
482502
)
483-
}).toThrow("'ifClause' must be a BaseSchema")
503+
}).toThrowError(
504+
new S.FluentSchemaError("'ifClause' must be a BaseSchema")
505+
)
484506
})
485507
it('thenClause', () => {
486508
expect(() => {
487509
BaseSchema().ifThen(BaseSchema().id('id'), undefined)
488-
}).toThrow("'thenClause' must be a BaseSchema")
510+
}).toThrowError(
511+
new S.FluentSchemaError("'thenClause' must be a BaseSchema")
512+
)
489513
})
490514
})
491515
})
@@ -547,7 +571,9 @@ describe('BaseSchema', () => {
547571
BaseSchema().description('then'),
548572
BaseSchema().description('else')
549573
)
550-
}).toThrow("'ifClause' must be a BaseSchema")
574+
}).toThrowError(
575+
new S.FluentSchemaError("'ifClause' must be a BaseSchema")
576+
)
551577
})
552578
it('thenClause', () => {
553579
expect(() => {
@@ -556,7 +582,9 @@ describe('BaseSchema', () => {
556582
undefined,
557583
BaseSchema().description('else')
558584
)
559-
}).toThrow("'thenClause' must be a BaseSchema")
585+
}).toThrowError(
586+
new S.FluentSchemaError("'thenClause' must be a BaseSchema")
587+
)
560588
})
561589
it('elseClause', () => {
562590
expect(() => {
@@ -565,7 +593,11 @@ describe('BaseSchema', () => {
565593
BaseSchema().description('then'),
566594
undefined
567595
)
568-
}).toThrow("'elseClause' must be a BaseSchema")
596+
}).toThrowError(
597+
new S.FluentSchemaError(
598+
"'elseClause' must be a BaseSchema or a false boolean value"
599+
)
600+
)
569601
})
570602
})
571603
})

src/FluentSchema.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ export type JSONSchema =
5959
| BooleanSchema
6060
| NullSchema
6161

62+
export class FluentSchemaError extends Error {
63+
name: string
64+
}
65+
6266
export interface SchemaOptions {
6367
schema: object
6468
generateIds: boolean

0 commit comments

Comments
 (0)