packages feed

stackctl-1.6.1.1: test/Stackctl/Test/App.hs

module Stackctl.Test.App
  ( TestApp
  , testAppAwsScope
  , testAppStackFilePath
  , TestAppT
  , runTestAppT

    -- * Re-exports
  , module Stackctl.Prelude
  , module Control.Lens
  , module Control.Monad.AWS.ViaMock
  , module Test.Hspec
  , module Test.Hspec.Expectations.Lifted
  ) where

import Stackctl.Prelude

import Blammo.Logging.Logger (newTestLogger)
import Control.Lens ((?~))
import Control.Monad.AWS
import Control.Monad.AWS.ViaMock
import Stackctl.AWS.Core (AccountId (..))
import Stackctl.AWS.Scope
import Stackctl.DirectoryOption
import Stackctl.FilterOption
import Test.Hspec (Spec, describe, example, it)
import Test.Hspec.Expectations.Lifted

data TestApp = TestApp
  { taLogger :: Logger
  , taMatchers :: Matchers
  , taAwsScope :: AwsScope
  , taFilterOption :: FilterOption
  , taDirectoryOption :: DirectoryOption
  }

instance HasLogger TestApp where
  loggerL = lens taLogger $ \x y -> x {taLogger = y}

instance HasMatchers TestApp where
  matchersL = lens taMatchers $ \x y -> x {taMatchers = y}

instance HasAwsScope TestApp where
  awsScopeL = lens taAwsScope $ \x y -> x {taAwsScope = y}

instance HasFilterOption TestApp where
  filterOptionL = lens taFilterOption $ \x y -> x {taFilterOption = y}

instance HasDirectoryOption TestApp where
  directoryOptionL = lens taDirectoryOption $ \x y -> x {taDirectoryOption = y}

newtype TestAppT m a = TestAppT
  { unTestAppT :: ReaderT TestApp (LoggingT m) a
  }
  deriving newtype
    ( Functor
    , Applicative
    , Monad
    , MonadIO
    , MonadUnliftIO
    , MonadLogger
    , MonadReader TestApp
    )
  deriving (MonadAWS) via (MockAWS (TestAppT m))

instance MonadIO m => MonadFail (TestAppT m) where
  fail msg = expectationFailure msg >> error "unreachable"

runTestAppT :: MonadUnliftIO m => TestAppT m a -> m a
runTestAppT f = do
  app <-
    TestApp
      <$> newTestLogger defaultLogSettings
      <*> pure mempty
      <*> pure testAppAwsScope
      <*> pure defaultFilterOption
      <*> pure defaultDirectoryOption

  runLoggerLoggingT app $ runReaderT (unTestAppT f) app

testAppAwsScope :: AwsScope
testAppAwsScope =
  AwsScope
    { awsAccountId = AccountId "0123456789"
    , awsAccountName = "test"
    , awsRegion = "us-east-1"
    }

-- | Gives a filepath relative to 'testAwsScope'
testAppStackFilePath :: Text -> FilePath
testAppStackFilePath base =
  "stacks"
    </> "0123456789.test"
    </> "us-east-1"
    </> unpack base
    <.> "yaml"