aeson-schema-0.3.0.2: test/Data/Aeson/Schema/Examples.hs
{-# LANGUAGE QuasiQuotes #-}
module Data.Aeson.Schema.Examples
( examples
) where
import Data.Aeson (Value)
import Data.Aeson.LitQQ (aesonLitQQ)
import qualified Data.Map as M
import Data.Text (Text)
import Data.Aeson.Schema
examples :: (String -> IO () -> a)
-> (Graph Schema Text -> Schema Text -> Value -> IO ())
-> (Graph Schema Text -> Schema Text -> Value -> IO ())
-> [a]
examples testCase assertValid' assertInvalid' =
[ testCase "patternProperties" $ do
let schema = [schemaQQ| {
"type": "object",
"properties": {
"positiveNumber": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
}
},
"patternProperties": {
".+Number$": { "type": "integer" },
".+String$": { "type": "string" }
}
} |]
assertValid schema [aesonLitQQ| { "positiveNumber": 13 } |]
assertInvalid schema [aesonLitQQ| { "positiveNumber": -13 } |]
assertInvalid schema [aesonLitQQ| { "positiveNumber": 13.5 } |]
assertValid schema [aesonLitQQ| { "fooString": "foo", "barString": "bar" } |]
assertInvalid schema [aesonLitQQ| { "fooString": null, "barString": "bar" } |]
, testCase "additionalProperties" $ do
let additionalNumbers = [schemaQQ| {
"type": "object",
"properties": { "null": { "type": "null" } },
"patternProperties": {
".+String$": { "type": "string" }
},
"additionalProperties": { "type": "number" }
} |]
assertValid additionalNumbers [aesonLitQQ| {
"null": null,
"emptyString": "",
"oneMoreThing": 23,
"theLastThing": 999
} |]
assertInvalid additionalNumbers [aesonLitQQ| { "null": null, "notANumber": true } |]
let noAdditionalProperties = [schemaQQ| {
"type": "object",
"properties": { "null": { "type": "null" } },
"patternProperties": {
".+String$": { "type": "string" }
},
"additionalProperties": false
} |]
assertValid noAdditionalProperties [aesonLitQQ| { "null": null, "emptyString": "" } |]
assertInvalid noAdditionalProperties [aesonLitQQ| {
"null": null,
"emptyString": "",
"oneMoreThing": 23,
"theLastThing": 999
} |]
, testCase "disallow" $ do
let onlyFloats = [schemaQQ| { "type": "number", "disallow": "integer" } |]
assertInvalid onlyFloats [aesonLitQQ| 9 |]
assertValid onlyFloats [aesonLitQQ| 9.75 |]
let notLengthThree = [schemaQQ| {
"type": "array",
"disallow": [{
"type": "array",
"minItems": 3,
"maxItems": 3
}]
} |]
assertValid notLengthThree [aesonLitQQ| [] |]
assertValid notLengthThree [aesonLitQQ| [1] |]
assertValid notLengthThree [aesonLitQQ| [1, 2] |]
assertInvalid notLengthThree [aesonLitQQ| [1, 2, 3] |]
assertValid notLengthThree [aesonLitQQ| [1, 2, 3, 4] |]
let everythingExceptNumbers = [schemaQQ| { "disallow": "number" } |]
assertInvalid everythingExceptNumbers [aesonLitQQ| 3 |]
assertInvalid everythingExceptNumbers [aesonLitQQ| 3.5 |]
assertValid everythingExceptNumbers [aesonLitQQ| true |]
assertValid everythingExceptNumbers [aesonLitQQ| "nobody expects the ..." |]
assertValid everythingExceptNumbers [aesonLitQQ| { "eins": 1, "zwei": 2 } |]
assertValid everythingExceptNumbers [aesonLitQQ| ["eins", "zwei"] |]
assertValid everythingExceptNumbers [aesonLitQQ| null |]
, testCase "type: subschema" $ do
let schema = [schemaQQ| {
"type": [
{
"type": "object",
"properties": { "insert": { "type": "string", "minLength": 1 } },
"additionalProperties": false
},
{
"type": "object",
"properties": { "delete": { "type": "number", "minimum": 1 } },
"additionalProperties": false
},
{
"type": "object",
"properties": { "retain": { "type": "number", "minimum": 1 } },
"additionalProperties": false
}
]
} |]
assertValid schema [aesonLitQQ| { "insert": "lorem" } |]
assertInvalid schema [aesonLitQQ| { "insert": "lorem", "delete": 5 } |]
assertValid schema [aesonLitQQ| { "delete": 5 } |]
assertInvalid schema [aesonLitQQ| { "delete": 5, "retain": 76 } |]
assertValid schema [aesonLitQQ| { "retain": 76 } |]
, testCase "dependencies" $ do
let aRequiresB = [schemaQQ| {
"type": "object",
"dependencies": { "a": "b" }
} |]
assertValid aRequiresB [aesonLitQQ| {} |]
assertValid aRequiresB [aesonLitQQ| { "b": false } |]
assertValid aRequiresB [aesonLitQQ| { "a": true, "b": false } |]
assertInvalid aRequiresB [aesonLitQQ| { "a": 3 } |]
let aRequiresBToBeANumber = [schemaQQ| {
"type": "object",
"dependencies": { "a": { "properties": { "b": { "type": "number" } } } }
} |]
assertValid aRequiresBToBeANumber [aesonLitQQ| {} |]
assertValid aRequiresBToBeANumber [aesonLitQQ| { "b": "lorem" } |]
assertValid aRequiresBToBeANumber [aesonLitQQ| { "a": "yes, we can" } |]
assertInvalid aRequiresBToBeANumber [aesonLitQQ| { "a": "yes, we can", "b": "lorem" } |]
assertValid aRequiresBToBeANumber [aesonLitQQ| { "a": "hi there", "b": 42 } |]
let aDisallowsB = [schemaQQ| {
"type": "object",
"dependencies": {
"a": {
"disallow": [{
"properties": {
"b": { "type": "any", "required": true }
}
}]
}
}
} |]
assertValid aDisallowsB [aesonLitQQ| { "a": "lorem" } |]
assertValid aDisallowsB [aesonLitQQ| { "b": 42 } |]
assertInvalid aDisallowsB [aesonLitQQ| { "a": "lorem", "b": 42 } |]
, testCase "extends" $ do
let schema = [schemaQQ| {
"type": "object",
"properties": {
"a": { "type": "number" }
},
"extends": [
{
"properties": {
"a": { "required": true }
}
},
{
"patternProperties": {
"^[a-z]$": { "minimum": -3 }
}
}
]
} |]
assertValid schema [aesonLitQQ| { "a": 2 } |]
assertInvalid schema [aesonLitQQ| {} |]
assertInvalid schema [aesonLitQQ| { "a": -4 } |]
assertInvalid schema [aesonLitQQ| { "a": "foo" } |]
assertInvalid schema [aesonLitQQ| { "a": -1, "b": -10 } |]
assertValid schema [aesonLitQQ| { "a": -1, "ba": -10 } |]
, testCase "$ref" $ do
let
a = [schemaQQ| { "$ref": "b", "minimum": 3 } |]
b = [schemaQQ| { "type": "number", "maximum": 2 } |]
graph = M.fromList [("a", a), ("b", b)]
assertValid' graph a [aesonLitQQ| 1 |]
assertInvalid' graph a [aesonLitQQ| 4 |]
]
where
assertValid = assertValid' M.empty
assertInvalid = assertInvalid' M.empty