packages feed

settei-0.1.0.0: test/Settei/ValueTest.hs

module Settei.ValueTest (tests) where

import Data.Text qualified as Text
import Settei
import Settei.Prelude
import Test.Tasty (TestTree, testGroup)
import Test.Tasty.HUnit (assertBool, testCase, (@?=))

tests :: TestTree
tests =
  testGroup
    "Settei.Value"
    [ testCase "text values decode" $
        decodeSetting publicText (RawText "hello") @?= Right "hello",
      testCase "textual booleans decode case-insensitively" $
        decodeSetting publicBoolean (RawText "TRUE") @?= Right True,
      testCase "bounded integral values decode" $
        decodeSetting publicInteger (RawText "42") @?= Right (42 :: Int),
      testCase "explicit enumerations decode" $
        decodeSetting environment (RawText "production") @?= Right Production,
      testCase "secret decoder failures omit rejected values" $ case decodeSetting secretText (RawText "supersecret") of
        Right _ -> fail "expected decoding to fail"
        Left failureValue ->
          assertBool
            "rendered failure leaked the rejected secret"
            (not (Text.isInfixOf "supersecret" (renderDecodeFailure failureValue)))
    ]

data Environment = Development | Production
  deriving stock (Generic, Eq, Show)

publicText :: Setting Text
publicText = publicSetting exampleKey "Example text" textDecoder

secretText :: Setting Bool
secretText = secretSetting exampleKey "Example secret" boolDecoder

publicBoolean :: Setting Bool
publicBoolean = publicSetting exampleKey "Example boolean" boolDecoder

publicInteger :: Setting Int
publicInteger = publicSetting exampleKey "Example integer" boundedIntegralDecoder

environment :: Setting Environment
environment =
  publicSetting
    exampleKey
    "Runtime environment"
    (enumDecoder [("development", Development), ("production", Production)])

exampleKey :: Key
exampleKey = validKey "example.value"

validKey :: Text -> Key
validKey value = either (error . show) id (parseKey value)