conferer-1.1.0.0: test/Conferer/ConfigSpec.hs
{-# LANGUAGE TypeApplications #-}
module Conferer.ConfigSpec where
import Test.Hspec
import Data.Text (Text)
import Data.Dynamic
import Conferer.Config
import Conferer.Source.InMemory
import Conferer.FromConfig.Internal (fromDynamics)
missingKey :: Key -> KeyLookupResult -> Bool
missingKey expectedKey (MissingKey k) = [expectedKey] == k
missingKey _ _ = False
foundInSources :: Key -> Text -> KeyLookupResult -> Bool
foundInSources expectedKey expected (FoundInSources k t) =
expected == t && expectedKey == k
foundInSources _keyExpected _expected _ =
False
foundInDefaults :: forall expected. (Eq expected, Typeable expected)
=> Key -> expected -> KeyLookupResult -> Bool
foundInDefaults expectedKey expected (FoundInDefaults k d) =
Just expected == fromDynamics @expected d && expectedKey == k
foundInDefaults _expctedKey _expected _ =
False
spec :: Spec
spec = do
describe "Config" $ do
let mkConfig keyMappings defaults content =
pure (emptyConfig
& addKeyMappings keyMappings
& addDefaults defaults)
>>= addSource (fromConfig content)
describe "#getKey" $ do
it "getting a non existent key returns missing key" $ do
c <- mkConfig [] [] []
res <- getKey "aaa" c
res `shouldSatisfy` missingKey "aaa"
it "getting a key only present in the defaults" $ do
c <- mkConfig [] [("some.key", toDyn @Int 1)] []
res <- getKey "some.key" c
res `shouldSatisfy` foundInDefaults "some.key" (1 :: Int)
context "with multiple sources and defaults" $ do
let mkConfig' defaults sourceWithPriority otherSource =
pure (emptyConfig
& addDefaults defaults)
>>= addSource (fromConfig sourceWithPriority)
>>= addSource (fromConfig otherSource)
it "getting an key returns unwraps the original map" $ do
c <- mkConfig' [] [] [("some.key", "1")]
res <- getKey "some.key" c
res `shouldSatisfy` foundInSources "some.key" "1"
it "getting an existent key returns in the bottom maps gets it" $ do
c <- mkConfig' [] [("some.key", "2")] [("some.key", "1")]
res <- getKey "some.key" c
res `shouldSatisfy` foundInSources "some.key" "2"
describe "with some key mapping" $ do
context "with basic one to one mapping" $
it "gets the value through a mapping" $ do
c <- mkConfig
[ ("something", "server") ]
[]
[ ("server", "aaa") ]
res <- getKey "something" c
res `shouldSatisfy` foundInSources "server" "aaa"
context "with a nested key mapping" $ do
it "goes through all the mappings and gets the right value" $ do
c <- mkConfig
[ ("something", "else")
, ("else", "server")
]
[]
[ ("server", "aaa")
]
res <- getKey "something" c
res `shouldSatisfy` foundInSources "server" "aaa"
context "with circular mappings" $ do
it "gets the first key" $ do
c <- mkConfig
[ ("a", "b")
, ("b", "a")
, ("b", "c")
]
[]
[ ("c", "aaa")
]
res <- getKey "a" c
res `shouldSatisfy` foundInSources "c" "aaa"
context "with nested key" $ do
it "maps the right upper key" $ do
c <- mkConfig
[ ("a", "b")
]
[]
[ ("b.k", "aaa")
]
res <- getKey "a.k" c
res `shouldSatisfy` foundInSources "b.k" "aaa"
context "with some defaults" $ do
it "maps and allows getting the default" $ do
c <- mkConfig
[ ("a", "b")
]
[ ("b", toDyn False)
]
[]
res <- getKey "a" c
res `shouldSatisfy` foundInDefaults "a" False
describe "#listSubkeys" $ do
it "return an empty list when nothing is configured" $ do
c <- mkConfig [] [] []
res <- listSubkeys "some" c
res `shouldBe` []
context "with some values in the config" $ do
it "when nothing is configured" $ do
c <- mkConfig [] [] [("some.key", "")]
res <- listSubkeys "some" c
res `shouldBe` ["some.key"]
context "with a config that has a value configured and \
\we get that same value" $ do
it "returns that key in the list of subkeys" $ do
c <- mkConfig [] [] [("some", "")]
res <- listSubkeys "some" c
res `shouldBe` []
context "with a config that has a value configured but \
\we get a different value" $ do
it "returns an empty list" $ do
c <- mkConfig [] [] [("some", "")]
res <- listSubkeys "other" c
res `shouldBe` []
context "with a config with defaults" $ do
it "returns those defaults in the list" $ do
c <- mkConfig [] [("some.key", toDyn @Int 7)] []
res <- listSubkeys "some" c
res `shouldBe` ["some.key"]
context "with configs in both defaults and sources" $ do
it "returns both results combined" $ do
c <- mkConfig [] [("some.key", toDyn @Int 7)] [("some.other", "")]
res <- listSubkeys "some" c
res `shouldBe` ["some.key", "some.other"]
context "mappings" $ do
context "with a simple mapping and a configured value" $ do
it "returns the keys that are present based on the mapping" $ do
c <- mkConfig
[ ("a", "b")
]
[]
[ ("b.k", "aaa")
]
res <- listSubkeys "a" c
res `shouldBe` ["a.k"]
context "with a multiple mappings and a configured value" $ do
it "returns the right keys" $ do
c <- mkConfig
[ ("a", "b")
, ("b", "c")
]
[]
[ ("c.k", "aaa")
]
res <- listSubkeys "a" c
res `shouldBe` ["a.k"]
context "with circular mappings" $ do
it "returns the right keys" $ do
c <- mkConfig
[ ("a", "b")
, ("b", "a")
]
[]
[ ("a.k", "aaa")
]
res <- listSubkeys "a" c
res `shouldBe` ["a.k"]
context "with reducing mappings" $ do
xit "returns the right keys" $ do
c <- mkConfig
[ ("a.k", "a")
]
[]
[ ("a.k", "aaa")
]
res <- listSubkeys "a" c
-- getKey "a.k.k" c >>= print
res `shouldBe` ["a.k", "a.k.k"]
it "keys that are present based on the mapping" $ do
c <- mkConfig
[ ("a", "b")
]
[ ("b.k", toDyn @String "aaa")
]
[ ]
res <- listSubkeys "a" c
res `shouldBe` ["a.k"]
describe "#addDefaults" $ do
context "with multiple defaults on the same key" $ do
it "the last one has more priority" $ do
let c = emptyConfig
& addDefaults
[ ("some.key", toDyn @Int 1)
, ("some.key", toDyn @Int 2)
]
res <- getKey "some.key" c
res `shouldSatisfy` foundInDefaults "some.key" (2 :: Int)