module Ribosome.Test.Unit where

import Control.Exception.Lifted (bracket_)
import Hedgehog (TestT)
import Hedgehog.Internal.Property (mkTestT, runTestT)
import System.FilePath (takeDirectory, takeFileName, (</>))
import System.Log ()
import System.Log.Logger (Priority(DEBUG, WARNING), setLevel, updateGlobalLogger)

import Ribosome.Control.Monad.Ribo (MonadRibo, NvimE, pluginName)
import Ribosome.Control.Ribosome (Ribosome)
import Ribosome.Error.Report.Class (ReportError)
import Ribosome.Plugin.RpcHandler (RpcHandler)
import Ribosome.Test.Embed (Runner, TestConfig(..), setupPluginEnv, unsafeEmbeddedSpecR)
import qualified Ribosome.Test.File as F (fixture, fixtureContent, tempDir)
import Ribosome.Test.Orphans ()

uPrefix :: Text
uPrefix :: Text
uPrefix = Text
"test"

uSpec :: (MonadIO m, NvimE e m) => Runner m
uSpec :: Runner m
uSpec TestConfig
conf m a
spec = do
  TestConfig -> m ()
forall (m :: * -> *) e.
(MonadIO m, NvimE e m) =>
TestConfig -> m ()
setupPluginEnv TestConfig
conf
  m a
spec

unitSpec ::
  MonadIO n =>
  MonadIO m =>
  NvimE e' n =>
  MonadFail m =>
  ReportError e =>
  MonadBaseControl IO m =>
  RpcHandler e (Ribosome env) n =>
  TestConfig ->
  env ->
  TestT n a ->
  TestT m a
unitSpec :: TestConfig -> env -> TestT n a -> TestT m a
unitSpec TestConfig
cfg env
env TestT n a
t = do
  m (Either Failure a, Journal) -> TestT m a
forall (m :: * -> *) a. m (Either Failure a, Journal) -> TestT m a
mkTestT (Runner n
-> TestConfig
-> env
-> n (Either Failure a, Journal)
-> m (Either Failure a, Journal)
forall (m :: * -> *) e env (n :: * -> *) a.
(MonadIO m, MonadFail m, ReportError e, MonadBaseControl IO m,
 RpcHandler e (Ribosome env) n) =>
Runner n -> TestConfig -> env -> n a -> m a
unsafeEmbeddedSpecR Runner n
forall (m :: * -> *) e. (MonadIO m, NvimE e m) => Runner m
uSpec TestConfig
cfg env
env (TestT n a -> n (Either Failure a, Journal)
forall (m :: * -> *) a. TestT m a -> m (Either Failure a, Journal)
runTestT TestT n a
t))

unitSpecDef ::
  MonadIO n =>
  MonadIO m =>
  NvimE e' n =>
  MonadFail m =>
  ReportError e =>
  MonadBaseControl IO m =>
  RpcHandler e (Ribosome env) n =>
  env ->
  TestT n a ->
  TestT m a
unitSpecDef :: env -> TestT n a -> TestT m a
unitSpecDef =
  TestConfig -> env -> TestT n a -> TestT m a
forall (n :: * -> *) (m :: * -> *) e' e env a.
(MonadIO n, MonadIO m, NvimE e' n, MonadFail m, ReportError e,
 MonadBaseControl IO m, RpcHandler e (Ribosome env) n) =>
TestConfig -> env -> TestT n a -> TestT m a
unitSpec TestConfig
forall a. Default a => a
def

unitSpecDef' ::
  MonadIO n =>
  MonadIO m =>
  NvimE e' n =>
  MonadFail m =>
  ReportError e =>
  MonadBaseControl IO m =>
  RpcHandler e (Ribosome ()) n =>
  TestT n a ->
  TestT m a
unitSpecDef' :: TestT n a -> TestT m a
unitSpecDef' =
  () -> TestT n a -> TestT m a
forall (n :: * -> *) (m :: * -> *) e' e env a.
(MonadIO n, MonadIO m, NvimE e' n, MonadFail m, ReportError e,
 MonadBaseControl IO m, RpcHandler e (Ribosome env) n) =>
env -> TestT n a -> TestT m a
unitSpecDef ()

tempDir :: MonadIO m => FilePath -> m FilePath
tempDir :: FilePath -> m FilePath
tempDir = Text -> FilePath -> m FilePath
forall (m :: * -> *). MonadIO m => Text -> FilePath -> m FilePath
F.tempDir Text
uPrefix

tempFile :: MonadIO m => FilePath -> m FilePath
tempFile :: FilePath -> m FilePath
tempFile FilePath
file = do
  FilePath
absDir <- FilePath -> m FilePath
forall (m :: * -> *). MonadIO m => FilePath -> m FilePath
tempDir (FilePath -> m FilePath) -> FilePath -> m FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> FilePath
takeDirectory FilePath
file
  return $ FilePath
absDir FilePath -> FilePath -> FilePath
</> FilePath -> FilePath
takeFileName FilePath
file

fixture :: MonadIO m => FilePath -> m FilePath
fixture :: FilePath -> m FilePath
fixture = Text -> FilePath -> m FilePath
forall (m :: * -> *). MonadIO m => Text -> FilePath -> m FilePath
F.fixture Text
uPrefix

fixtureContent :: MonadIO m => FilePath -> m Text
fixtureContent :: FilePath -> m Text
fixtureContent = Text -> FilePath -> m Text
forall (m :: * -> *). MonadIO m => Text -> FilePath -> m Text
F.fixtureContent Text
uPrefix

withLogAs ::
  MonadIO m =>
  MonadBaseControl IO m =>
  Text ->
  m a ->
  m a
withLogAs :: Text -> m a -> m a
withLogAs Text
name =
  m () -> m () -> m a -> m a
forall (m :: * -> *) a b c.
MonadBaseControl IO m =>
m a -> m b -> m c -> m c
bracket_ (Priority -> m ()
logLevel Priority
DEBUG) (Priority -> m ()
logLevel Priority
WARNING)
  where
    logLevel :: Priority -> m ()
logLevel =
      IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (Priority -> IO ()) -> Priority -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> (Logger -> Logger) -> IO ()
updateGlobalLogger (Text -> FilePath
forall a. ToString a => a -> FilePath
toString Text
name) ((Logger -> Logger) -> IO ())
-> (Priority -> Logger -> Logger) -> Priority -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Priority -> Logger -> Logger
setLevel

withLog ::
  MonadRibo m =>
  MonadBaseControl IO m =>
  m a ->
  m a
withLog :: m a -> m a
withLog m a
thunk =
  (Text -> m a -> m a
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
Text -> m a -> m a
`withLogAs` m a
thunk) (Text -> m a) -> m Text -> m a
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< m Text
forall (m :: * -> *). MonadRibo m => m Text
pluginName