opt-env-conf-test-0.0.0.2: test/OptEnvConf/HelpSpec.hs
{-# LANGUAGE ApplicativeDo #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
module OptEnvConf.HelpSpec (spec) where
import Control.Applicative
import Data.GenValidity.Aeson ()
import Data.Text (Text)
import qualified Data.Text as T
import Data.Version
import Data.Word
import OptEnvConf
import OptEnvConf.Args as Args
import OptEnvConf.Args.Gen ()
import OptEnvConf.EnvMap.Gen ()
import OptEnvConf.Error
import OptEnvConf.TestUtils
import Test.Syd
import Text.Colour
spec :: Spec
spec = do
-- Help parsing works at the top level
helpSpec
"toplevel-pure"
[]
-- Help parsing needs to work even if provided settings are invalid
helpSpec
"toplevel-pure-with-invalid-port"
["--port", "notaport"]
helpSpec
"read"
["read"]
helpSpec
"create"
["create"]
helpSpec
"sub"
["sub"]
helpSpec
"sub-foo"
["sub", "foo"]
helpSpec
"sub-bar"
["sub", "bar"]
-- Help parsing needs to work if you type in the wrong command too.
helpSpec
"wrong-command"
["quux"]
data Instructions = Instructions !Settings !Dispatch
instance HasParser Instructions where
settingsParser =
withLocalYamlConfig $
Instructions
<$> settingsParser
<*> settingsParser
data Dispatch
= DispatchRead
| DispatchCreate !String
| DispatchWithSub !Sub
instance HasParser Dispatch where
settingsParser =
commands
[ command "read" "read command explanation" $ pure DispatchRead,
command "create" "create command explanation" $
DispatchCreate
<$> setting
[ help "The item to create",
reader str,
argument,
metavar "STR"
],
command "sub" "command with subcommand" $ DispatchWithSub <$> settingsParser
]
data Sub
= SubFoo
| SubBar
instance HasParser Sub where
settingsParser =
commands
[ command "foo" "foo explanation" $ pure SubFoo,
command "bar" "bar explanation" $ pure SubBar
]
data Settings = Settings
{ settingPort :: Word16,
settingLogLevel :: String,
settingPaymentSettings :: Maybe PaymentSettings
}
instance HasParser Settings where
settingsParser = do
settingPort <-
setting
[ help "port to serve requests on",
reader auto,
metavar "PORT",
name "port",
value 8080
]
settingLogLevel <-
setting
[ help "minimal severity of log messages",
reader str,
metavar "LOG_LEVEL",
name "log-level",
value "DEBUG"
]
settingPaymentSettings <- optional $ subSettings "payment"
pure Settings {..}
data PaymentSettings = PaymentSettings
{ paymentSetPublicKey :: String,
paymentSetSecretKey :: Text,
paymentSetCurrency :: Maybe String
}
instance HasParser PaymentSettings where
settingsParser = do
paymentSetPublicKey <-
setting
[ help "Public key",
reader str,
name "public-key",
metavar "PUBLIC_KEY"
]
paymentSetSecretKey <-
secretTextFileSetting
[ help "Secret key",
name "secret-key",
metavar "SECRET_KEY_FILE"
]
paymentSetCurrency <-
optional $
setting
[ help "Currency",
reader str,
name "currency",
metavar "CURRENCY"
]
pure PaymentSettings {..}
helpSpec :: String -> [String] -> Spec
helpSpec file args =
it (unwords ["this help page in the same way for args:", show args]) $ do
let version = makeVersion [0, 0, 0]
let argMap = Args.parseArgs args
let parser = settingsParser @Instructions
errOrDocs <- runHelpParser Nothing argMap parser
case errOrDocs of
Left err -> expectationFailure $ T.unpack $ renderChunksText With24BitColours $ renderErrors err
Right mCommandDoc -> do
let progname = "example"
pure $
pureGoldenChunksFile ("test_resources/help/" <> file <> ".txt") $
case mCommandDoc of
Nothing -> renderHelpPage progname version "example program description" (parserDocs parser)
Just (commandPath, commandDoc) -> renderCommandHelpPage progname commandPath commandDoc