packages feed

aeson-prefix-0.1.0.0: test/Spec.hs

{-# LANGUAGE OverloadedStrings #-}

import Test.Hspec

import Control.Monad.Reader (runReader)

import Data.Aeson
import Data.Aeson.Prefix
import Data.ByteString (ByteString)
import Data.Maybe (fromJust)
import Data.Text (Text)

defaultSeparator :: Separator
defaultSeparator = "."

defaultPrefix :: Text
defaultPrefix = "prefix"

optionsDefault :: Options
optionsDefault = Options False defaultSeparator Nothing

optionsPrefixArrays :: Options
optionsPrefixArrays = Options True defaultSeparator Nothing

optionsWithPrefix :: Options
optionsWithPrefix = Options False defaultSeparator (Just defaultPrefix)

optionsWithPrefixAndPrefixArrays :: Options
optionsWithPrefixAndPrefixArrays = Options True defaultSeparator (Just defaultPrefix)

decodeExample :: ByteString -> Value
decodeExample = fromJust . decodeStrict'

prefixTest :: Options -> ByteString -> ByteString -> Expectation
prefixTest opts input expected = (flip runReader opts . prefix) (decodeExample input) `shouldBe` decodeExample expected

allOptions :: [Options]
allOptions = [ optionsDefault
             , optionsPrefixArrays
             , optionsWithPrefix
             , optionsWithPrefixAndPrefixArrays
             ]

-- Test Inputs

inputSimple :: ByteString
inputSimple = "{ \"a\": 1 }"

inputOneLevel :: ByteString
inputOneLevel = "{ \"a\": { \"b\": 1, \"c\": 2 } }"

inputTwoLevel :: ByteString
inputTwoLevel = "{ \"a\": { \"b\": { \"d\": 1 }, \"c\": { \"e\": 2 } } }"

inputTopArray :: ByteString
inputTopArray = "[ { \"a\": { \"b\": 1 } }, { \"a\": { \"b\": 2 } } ]"

inputWithArrayOneLevel :: ByteString
inputWithArrayOneLevel = "{ \"a\": [ { \"b\": { \"c\": 1 } }, { \"b\": { \"c\": 2 } } ] }"

main :: IO ()
main = hspec $
  describe "Data.Aeson.Prefix" $
    describe "prefix" $ do
      it "doesn't change empty object" $
        mapM_ (\o -> prefixTest o "{}" "{}") allOptions
      it "doesn't change flat array" $ do
        let input = "[\"a\", \"b\"]"
        mapM_ (\o -> prefixTest o input input) allOptions
      describe "default options" $ do
        let shouldResultIn = prefixTest optionsDefault
        it "doesn't change simple object" $ 
          inputSimple `shouldResultIn` inputSimple
        it "works for one level prefixing" $ 
          inputOneLevel `shouldResultIn` "{ \"a\": { \"a.b\": 1, \"a.c\": 2 } }"
        it "works with two level prefixing" $ 
          inputTwoLevel `shouldResultIn` "{ \"a\": { \"a.b\": { \"a.b.d\": 1 }, \"a.c\": { \"a.c.e\": 2 } } }"
        it "works with top level array of one level prefixing" $
          inputTopArray `shouldResultIn` "[ { \"a\": { \"a.b\": 1 } }, { \"a\": { \"a.b\": 2 } } ]"
        it "works with array of one level prefixing" $ 
          inputWithArrayOneLevel `shouldResultIn` "{ \"a\": [ { \"b\": {\"b.c\": 1 } }, { \"b\": { \"b.c\": 2 } } ] }"
      describe "options with prefixArrays" $ do
        let shouldResultIn = prefixTest optionsPrefixArrays
        it "doesn't change simple object" $ 
          inputSimple `shouldResultIn` inputSimple
        it "works for one level prefixing" $ 
          inputOneLevel `shouldResultIn` "{ \"a\": { \"a.b\": 1, \"a.c\": 2 } }"
        it "works with two level prefixing" $ 
          inputTwoLevel `shouldResultIn` "{ \"a\": { \"a.b\": { \"a.b.d\": 1 }, \"a.c\": { \"a.c.e\": 2 } } }"
        it "works with top level array of one level prefixing" $
          inputTopArray `shouldResultIn` "[ { \"a\": { \"a.b\": 1 } }, { \"a\": { \"a.b\": 2 } } ]"
        it "works with array of one level prefixing" $ 
          inputWithArrayOneLevel `shouldResultIn` "{ \"a\": [ { \"a.b\": {\"a.b.c\": 1 } }, { \"a.b\": { \"a.b.c\": 2 } } ] }"
      describe "options with user defined prefix" $ do
        let shouldResultIn = prefixTest optionsWithPrefix
        it "doesn't change simple object" $ 
          inputSimple `shouldResultIn` "{ \"prefix.a\": 1 }"
        it "works for one level prefixing" $ 
          inputOneLevel `shouldResultIn` "{ \"prefix.a\": { \"prefix.a.b\": 1, \"prefix.a.c\": 2 } }"
        it "works with two level prefixing" $ 
          inputTwoLevel `shouldResultIn` "{ \"prefix.a\": { \"prefix.a.b\": { \"prefix.a.b.d\": 1 }, \"prefix.a.c\": { \"prefix.a.c.e\": 2 } } }"
        it "works with top level array of one level prefixing" $
          inputTopArray `shouldResultIn` "[ { \"a\": { \"a.b\": 1 } }, { \"a\": { \"a.b\": 2 } } ]"
        it "works with array of one level prefixing" $ 
          inputWithArrayOneLevel `shouldResultIn` "{ \"prefix.a\": [ { \"b\": {\"b.c\": 1 } }, { \"b\": { \"b.c\": 2 } } ] }"
      describe "options with prefixArrays and user defined prefix" $ do
        let shouldResultIn = prefixTest optionsWithPrefixAndPrefixArrays
        it "doesn't change simple object" $ 
          inputSimple `shouldResultIn` "{ \"prefix.a\": 1 }"
        it "works for one level prefixing" $ 
          inputOneLevel `shouldResultIn` "{ \"prefix.a\": { \"prefix.a.b\": 1, \"prefix.a.c\": 2 } }"
        it "works with two level prefixing" $ 
          inputTwoLevel `shouldResultIn` "{ \"prefix.a\": { \"prefix.a.b\": { \"prefix.a.b.d\": 1 }, \"prefix.a.c\": { \"prefix.a.c.e\": 2 } } }"
        it "works with top level array of one level prefixing" $
          inputTopArray `shouldResultIn` "[ { \"prefix.a\": { \"prefix.a.b\": 1 } }, { \"prefix.a\": { \"prefix.a.b\": 2 } } ]"
        it "works with array of one level prefixing" $ 
          inputWithArrayOneLevel `shouldResultIn` "{ \"prefix.a\": [ { \"prefix.a.b\": {\"prefix.a.b.c\": 1 } }, { \"prefix.a.b\": { \"prefix.a.b.c\": 2 } } ] }"