content: module Test.Stan.Cli
      ( cliSpec
      ) where
  
  import Hedgehog (forAll, (===))
  import Options.Applicative (ParserResult (Success), execParserPure)
  import Test.Hspec (Spec, describe, it, shouldBe)
  import Test.Hspec.Hedgehog (hedgehog)
  import Trial (fiasco, trialToMaybe, withTag)
  
  import Stan.Cli (StanArgs (..), StanCommand (..), stanCliParser, stanParserPrefs)
  import Stan.Config (Check (..), CheckFilter (..), CheckType (..), Config, ConfigP (..),
                      PartialConfig, Scope (..), configToCliCommand, finaliseConfig)
  import Stan.Core.Id (Id (..))
  import Test.Stan.Gen (Property, genCheck, genConfig, genId, genScope)
  
  
  cliSpec :: Spec
  cliSpec = describe "CLI configuration tests" $ do
      it "execParserPure . configToCliCommand ≡ pure" cliConfigRoundtripProperty
      it "Converts Config to CLI command and parses it back" $
          case execParserPure stanParserPrefs stanCliParser (stanCommand configExample) of
              Success (Stan StanArgs{..}) -> stanArgsConfig `shouldBe` partialConfigExample
              _failure                    -> fail "Toml-To-CLI doesn't match the original config"
  
    where
      configExample :: Config
      configExample = ConfigP
          { configChecks = checks
          , configRemoved = []
          , configIgnored = []
          }
  
      partialConfigExample :: PartialConfig
      partialConfigExample = ConfigP
          { configChecks = withTag "CLI" $ pure checks
          , configRemoved = withTag "CLI" $ fiasco "No CLI option specified for: remove"
          , configIgnored = withTag "CLI" $ fiasco "No CLI option specified for: ignore"
          }
  
      checks :: [Check]
      checks =
          [ Check Exclude CheckAll (ScopeDirectory "test/")
          , Check Include CheckAll ScopeAll
          , Check Exclude (CheckInspection $ Id "STAN-0002") ScopeAll
          , Check
              Exclude
              (CheckInspection $ Id "STAN-0001")
              (ScopeFile "src/MyFile.hs")
          ]
  
  cliConfigRoundtripProperty :: Property
  cliConfigRoundtripProperty = hedgehog $ do
      check <- forAll genCheck
      scope <- forAll genScope
      obs   <- forAll genId
      -- we need to have a non-empty list as empty list is Fiasco for CLI.
      config <- forAll $ genConfig <&> \c -> c
          { configChecks  = check : configChecks c
          , configRemoved = scope : configRemoved c
          , configIgnored = obs : configIgnored c
          }
      case execParserPure stanParserPrefs stanCliParser (stanCommand config) of
          Success (Stan StanArgs{..}) ->
              trialToMaybe (finaliseConfig stanArgsConfig) === Just config
          _failure -> fail $ "Toml-To-CLI doesn't match the original config:\n"
              <> toString (configToCliCommand config)
  
  stanCommand :: Config -> [String]
  stanCommand = filter (/= "\\") . drop 1 . map toString . words . configToCliCommand
  