Skip to content

Commit 5c2f38d

Browse files
committed
test: make sure type specific keywords are applied properly
1 parent c46b9b2 commit 5c2f38d

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

test/unit/Test/Spec/JsonSchema/Validation.purs

Lines changed: 108 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import Data.Argonaut.Core (Json)
77
import Data.Argonaut.Core as A
88
import Data.Argonaut.Gen as AGen
99
import Data.Foldable (foldMap, traverse_)
10+
import Data.Int as Int
1011
import Data.List (List(..), (:))
1112
import Data.List as List
1213
import Data.Markdown (CodeBlockType(..), Document)
@@ -15,7 +16,10 @@ import Data.Maybe (Maybe(..))
1516
import Data.Set (Set)
1617
import Data.Set as Set
1718
import Data.String as String
18-
import JsonSchema (JsonSchema(..), JsonValueType(..))
19+
import Data.String.Gen as StringGen
20+
import Data.Tuple.Nested ((/\))
21+
import Foreign.Object as Object
22+
import JsonSchema (JsonSchema(..), JsonValueType(..), Keywords)
1923
import JsonSchema as Schema
2024
import JsonSchema.Codec.Printing as Printing
2125
import JsonSchema.Gen as SchemaGen
@@ -24,6 +28,7 @@ import JsonSchema.SchemaPath (SchemaPathSegment(..))
2428
import JsonSchema.Validation (Violation, ViolationReason(..))
2529
import JsonSchema.Validation as Validation
2630
import Test.QuickCheck (Result(..))
31+
import Test.QuickCheck.Gen (Gen)
2732
import Test.Spec (describe)
2833
import Test.Types (Example, TestLength(..), TestSpec)
2934
import Test.Utils (exampleTestCase, failWithDetails, generativeTestCase)
@@ -262,6 +267,71 @@ spec = describe "Validation" do
262267

263268
traverse_ exampleTestCase examples
264269

270+
keywordAppliesOnlyToProperty
271+
{ genNonApplicableJson: AGen.genJson `Gen.suchThat`
272+
(not A.isArray)
273+
, genValidApplicableJson: A.fromArray <$>
274+
(Gen.unfoldable $ pure A.jsonNull)
275+
, jsonDescription: "array"
276+
, keywordName: "items"
277+
, keywords:
278+
Schema.defaultKeywords
279+
{ items = Just $ ObjectSchema $
280+
Schema.defaultKeywords
281+
{ typeKeyword = Just $ Set.singleton JsonNull }
282+
}
283+
}
284+
285+
keywordAppliesOnlyToProperty
286+
{ genNonApplicableJson: AGen.genJson `Gen.suchThat`
287+
(not A.isNumber)
288+
, genValidApplicableJson: A.fromNumber <$> do
289+
i ← Gen.chooseInt (-1000) 1000
290+
pure $ Int.toNumber $ 2 * i
291+
, jsonDescription: "numeric"
292+
, keywordName: "multipleOf"
293+
, keywords: Schema.defaultKeywords { multipleOf = Just 2.0 }
294+
}
295+
296+
keywordAppliesOnlyToProperty
297+
{ genNonApplicableJson: AGen.genJson `Gen.suchThat`
298+
(not A.isObject)
299+
, genValidApplicableJson: do
300+
otherProperties ← Gen.unfoldable do
301+
propertyName ← StringGen.genAlphaString
302+
json ← AGen.genJson
303+
pure $ propertyName /\ json
304+
305+
requiredProperty ← do
306+
json ← AGen.genJson
307+
pure $ "requiredProperty" /\ json
308+
309+
pure
310+
$ A.fromObject
311+
$ Object.fromFoldable
312+
$ [ requiredProperty ] <> otherProperties
313+
, jsonDescription: "object"
314+
, keywordName: "required"
315+
, keywords:
316+
Schema.defaultKeywords
317+
{ required = Set.singleton "requiredProperty"
318+
}
319+
}
320+
321+
keywordAppliesOnlyToProperty
322+
{ genNonApplicableJson: AGen.genJson `Gen.suchThat`
323+
(not A.isArray)
324+
, genValidApplicableJson: pure $ A.fromArray [ A.jsonNull ]
325+
, jsonDescription: "array"
326+
, keywordName: "uniqueItems"
327+
, keywords:
328+
Schema.defaultKeywords
329+
{ items = Just
330+
$ ObjectSchema
331+
$ Schema.defaultKeywords { uniqueItems = true }
332+
}
333+
}
334+
265335
generativeTestCase Short
266336
"null type accepts only null JSON values"
267337
do
@@ -346,3 +416,40 @@ spec = describe "Validation" do
346416
$ Printing.printSchema originalSchema
347417
, originalSchemaViolations
348418
}
419+
420+
keywordAppliesOnlyToProperty
421+
{ genNonApplicableJson Gen Json
422+
, genValidApplicableJson Gen Json
423+
, jsonDescription String
424+
, keywordName String
425+
, keywords Keywords
426+
}
427+
TestSpec
428+
keywordAppliesOnlyToProperty spec =
429+
generativeTestCase Long
430+
( spec.keywordName
431+
<> " applies only to "
432+
<> spec.jsonDescription
433+
<>
434+
" JSON values"
435+
)
436+
do
437+
json ← Gen.choose
438+
spec.genNonApplicableJson
439+
spec.genValidApplicableJson
440+
441+
let
442+
schema = ObjectSchema spec.keywords
443+
violations = json `Validation.validateAgainst` schema
444+
445+
pure
446+
if Set.isEmpty violations then
447+
Success
448+
else
449+
failWithDetails
450+
( "validation has failed even though the only keyword was constraining only "
451+
<> spec.jsonDescription
452+
)
453+
{ json: A.stringify json
454+
, schema: A.stringify $ Printing.printSchema schema
455+
}

test/unit/Test/Utils.purs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ generativeTestCase testLength title property = do
2121
shouldRun ← liftEffect $ not <$> checkShouldSkip
2222
when
2323
shouldRun
24-
(it title (liftEffect $ quickCheckGen' iterations property))
24+
( it
25+
("Property: " <> title)
26+
(liftEffect $ quickCheckGen' iterations property)
27+
)
2528
where
2629
checkShouldSkip Effect Boolean
2730
checkShouldSkip = maybe false (_ == "true")

0 commit comments

Comments
 (0)