hq-json-0.1.1: test/HQ/Transformation/ASTSpec.hs
{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}
module HQ.Transformation.ASTSpec (spec) where
import Data.Aeson (Value (..))
import Data.Aeson.KeyMap qualified as KeyMap
import HQ.Transformation
import HQ.Transformation.AST
import HQ.Transformation.TransformationType
import Relude hiding (Compose, Const, and, isPrefixOf, length, not, or, reverse, subtract, xor)
import Test.Syd
spec :: Spec
spec = describe "HQ.Transformation.AST" $ do
describe "inferTransformationType" $ do
it "tags well-typed transformations" $ forM_ happyCases $ \(t, expected) ->
inferTransformationType t `shouldBe` Right expected
it "rejects ill-typed transformations" $ forM_ errorCases $ \(t, expected) ->
inferTransformationType t `shouldBe` Left expected
it "reports the failing composition in DSL syntax" $ do
case inferTransformationType (Compose (Add 1) (Equal (Number 3))) of
Left (InvalidCompose t _ _) -> show t `shouldBe` ("+1 . == 3" :: String)
Left err -> expectationFailure $ "wrong error: " <> show err
Right _ -> expectationFailure "expected an InvalidCompose"
it "renders and/xor precedence without redundant parens" $ do
show (Or (And (Equal (Number 1)) (Equal (Number 1))) (Equal (Number 3)))
`shouldBe` ("== 1 and == 1 or == 3" :: String)
show (And (Equal (Number 1)) (Or (Equal (Number 2)) (Equal (Number 3))))
`shouldBe` ("== 1 and (== 2 or == 3)" :: String)
show (Xor (And (Equal (Number 1)) (Equal (Number 2))) (Equal (Number 3)))
`shouldBe` ("== 1 and == 2 xor == 3" :: String)
happyCases :: [(Transformation, TransformationType)]
happyCases =
[ (Add 1, TransformationType ValueNumber ValueNumber),
(Lt 1, TransformationType ValueNumber ValueBool),
(Lte 1, TransformationType ValueNumber ValueBool),
(ConcatString " x", TransformationType ValueString ValueString),
(StripPrefix "pre", TransformationType ValueString ValueString),
(StripSuffix "suf", TransformationType ValueString ValueString),
(IsPrefixOf "pre", TransformationType ValueString ValueBool),
(IsSuffixOf "suf", TransformationType ValueString ValueBool),
(IsInfixOf "fix", TransformationType ValueString ValueBool),
(IsEmpty, TransformationType ValueArray ValueBool),
(ArrayLength, TransformationType ValueArray ValueNumber),
(ArrayReverse, TransformationType ValueArray ValueArray),
(ArrayUnique, TransformationType ValueArray ValueArray),
(ArraySort, TransformationType ValueArray ValueArray),
(Merge (KeyMap.fromList [("b", Number 1)]), TransformationType ValueObject ValueObject),
(DeepMerge (KeyMap.fromList [("b", Number 1)]), TransformationType ValueObject ValueObject),
(Const (Number 3), TransformationType ValueAny ValueNumber),
(Compose (Const (Number 3)) (Add 1), TransformationType ValueNumber ValueNumber),
(Compose (Add 1) (Const (Number 3)), TransformationType ValueAny ValueNumber),
(Compose (Add 1) (Multiply 2), TransformationType ValueNumber ValueNumber),
(Compose Not (Equal (Number 1)), TransformationType ValueAny ValueBool),
(Or (Equal (Number 1)) (Equal (Number 2)), TransformationType ValueAny ValueBool),
(And (Equal (Number 1)) (Equal (Number 1)), TransformationType ValueAny ValueBool),
(Xor (Equal (Number 1)) (Equal (Number 2)), TransformationType ValueAny ValueBool),
(Compose (Equal (Number 1)) Trim, TransformationType ValueString ValueBool),
(Compose IsEmpty ArrayReverse, TransformationType ValueArray ValueBool)
]
errorCases :: [(Transformation, TransformationTypeError)]
errorCases =
[ (Divide 0, InvalidDivideByZero (Divide 0)),
(Compose (Add 1) (Const (String "x")), InvalidCompose (Compose (Add 1) (Const (String "x"))) ValueString ValueNumber),
(Or (Add 1) (Equal (Number 2)), InvalidOr (Or (Add 1) (Equal (Number 2))) ValueNumber),
(Or (Equal (Number 1)) (Add 2), InvalidOr (Or (Equal (Number 1)) (Add 2)) ValueNumber),
(And (Add 1) (Equal (Number 2)), InvalidAnd (And (Add 1) (Equal (Number 2))) ValueNumber),
(Xor (Equal (Number 1)) (Add 2), InvalidXor (Xor (Equal (Number 1)) (Add 2)) ValueNumber),
(Compose (Add 1) (Equal (Number 3)), InvalidCompose (Compose (Add 1) (Equal (Number 3))) ValueBool ValueNumber),
(Compose (ConcatString " x") (Add 1), InvalidCompose (Compose (ConcatString " x") (Add 1)) ValueNumber ValueString),
(Compose (StripPrefix "a") ArrayLength, InvalidCompose (Compose (StripPrefix "a") ArrayLength) ValueNumber ValueString)
]