@@ -8,6 +8,7 @@ module TestUserAcceptance where
88
99import qualified Data.Text as T
1010import System.IO.Temp (createTempDirectory , getCanonicalTemporaryDirectory )
11+ import Data.Functor (($>) )
1112import Data.Ini (parseIni , writeIniFileWith , KeySeparator (.. ), WriteIniSettings (.. ))
1213import Data.Semigroup ((<>) )
1314import Control.Concurrent (threadDelay )
@@ -19,7 +20,7 @@ import Data.Maybe (isJust)
1920import Control.Monad.IO.Class (liftIO )
2021import Control.Monad.Reader (runReaderT , ask , ReaderT )
2122
22- import Control.Lens (view , _3 , _2 )
23+ import Control.Lens (Lens' , view )
2324import Data.List (isInfixOf , intercalate )
2425import System.Process (callProcess , readProcess )
2526import System.Directory
@@ -37,20 +38,24 @@ data Condition
3738systemTests ::
3839 TestTree
3940systemTests =
40- testGroup
41- " user acceptance tests"
42- [ testUserViewsMailSuccessfully
43- , testUserCanManipulateNMQuery
44- , testUserCanSwitchBackToIndex
45- , testCanToggleHeaders
46- , testSetsMailToRead
47- , testErrorHandling
48- , testHelp
49- , testManageTagsOnMails
50- , testManageTagsOnThreads
51- ]
52-
53- testManageTagsOnMails :: TestTree
41+ withResource pre post $ \ _ ->
42+ testGroup " user acceptance tests" $ zipWith ($) tests [0 .. ]
43+ where
44+ pre = let n = " keepalive" in setUpTmuxSession n $> n
45+ post = cleanUpTmuxSession
46+ tests =
47+ [ testUserViewsMailSuccessfully
48+ , testUserCanManipulateNMQuery
49+ , testUserCanSwitchBackToIndex
50+ , testCanToggleHeaders
51+ , testSetsMailToRead
52+ , testErrorHandling
53+ , testHelp
54+ , testManageTagsOnMails
55+ , testManageTagsOnThreads
56+ ]
57+
58+ testManageTagsOnMails :: Int -> TestTree
5459testManageTagsOnMails = withTmuxSession " manage tags on mails" $
5560 \ step -> do
5661 startApplication
@@ -95,7 +100,7 @@ testManageTagsOnMails = withTmuxSession "manage tags on mails" $
95100
96101 pure ()
97102
98- testManageTagsOnThreads :: TestTree
103+ testManageTagsOnThreads :: Int -> TestTree
99104testManageTagsOnThreads = withTmuxSession " manage tags on threads" $
100105 \ step -> do
101106 startApplication
@@ -117,7 +122,7 @@ testManageTagsOnThreads = withTmuxSession "manage tags on threads" $
117122
118123 pure ()
119124
120- testHelp :: TestTree
125+ testHelp :: Int -> TestTree
121126testHelp = withTmuxSession " help view" $
122127 \ step -> do
123128 startApplication
@@ -128,8 +133,7 @@ testHelp = withTmuxSession "help view" $
128133 sendKeys " Escape" (Literal " Purebred" )
129134 pure ()
130135
131- testErrorHandling ::
132- TestTree
136+ testErrorHandling :: Int -> TestTree
133137testErrorHandling = withTmuxSession " error handling" $
134138 \ step -> do
135139 startApplication
@@ -149,8 +153,7 @@ testErrorHandling = withTmuxSession "error handling" $
149153
150154 pure ()
151155
152- testSetsMailToRead ::
153- TestTree
156+ testSetsMailToRead :: Int -> TestTree
154157testSetsMailToRead = withTmuxSession " user can toggle read tag" $
155158 \ step -> do
156159 startApplication
@@ -166,8 +169,7 @@ testSetsMailToRead = withTmuxSession "user can toggle read tag" $
166169 sendKeys " t" (Regex (buildAnsiRegex [" 1" ] [" 37" ] [" 43" ] <> " .*Testmail" ))
167170 pure ()
168171
169- testCanToggleHeaders ::
170- TestTree
172+ testCanToggleHeaders :: Int -> TestTree
171173testCanToggleHeaders = withTmuxSession " user can toggle Headers" $
172174 \ step -> do
173175 startApplication
@@ -184,8 +186,7 @@ testCanToggleHeaders = withTmuxSession "user can toggle Headers" $
184186 out <- sendKeys " h" (Literal " This is a test mail" )
185187 assertRegex " Purebred.*\n .*[Ff]rom" out
186188
187- testUserViewsMailSuccessfully ::
188- TestTree
189+ testUserViewsMailSuccessfully :: Int -> TestTree
189190testUserViewsMailSuccessfully = withTmuxSession " user can view mail" $
190191 \ step -> do
191192 startApplication
@@ -200,8 +201,7 @@ testUserViewsMailSuccessfully = withTmuxSession "user can view mail" $
200201 sendKeys " Enter" (Literal " This is a test mail" )
201202 pure ()
202203
203- testUserCanManipulateNMQuery ::
204- TestTree
204+ testUserCanManipulateNMQuery :: Int -> TestTree
205205testUserCanManipulateNMQuery =
206206 withTmuxSession
207207 " manipulating notmuch search query results in empty index" $
@@ -234,8 +234,7 @@ testUserCanManipulateNMQuery =
234234 sendKeys " Enter" (Literal " HOLY PUREBRED" )
235235 pure ()
236236
237- testUserCanSwitchBackToIndex ::
238- TestTree
237+ testUserCanSwitchBackToIndex :: Int -> TestTree
239238testUserCanSwitchBackToIndex =
240239 withTmuxSession " user can switch back to mail index during composition" $
241240 \ step -> do
@@ -268,8 +267,6 @@ testUserCanSwitchBackToIndex =
268267 sendKeys " Tab" (Literal " test subject" )
269268 pure ()
270269
271- type Env = (String , String , String )
272-
273270assertSubstrInOutput :: String -> String -> ReaderT Env IO ()
274271assertSubstrInOutput substr out = liftIO $ assertBool (substr <> " not found in\n\n " <> out) $ substr `isInfixOf` out
275272
@@ -282,16 +279,35 @@ assertRegex regex out = liftIO $ assertBool
282279defaultSessionName :: String
283280defaultSessionName = " purebredtest"
284281
285- tearDown :: (String , String , String ) -> IO ()
286- tearDown (testdir, _, _)= do
282+ data Env = Env
283+ { _envDir :: FilePath
284+ , _envMaildir :: FilePath
285+ , _envSessionName :: String
286+ }
287+
288+ envDir :: Lens' Env FilePath
289+ envDir f (Env a b c) = fmap (\ a' -> Env a' b c) (f a)
290+
291+ envMaildir :: Lens' Env FilePath
292+ envMaildir f (Env a b c) = fmap (\ b' -> Env a b' c) (f b)
293+
294+ envSessionName :: Lens' Env String
295+ envSessionName f (Env a b c) = fmap (\ c' -> Env a b c') (f c)
296+ {-# ANN envSessionName ("HLint: ignore Avoid lambda" :: String) #-}
297+
298+ -- | Tear down a test session
299+ tearDown :: Env -> IO ()
300+ tearDown (Env testdir _ sessionName) = do
287301 removeDirectoryRecursive testdir
288- cleanUpTmuxSession defaultSessionName
302+ cleanUpTmuxSession sessionName
289303
290- setUp :: IO (String , String , String )
291- setUp = do
292- let sessionname = defaultSessionName
293- (testdir, testmdir) <- setUpTmuxSession sessionname >> setUpTempMaildir
294- pure (testdir, testmdir, sessionname)
304+ -- | Set up a test session.
305+ setUp :: Int -> IO Env
306+ setUp i = do
307+ let sessionName = defaultSessionName <> show i
308+ setUpTmuxSession sessionName
309+ (testdir, maildir) <- setUpTempMaildir
310+ pure $ Env testdir maildir sessionName
295311
296312setUpTempMaildir :: IO (String , String )
297313setUpTempMaildir = do
@@ -358,22 +374,28 @@ cleanUpTmuxSession sessionname =
358374
359375
360376-- | Run all application steps in a session defined by session name.
361- withTmuxSession :: TestName -> ((String -> IO () ) -> ReaderT Env IO () ) -> TestTree
362- withTmuxSession tcname testfx =
363- withResource setUp tearDown $
377+ withTmuxSession
378+ :: TestName
379+ -> ((String -> IO () ) -> ReaderT Env IO () )
380+ -> Int -- ^ session sequence number (will be appended to session name)
381+ -> TestTree
382+ withTmuxSession tcname testfx i =
383+ withResource (setUp i) tearDown $
364384 \ env -> testCaseSteps tcname $ \ stepfx -> env >>= runReaderT (testfx stepfx)
365385
366386-- | Send keys into the program and wait for the condition to be
367387-- met, failing the test if the condition is not met after some
368388-- time.
369389sendKeys :: String -> Condition -> ReaderT Env IO String
370390sendKeys keys expect = do
371- liftIO $ callProcess " tmux" $ communicateSessionArgs keys False
391+ sessionName <- getSessionName
392+ liftIO $ callProcess " tmux" $ communicateSessionArgs sessionName keys False
372393 waitForCondition expect defaultCountdown
373394
374395sendLiteralKeys :: String -> ReaderT Env IO String
375396sendLiteralKeys keys = do
376- liftIO $ callProcess " tmux" $ communicateSessionArgs keys True
397+ sessionName <- getSessionName
398+ liftIO $ callProcess " tmux" $ communicateSessionArgs sessionName keys True
377399 waitForString keys defaultCountdown
378400
379401capture :: ReaderT Env IO String
@@ -382,10 +404,10 @@ capture = do
382404 liftIO $ readProcess " tmux" [" capture-pane" , " -e" , " -p" , " -t" , sessionname] []
383405
384406getSessionName :: ReaderT Env IO String
385- getSessionName = view (_3 . ask)
407+ getSessionName = view (envSessionName . ask)
386408
387- getTestMaildir :: ReaderT Env IO String
388- getTestMaildir = view (_2 . ask)
409+ getTestMaildir :: ReaderT Env IO FilePath
410+ getTestMaildir = view (envMaildir . ask)
389411
390412holdOffTime :: Int
391413holdOffTime = 10 ^ 6
@@ -436,12 +458,18 @@ defaultCountdown = 5
436458startApplication :: ReaderT Env IO ()
437459startApplication = do
438460 testmdir <- getTestMaildir
439- liftIO $ callProcess " tmux" $ communicateSessionArgs (" purebred --database " <> testmdir <> " \r " ) False
461+ sessionName <- getSessionName
462+ liftIO $ callProcess " tmux" $
463+ communicateSessionArgs sessionName (" purebred --database " <> testmdir <> " \r " ) False
440464 void $ waitForString " Purebred: Item" defaultCountdown
441465
442- communicateSessionArgs :: String -> Bool -> [String ]
443- communicateSessionArgs keys asLiteral =
444- [" send-keys" , " -t" , defaultSessionName] <> [" -l" | asLiteral] <> [keys]
466+ communicateSessionArgs
467+ :: String -- ^ session name
468+ -> String -- ^ keys
469+ -> Bool -- ^ send the keys literally
470+ -> [String ]
471+ communicateSessionArgs sessionName keys asLiteral =
472+ [" send-keys" , " -t" , sessionName] <> [" -l" | asLiteral] <> [keys]
445473
446474
447475type AnsiAttrParam = String
0 commit comments