@@ -53,7 +53,7 @@ import Text.Regex.TDFA ((=~))
5353import Control.Concurrent.Async (withAsync )
5454import qualified Data.Aeson as JSON
5555import qualified Data.ByteString.Lazy as BSL
56- import Control.Monad (unless , when , void , forM_ , liftM2 , liftM4 )
56+ import Control.Monad (unless , when , void , forM_ , foldM , liftM2 , liftM4 )
5757import Control.Monad.Catch ( bracket_ )
5858import Control.Monad.Trans.Reader (asks , withReaderT , runReaderT )
5959import Control.Monad.IO.Class (MonadIO (.. ))
@@ -836,6 +836,31 @@ assertFileDoesNotContain path needle =
836836 (assertFailure (" expected: " ++ needle ++ " \n " ++
837837 " in file: " ++ path)))
838838
839+ -- | Assert that at least one of the given paths contains the given search string.
840+ assertAnyFileContains :: MonadIO m => WithCallStack ([FilePath ] -> String -> m () )
841+ assertAnyFileContains paths needle = do
842+ let findOne found path =
843+ if found
844+ then pure found
845+ else withFileContents path $ \ contents ->
846+ pure $! needle `isInfixOf` contents
847+ foundNeedle <- liftIO $ foldM findOne False paths
848+ withFrozenCallStack $
849+ unless foundNeedle $
850+ assertFailure $
851+ " expected: " <>
852+ needle <>
853+ " \n in one of:\n " <>
854+ unlines (map (" * " <> ) paths)
855+
856+ -- | Assert that none of the given paths contains the given search string.
857+ assertNoFileContains :: MonadIO m => WithCallStack ([FilePath ] -> String -> m () )
858+ assertNoFileContains paths needle =
859+ liftIO $
860+ forM_ paths $
861+ \ path ->
862+ assertFileDoesNotContain path needle
863+
839864-- | Replace line breaks with spaces, correctly handling "\r\n".
840865concatOutput :: String -> String
841866concatOutput = unwords . lines . filter ((/=) ' \r ' )
@@ -857,13 +882,16 @@ matchGlob root glob = do
857882 liftIO $ Glob. globDir1 (Glob. compile glob) root
858883
859884-- | Assert that a glob matches at least one path in the given root directory.
860- assertGlobMatches :: MonadIO m => WithCallStack (FilePath -> String -> m () )
885+ --
886+ -- The matched paths are returned for further validation.
887+ assertGlobMatches :: MonadIO m => WithCallStack (FilePath -> String -> m [FilePath ])
861888assertGlobMatches root glob = do
862889 results <- matchGlob root glob
863890 withFrozenCallStack $
864891 when (null results) $
865892 assertFailure $
866893 " Expected glob " <> show glob <> " to match in " <> show root
894+ pure results
867895
868896-- | Assert that a glob matches no paths in the given root directory.
869897assertGlobDoesNotMatch :: MonadIO m => WithCallStack (FilePath -> String -> m () )
@@ -882,7 +910,9 @@ assertGlobDoesNotMatch root glob = do
882910-- | Assert that a glob matches a path in the given root directory.
883911--
884912-- The root directory is determined from the `TestEnv` with a function like `testDistDir`.
885- assertGlobMatchesTestDir :: WithCallStack ((TestEnv -> FilePath ) -> String -> TestM () )
913+ --
914+ -- The matched paths are returned for further validation.
915+ assertGlobMatchesTestDir :: WithCallStack ((TestEnv -> FilePath ) -> String -> TestM [FilePath ])
886916assertGlobMatchesTestDir rootSelector glob = do
887917 root <- asks rootSelector
888918 assertGlobMatches root glob
0 commit comments