poppy-codegen-1.0.0: test/Poppy/Codegen/ValidateSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Poppy.Codegen.ValidateSpec
( validateSpec,
)
where
import Poppy.Codegen.IR
import qualified Poppy.Codegen.Schema as Builder
import Poppy.Codegen.Spec.Editor (editorSchema)
import Poppy.Codegen.Spec.Example (exampleSchema)
import Poppy.Codegen.Spec.Flag (flagSchema)
import Poppy.Codegen.Spec.Packet (packetSchema)
import Poppy.Codegen.Spec.Shelf (shelfSchema)
import Poppy.Codegen.Validate
import Test.Hspec
emptySchema :: [Model] -> Schema
emptySchema models =
Schema {schemaEnums = [], schemaModels = models, schemaUniques = []}
validateSpec :: Spec
validateSpec =
describe "Poppy.Codegen.Validate" $ do
describe "example specs" $ do
it "accepts the Shelf schema" $
validateSchema shelfSchema `shouldBe` []
it "accepts the canonical Example schema" $
validateSchema exampleSchema `shouldBe` []
it "accepts a Schema with a boolean field" $
validateSchema flagSchema `shouldBe` []
it "accepts a Schema with numeric and jsonb fields" $
validateSchema packetSchema `shouldBe` []
it "rejects a builder model with no primary key" $
validateSchema (Builder.schema [] [Builder.model "Widget" [text "name"] []] [])
`shouldBe` [ModelMissingPrimaryKey "Widget"]
describe "primary keys" $ do
it "rejects a model with no primary key" $ do
let schema =
emptySchema
[ Model
{ modelName = "Widget",
modelTable = "widget",
modelFields = [text "name"],
modelRelations = []
}
]
validateSchema schema
`shouldBe` [ModelMissingPrimaryKey "Widget"]
it "rejects a model with multiple primary keys" $ do
let schema =
emptySchema
[ Model
{ modelName = "Widget",
modelTable = "widget",
modelFields = [pk (uuid "id"), pk (uuid "otherId")],
modelRelations = []
}
]
validateSchema schema
`shouldBe` [ModelMultiplePrimaryKeys "Widget"]
describe "enums" $ do
it "rejects a field referencing an unknown enum" $ do
let schema =
emptySchema
[ Model
{ modelName = "Item",
modelTable = "item",
modelFields = [pk (uuid "id"), enumField "unit" "Unit"],
modelRelations = []
}
]
validateSchema schema
`shouldBe` [UnknownEnumType "Item" "unit" "Unit"]
it "rejects an enum with no variants" $ do
let schema =
Schema
{ schemaEnums = [enum_ "Unit" []],
schemaModels =
[ Model
{ modelName = "Item",
modelTable = "item",
modelFields = [pk (uuid "id")],
modelRelations = []
}
],
schemaUniques = []
}
validateSchema schema
`shouldBe` [EnumHasNoVariants "Unit"]
it "rejects duplicate enum variant names" $ do
let schema =
Schema
{ schemaEnums = [enum_ "Unit" [variant "G", variant "G"]],
schemaModels =
[ Model
{ modelName = "Item",
modelTable = "item",
modelFields = [pk (uuid "id")],
modelRelations = []
}
],
schemaUniques = []
}
validateSchema schema
`shouldBe` [DuplicateEnumVariant "Unit" "G"]
describe "relations" $ do
it "rejects a relation pointing at an unknown model" $ do
let schema =
emptySchema
[ Model
{ modelName = "Shelf",
modelTable = "test_shelf",
modelFields = [pk (uuid "id")],
modelRelations =
[ hasMany "shelfBooks" "Shelf" "Missing" "id" "shelfId"
]
}
]
validateSchema schema
`shouldBe` [UnknownRelationModel "shelfBooks" "to" "Missing"]
it "rejects a relation with an unknown field" $ do
let schema =
emptySchema
[ Model
{ modelName = "Shelf",
modelTable = "test_shelf",
modelFields = [pk (uuid "id")],
modelRelations =
[ hasMany "shelfBooks" "Shelf" "Book" "id" "shelfId"
]
},
Model
{ modelName = "Book",
modelTable = "test_book",
modelFields = [pk (uuid "id"), text "title"],
modelRelations = []
}
]
validateSchema schema
`shouldBe` [UnknownRelationField "shelfBooks" "Book" "shelfId"]
it "rejects a relation name used twice on one model" $ do
let schema =
Builder.schema
[]
[ Builder.model
"Author"
[pk (uuid "id"), text "name"]
[ Builder.hasMany "posts" "Post" "authorId",
Builder.hasMany "posts" "Post" "authorId"
],
Builder.model
"Post"
[pk (uuid "id"), uuid "authorId", text "title"]
[]
]
[]
validateSchema schema
`shouldBe` [ DuplicateRelationName "Author" "posts"
]
it "rejects a relation name equal to a scalar field" $ do
let schema =
Builder.schema
[]
[ Builder.model
"Author"
[pk (uuid "id"), text "name"]
[Builder.hasMany "name" "Post" "authorId"],
Builder.model
"Post"
[pk (uuid "id"), uuid "authorId"]
[]
]
[]
validateSchema schema
`shouldBe` [RelationNameClashesWithField "Author" "name"]
it "accepts two relations from one model to the same model" $ do
validateSchema editorSchema `shouldBe` []
describe "uniques" $ do
it "rejects a unique constraint on an unknown model" $ do
let schema =
emptySchema
[ Model
{ modelName = "Widget",
modelTable = "widget",
modelFields = [pk (uuid "id")],
modelRelations = []
}
]
drifted = schema {schemaUniques = [unique_ "Nope" ["id"]]}
validateSchema drifted
`shouldBe` [UnknownUniqueModel "Nope"]
it "rejects a unique constraint that references an unknown field" $ do
let schema =
emptySchema
[ Model
{ modelName = "Widget",
modelTable = "widget",
modelFields = [pk (uuid "id")],
modelRelations = []
}
]
drifted = schema {schemaUniques = [unique_ "Widget" ["name"]]}
validateSchema drifted
`shouldBe` [UnknownUniqueField "Widget" "name"]