packages feed

main-tester-0.1.0.0: test/Spec.hs

import           Control.Monad (mapM_)
import           Data.ByteString.Char8 (pack)
import           System.Environment (getArgs)
import           System.Exit (ExitCode(ExitSuccess, ExitFailure) , exitWith)
import           System.IO (stderr, hPutStr)
import           Test.Hspec
import           Test.Hspec.QuickCheck
import           Test.QuickCheck
                   ( Arbitrary
                   , arbitrary
                   , choose
                   , oneof
                   , listOf
                   )

import           Test.Main
import           Test.Main.Internal


newtype AExitCode = AExitCode ExitCode deriving Show

instance Arbitrary AExitCode where
  arbitrary =
    AExitCode <$> oneof [pure ExitSuccess, ExitFailure <$> choose (1, maxBound)]


newtype PrintableAsciiString =
  PrintableAsciiString { getPrintableAsciiString :: String } deriving Show

-- https://en.wikipedia.org/wiki/ASCII#Character_set
instance Arbitrary PrintableAsciiString where
  arbitrary = PrintableAsciiString <$> listOf (choose (' ', '~'))


main :: IO ()
main = hspec $
  describe "Test.Main" $
    prop "passes stdin and arguments to the program, and capture stdin data, stderr data, and exitCode" $
      \(argsA, inDataA, AExitCode eCode) -> do
        let args = map getPrintableAsciiString argsA
            inData = pack $ getPrintableAsciiString inDataA
            testedMain = do
              mapM_ putStrLn =<< getArgs
              hPutStr stderr =<< getContents
              exitWith eCode

        actual <- withStdin inData $ withArgs args $ captureProcessResult testedMain

        normalizeNewLines actual `shouldBe`
          normalizeNewLines (ProcessResult (pack $ unlines args) inData eCode)