{-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE OverloadedStrings #-} module Main (main) where import Data.Aeson.QQ import Data.Aeson.Types import Data.Aeson.Commit import Control.Applicative import Data.Text (Text) import Test.Tasty import Test.Tasty.Hspec tests :: Spec tests = testParserWithCases pNested [ ( "fails" , [aesonQQ| {} |] , Left $ unlines [ "Error in $: No match," , "- key \"value\" not found" , "- key \"nested\" not found" ] ) , ( "succeeds unnested" , [aesonQQ| { value: "top" } |] , Right "top" ) , ( "succeeds and prefers nested" , [aesonQQ| { value: "top" , nested: { value: "nest" } } |] , Right "nest" ) , ( "fails on malformed nested" , [aesonQQ| { value: "top", nested: { foo: 9 } } |] , Left "Error in $.nested: key \"value\" not found" ) , ( "fails on nested type mismatch" , [aesonQQ| { value: "top", nested: 9 } |] , Left "Error in $.nested: parsing nestedObj failed, expected Object, but encountered Number" ) ] where pNested :: Value -> Parser Text pNested = withObject "topLevel" $ \o -> runCommit $ (o .:> "nested") (withObject "nestedObj" (.: "value")) <|> tryParser (o .: "value") testParserWithCases :: (Eq a, Show a) => (v -> Parser a) -> [(String, v, Either String a)] -> Spec testParserWithCases p = mapM_ ( \(name, v, result) -> it name (parseEither p v `shouldBe` result)) main :: IO () main = testSpecs tests >>= defaultMain . testGroup "aeson-commit"