    {-|
    Module      : Test.Tasty.Lua.Translate
    Copyright   : © 2019–2020 Albert Krewinkel
    License     : MIT
    Maintainer  : Albert Krewinkel <albert+hslua@zeitkraut.de>
    Stability   : alpha
    Portability : Requires GHC

    Translate test results from Lua into a Tasty @'TestTree'@.
    -}
    module Test.Tasty.Lua.Translate
      ( translateResultsFromFile
      , pathFailure
      )
    where

    import Foreign.Lua (Lua)
    import Test.Tasty.Lua.Core (Outcome (..), ResultTree (..), UnnamedTree (..),
                                runTastyFile)
    import qualified Test.Tasty as Tasty
    import qualified Test.Tasty.Providers as Tasty

    -- | Run tasty.lua tests from the given file and translate the result
    -- into a mock Tasty @'TestTree'@.
    translateResultsFromFile :: FilePath -> Lua Tasty.TestTree
    translateResultsFromFile :: FilePath -> Lua TestTree
    translateResultsFromFile fp :: FilePath
    fp = do
      Either FilePath [ResultTree]
    result <- FilePath -> Lua (Either FilePath [ResultTree])
    runTastyFile FilePath
    fp
      case Either FilePath [ResultTree]
    result of
        Left errMsg :: FilePath
    errMsg -> TestTree -> Lua TestTree
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TestTree -> Lua TestTree) -> TestTree -> Lua TestTree
    forall a b. (a -> b) -> a -> b
    $ FilePath -> FilePath -> TestTree
    pathFailure FilePath
    fp FilePath
    errMsg
        Right tree :: [ResultTree]
    tree  -> TestTree -> Lua TestTree
    forall (m :: * -> *) a. Monad m => a -> m a
    return (TestTree -> Lua TestTree) -> TestTree -> Lua TestTree
    forall a b. (a -> b) -> a -> b
    $ FilePath -> [TestTree] -> TestTree
    Tasty.testGroup FilePath
    fp ((ResultTree -> TestTree) -> [ResultTree] -> [TestTree]
    forall a b. (a -> b) -> [a] -> [b]
    map ResultTree -> TestTree
    testTree [ResultTree]
    tree)

    -- | Report failure of testing a path.
    pathFailure :: FilePath -> String -> Tasty.TestTree
    pathFailure :: FilePath -> FilePath -> TestTree
    pathFailure fp :: FilePath
    fp errMsg :: FilePath
    errMsg = FilePath -> MockTest -> TestTree
    forall t. IsTest t => FilePath -> t -> TestTree
    Tasty.singleTest FilePath
    fp (Outcome -> MockTest
    MockTest (FilePath -> Outcome
    Failure FilePath
    errMsg))

    -- | Convert internal (tasty.lua) result tree format into Tasty tree.
    testTree :: ResultTree -> Tasty.TestTree
    testTree :: ResultTree -> TestTree
    testTree (ResultTree name :: FilePath
    name tree :: UnnamedTree
    tree) =
      case UnnamedTree
    tree of
        SingleTest outcome :: Outcome
    outcome -> FilePath -> MockTest -> TestTree
    forall t. IsTest t => FilePath -> t -> TestTree
    Tasty.singleTest FilePath
    name (Outcome -> MockTest
    MockTest Outcome
    outcome)
        TestGroup results :: [ResultTree]
    results  -> FilePath -> [TestTree] -> TestTree
    Tasty.testGroup FilePath
    name ((ResultTree -> TestTree) -> [ResultTree] -> [TestTree]
    forall a b. (a -> b) -> [a] -> [b]
    map ResultTree -> TestTree
    testTree [ResultTree]
    results)

    -- | Mock test which just returns the predetermined outcome. An
    -- @'Outcome'@ can be treated like a Tasty test, as it encodes all
    -- necessary information. Usually, calling @'run'@ would trigger the
    -- execution of the test, but in this case, the test has already been
    -- run when the Lua script was executed.
    newtype MockTest = MockTest Outcome

    instance Tasty.IsTest MockTest where
      run :: OptionSet -> MockTest -> (Progress -> IO ()) -> IO Result
    run _ (MockTest outcome :: Outcome
    outcome) _ = Result -> IO Result
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Result -> IO Result) -> Result -> IO Result
    forall a b. (a -> b) -> a -> b
    $ case Outcome
    outcome of
        Success     -> FilePath -> Result
    Tasty.testPassed ""
        Failure msg :: FilePath
    msg -> FilePath -> Result
    Tasty.testFailed FilePath
    msg

      testOptions :: Tagged MockTest [OptionDescription]
    testOptions = [OptionDescription] -> Tagged MockTest [OptionDescription]
    forall (m :: * -> *) a. Monad m => a -> m a
    return []