module Test.Syd.Def.Scenario (scenarioDir, scenarioDirRecur) where

import Control.Monad
import Control.Monad.IO.Class
import Data.Maybe
import Path
import Path.IO
import qualified System.FilePath as FP
import Test.Syd.Def.Specify
import Test.Syd.Def.TestDefM

-- | Define a test for each file in the given directory.
--
-- Example:
--
-- >   scenarioDir "test_resources/even" $ \fp ->
-- >     it "contains an even number" $ do
-- >       s <- readFile fp
-- >       n <- readIO s
-- >       (n :: Int) `shouldSatisfy` even
scenarioDir :: FilePath -> (FilePath -> TestDefM outers inner ()) -> TestDefM outers inner ()
scenarioDir :: forall (outers :: [*]) inner.
FilePath
-> (FilePath -> TestDefM outers inner ())
-> TestDefM outers inner ()
scenarioDir = forall (outers :: [*]) inner.
(Path Abs Dir -> IO ([Path Rel Dir], [Path Rel File]))
-> FilePath
-> (FilePath -> TestDefM outers inner ())
-> TestDefM outers inner ()
scenarioDirHelper forall (m :: * -> *) b.
MonadIO m =>
Path b Dir -> m ([Path Rel Dir], [Path Rel File])
listDirRel

-- | Define a test for each file in the given directory, recursively.
--
-- Example:
--
-- >   scenarioDirRecur "test_resources/odd" $ \fp ->
-- >     it "contains an odd number" $ do
-- >       s <- readFile fp
-- >       n <- readIO s
-- >       (n :: Int) `shouldSatisfy` odd
scenarioDirRecur :: FilePath -> (FilePath -> TestDefM outers inner ()) -> TestDefM outers inner ()
scenarioDirRecur :: forall (outers :: [*]) inner.
FilePath
-> (FilePath -> TestDefM outers inner ())
-> TestDefM outers inner ()
scenarioDirRecur = forall (outers :: [*]) inner.
(Path Abs Dir -> IO ([Path Rel Dir], [Path Rel File]))
-> FilePath
-> (FilePath -> TestDefM outers inner ())
-> TestDefM outers inner ()
scenarioDirHelper forall (m :: * -> *) b.
MonadIO m =>
Path b Dir -> m ([Path Rel Dir], [Path Rel File])
listDirRecurRel

scenarioDirHelper ::
  (Path Abs Dir -> IO ([Path Rel Dir], [Path Rel File])) ->
  FilePath ->
  (FilePath -> TestDefM outers inner ()) ->
  TestDefM outers inner ()
scenarioDirHelper :: forall (outers :: [*]) inner.
(Path Abs Dir -> IO ([Path Rel Dir], [Path Rel File]))
-> FilePath
-> (FilePath -> TestDefM outers inner ())
-> TestDefM outers inner ()
scenarioDirHelper Path Abs Dir -> IO ([Path Rel Dir], [Path Rel File])
lister FilePath
dp FilePath -> TestDefM outers inner ()
func =
  forall (outers :: [*]) inner.
FilePath -> TestDefM outers inner () -> TestDefM outers inner ()
describe FilePath
dp forall a b. (a -> b) -> a -> b
$ do
    Path Abs Dir
ad <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *). MonadIO m => FilePath -> m (Path Abs Dir)
resolveDir' FilePath
dp
    [Path Rel File]
fs <- forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. a -> Maybe a -> a
fromMaybe []) forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(MonadIO m, MonadCatch m) =>
m a -> m (Maybe a)
forgivingAbsence forall a b. (a -> b) -> a -> b
$ forall a b. (a, b) -> b
snd forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Path Abs Dir -> IO ([Path Rel Dir], [Path Rel File])
lister Path Abs Dir
ad
    forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [Path Rel File]
fs forall a b. (a -> b) -> a -> b
$ \Path Rel File
rf -> do
      let fp :: FilePath
fp = FilePath
dp FilePath -> FilePath -> FilePath
FP.</> Path Rel File -> FilePath
fromRelFile Path Rel File
rf
      forall (outers :: [*]) inner.
FilePath -> TestDefM outers inner () -> TestDefM outers inner ()
describe (Path Rel File -> FilePath
fromRelFile Path Rel File
rf) forall a b. (a -> b) -> a -> b
$ FilePath -> TestDefM outers inner ()
func FilePath
fp