{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} module Main (main) where import Control.Applicative import Data.Aeson.Commit import Data.Aeson.QQ import Data.Aeson.Types import Data.Text (Text) import Test.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 = hspec tests