packages feed

jsons-to-schema-0.1.0.0: test/JSONSchema/Draft4/ComplexTypeTests.hs

{-# LANGUAGE QuasiQuotes #-}

module JSONSchema.Draft4.ComplexTypeTests where

import           JSONSchema.Draft4.SchemaGenerationConfig
import           NeatInterpolation
import           Protolude
import           Test.Hspec
import           TestUtils

tupleTypedArrayConfig :: SchemaGenerationConfig
tupleTypedArrayConfig =
  defaultSchemaGenerationConfig {typeArraysAsTuples = True}

sealedObjectPropertiesConfig :: SchemaGenerationConfig
sealedObjectPropertiesConfig =
  defaultSchemaGenerationConfig {sealObjectProperties = True}

testSingleEmptyObject :: Spec
testSingleEmptyObject =
  it "can generate the schema for a single empty object" $
  let j1 = [text| {} |]
      expected = [text| {"type": "object", "properties": {}} |]
  in testJsonsToSchema [j1] expected

testSingleBasicObject :: Spec
testSingleBasicObject =
  it "can generate the schema for a single basic object" $
  let j1 =
        [text| {
                      "Red Windsor": "Normally, but today the van broke down.",
                      "Stilton": "Sorry.",
                      "Gruyere": false
                    } |]
      expected =
        [text| {
                            "required": ["Gruyere", "Red Windsor", "Stilton"],
                            "type": "object",
                            "properties": {
                                "Red Windsor": {"type": "string"},
                                "Gruyere": {"type": "boolean"},
                                "Stilton": {"type": "string"}
                            }
                          } |]
  in testJsonsToSchema [j1] expected

testSingleBasicObjectSealingProperties :: Spec
testSingleBasicObjectSealingProperties =
  it
    "can generate the schema for a single basic object while sealing properties" $
  let j1 =
        [text| {
                      "Red Windsor": "Normally, but today the van broke down.",
                      "Stilton": "Sorry.",
                      "Gruyere": false
                    } |]
      expected =
        [text| {
                            "required": ["Gruyere", "Red Windsor", "Stilton"],
                            "type": "object",
                            "properties": {
                                "Red Windsor": {"type": "string"},
                                "Gruyere": {"type": "boolean"},
                                "Stilton": {"type": "string"}
                            },
                            "additionalProperties": false
                          } |]
  in testJsonsToSchemaWithConfig sealedObjectPropertiesConfig [j1] expected

testComplexArrayInObject :: Spec
testComplexArrayInObject =
  it "can generate the schema for arrays that are in objects" $
  let j1 = [text| {"a": "b", "c": [1, 2, 3]} |]
      expected =
        [text| {
                            "required": ["a", "c"],
                            "type": "object",
                            "properties": {
                                "a": {"type": "string"},
                                "c": {
                                    "type": "array",
                                    "items": {"type": "integer"}
                                }
                            }
                          }
                    |]
  in testJsonsToSchema [j1] expected

testComplexObjectInArray :: Spec
testComplexObjectInArray =
  it "can generate the schema for objects that are in arrays" $
  let j1 =
        [text| [
                      {"name": "Sir Lancelot of Camelot",
                       "quest": "to seek the Holy Grail",
                       "favorite colour": "blue"},
                      {"name": "Sir Robin of Camelot",
                       "quest": "to seek the Holy Grail",
                       "capitol of Assyria": null
                       }]
             |]
      expected =
        [text| {
                              "type": "array",
                              "items": {
                                  "type": "object",
                                  "required": ["name", "quest"],
                                  "properties": {
                                      "quest": {"type": "string"},
                                      "name": {"type": "string"},
                                      "favorite colour": {"type": "string"},
                                      "capitol of Assyria": {"type": "null"}
                                  }
                              }
                          }
                    |]
  in testJsonsToSchema [j1] expected

testComplexObjectInArraySealingProperties :: Spec
testComplexObjectInArraySealingProperties =
  it
    "can generate the schema for objects that are in arrays while sealing properties" $
  let j1 =
        [text| [
                      {"name": "Sir Lancelot of Camelot",
                       "quest": "to seek the Holy Grail",
                       "favorite colour": "blue"},
                      {"name": "Sir Robin of Camelot",
                       "quest": "to seek the Holy Grail",
                       "capitol of Assyria": null
                       }]
             |]
      expected =
        [text| {
                              "type": "array",
                              "items": {
                                  "type": "object",
                                  "required": ["name", "quest"],
                                  "properties": {
                                      "quest": {"type": "string"},
                                      "name": {"type": "string"},
                                      "favorite colour": {"type": "string"},
                                      "capitol of Assyria": {"type": "null"}
                                  },
                                  "additionalProperties": false
                              }
                          }
                    |]
  in testJsonsToSchemaWithConfig sealedObjectPropertiesConfig [j1] expected

testComplexThreeDeepObject :: Spec
testComplexThreeDeepObject =
  it "can generate the schema for a deeply nested object" $
  let j1 = [text| {"matryoshka": {"design": {"principle": "FTW!"}}} |]
      expected =
        [text| {
                            "type": "object",
                            "required": ["matryoshka"],
                            "properties": {
                                "matryoshka": {
                                    "type": "object",
                                    "required": ["design"],
                                    "properties": {
                                        "design": {
                                            "type": "object",
                                            "required": ["principle"],
                                            "properties": {
                                                "principle": {"type": "string"}
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    |]
  in testJsonsToSchema [j1] expected

testComplexThreeDeepObjectSealingProperties :: Spec
testComplexThreeDeepObjectSealingProperties =
  it
    "can generate the schema for a deeply nested object while sealing properties" $
  let j1 = [text| {"matryoshka": {"design": {"principle": "FTW!"}}} |]
      expected =
        [text| {
                            "type": "object",
                            "required": ["matryoshka"],
                            "properties": {
                                "matryoshka": {
                                    "type": "object",
                                    "required": ["design"],
                                    "properties": {
                                        "design": {
                                            "type": "object",
                                            "required": ["principle"],
                                            "properties": {
                                                "principle": {"type": "string"}
                                            },
                                            "additionalProperties": false
                                        }
                                    },
                                    "additionalProperties": false
                                }
                            },
                            "additionalProperties": false
                        }
                    |]
  in testJsonsToSchemaWithConfig sealedObjectPropertiesConfig [j1] expected

testMultipleEmptyObjects :: Spec
testMultipleEmptyObjects =
  it "can generate the schema for multiple empty objects" $
  let j1 = [text| {} |]
      j2 = [text| {} |]
      expected = [text| {"type": "object", "properties": {}} |]
  in testJsonsToSchema [j1, j2] expected

testEdgeCaseNestedSchema :: Spec
testEdgeCaseNestedSchema =
  it "can generate the schema for strangely nested objects" $
  let j1 =
        [text| [
                        [
                            null,
                            [
                                null
                            ]
                        ],
                        {},
                        {
                            "!": false
                        }
                    ] |]
      expected =
        [text|
          {
            "items": {
                "items": {
                    "items": {
                        "type": "null"
                    },
                    "type": [
                        "array",
                        "null"
                    ]
                },
                "type": [
                    "object",
                    "array"
                ],
                "properties": {
                    "!": {
                        "type": "boolean"
                    }
                }
            },
            "type": "array"
          }
         |]
  in testJsonsToSchemaPretty [j1] expected