{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -fno-warn-duplicate-exports #-}

module Test.Syd
  ( -- * Top level API functions
    sydTest,
    sydTestWith,

    -- * Defining a test suite

    -- * Declaring tests
    describe,
    it,
    itWithOuter,
    itWithBoth,
    itWithAll,
    specify,
    specifyWithOuter,
    specifyWithBoth,
    specifyWithAll,

    -- ** Commented-out tests
    xdescribe,
    xit,
    xitWithOuter,
    xitWithBoth,
    xitWithAll,
    xspecify,
    xspecifyWithOuter,
    xspecifyWithBoth,
    xspecifyWithAll,

    -- ** Pending tests
    pending,
    pendingWith,

    -- ** Environment-based tests
    eit,
    withTestEnv,

    -- ** Golden tests
    pureGoldenByteStringFile,
    goldenByteStringFile,
    pureGoldenTextFile,
    goldenTextFile,
    pureGoldenStringFile,
    goldenStringFile,
    goldenShowInstance,
    goldenPrettyShowInstance,

    -- ** Expectations
    shouldBe,
    shouldNotBe,
    shouldSatisfy,
    shouldSatisfyNamed,
    shouldNotSatisfy,
    shouldNotSatisfyNamed,
    shouldReturn,
    shouldNotReturn,
    shouldStartWith,
    shouldEndWith,
    shouldContain,
    expectationFailure,
    context,
    Expectation,
    shouldThrow,
    Selector,
    anyException,
    anyErrorCall,
    errorCall,
    anyIOException,
    anyArithException,

    -- *** String expectations
    stringShouldBe,
    textShouldBe,

    -- *** For throwing raw assertions
    stringsNotEqualButShouldHaveBeenEqual,
    textsNotEqualButShouldHaveBeenEqual,
    bytestringsNotEqualButShouldHaveBeenEqual,
    Assertion (..),

    -- ** Declaring test dependencies

    -- *** Dependencies around all of a group of tests
    beforeAll,
    beforeAll_,
    beforeAllWith,
    afterAll,
    afterAll',
    afterAll_,
    aroundAll,
    aroundAll_,
    aroundAllWith,

    -- *** Dependencies around each of a group of tests
    before,
    before_,
    after,
    after_,
    around,
    around_,
    aroundWith,

    -- **** Setup functions

    -- ***** Using setup functions
    setupAround,
    setupAroundWith,
    setupAroundWith',

    -- ***** Creating setup functions
    SetupFunc (..),
    makeSimpleSetupFunc,
    useSimpleSetupFunc,
    connectSetupFunc,
    composeSetupFunc,
    wrapSetupFunc,
    unwrapSetupFunc,

    -- *** Declaring different test settings
    modifyMaxSuccess,
    modifyMaxDiscardRatio,
    modifyMaxSize,
    modifyMaxShrinks,
    modifyRunSettings,
    TestRunSettings (..),

    -- *** Declaring parallelism
    sequential,
    parallel,
    withParallelism,
    Parallelism (..),

    -- *** Declaring randomisation order
    randomiseExecutionOrder,
    doNotRandomiseExecutionOrder,
    withExecutionOrderRandomisation,
    ExecutionOrderRandomisation (..),

    -- *** Doing IO during test definition
    runIO,

    -- ** Test definition types
    TestDefM (..),
    TestDef,
    execTestDefM,
    runTestDefM,

    -- ** Test suite types
    TDef (..),
    TestForest,
    TestTree,
    SpecDefForest,
    SpecDefTree (..),
    ResultForest,
    ResultTree,
    shouldExitFail,

    -- ** Hspec synonyms

    --
    -- These synonyms have been provided so that you can more or less "just" replace "hspec" by "sydTest" and have things work.
    -- However, hspec does not distinguish between inner and outer resources, so these synonyms assume that all resources are inner resources.
    Spec,
    SpecWith,
    SpecM,

    -- * Utilities
    ppShow,

    -- * Reexports
    module Test.Syd.Def,
    module Test.Syd.Expectation,
    module Test.Syd.HList,
    module Test.Syd.Modify,
    module Test.Syd.Output,
    module Test.Syd.Run,
    module Test.Syd.Runner,
    module Test.Syd.SpecDef,
    module Test.Syd.SpecForest,
    module Control.Monad.IO.Class,
  )
where

import Control.Monad
import Control.Monad.IO.Class
import System.Exit
import Test.QuickCheck.IO ()
import Test.Syd.Def
import Test.Syd.Expectation
import Test.Syd.HList
import Test.Syd.Modify
import Test.Syd.OptParse
import Test.Syd.Output
import Test.Syd.Run
import Test.Syd.Runner
import Test.Syd.SpecDef
import Test.Syd.SpecForest
import Text.Show.Pretty (ppShow)

-- | Evaluate a test suite definition and then run it, with default 'Settings'
sydTest :: Spec -> IO ()
sydTest :: Spec -> IO ()
sydTest Spec
spec = do
  Settings
sets <- IO Settings
getSettings
  Settings -> Spec -> IO ()
sydTestWith Settings
sets Spec
spec

-- | Evaluate a test suite definition and then run it, with given 'Settings'
sydTestWith :: Settings -> Spec -> IO ()
sydTestWith :: Settings -> Spec -> IO ()
sydTestWith Settings
sets Spec
spec = do
  Timed ResultForest
resultForest <- Settings -> Spec -> IO (Timed ResultForest)
forall r. Settings -> TestDefM '[] () r -> IO (Timed ResultForest)
sydTestResult Settings
sets Spec
spec
  Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ResultForest -> Bool
shouldExitFail (Timed ResultForest -> ResultForest
forall a. Timed a -> a
timedValue Timed ResultForest
resultForest)) (ExitCode -> IO ()
forall a. ExitCode -> IO a
exitWith (Int -> ExitCode
ExitFailure Int
1))

runIO :: IO e -> TestDefM a b e
runIO :: IO e -> TestDefM a b e
runIO = IO e -> TestDefM a b e
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO