ihp-1.5.0: Haskell Web Framework
Safe HaskellNone
LanguageGHC2021

IHP.Test.Mocking

Synopsis

Documentation

type ContextParameters application = (?request :: Request, ?respond :: Respond, ?modelContext :: ModelContext, ?application :: application, InitControllerContext application, ?mocking :: MockContext application) Source #

runTestMiddlewares :: FrameworkConfig -> ModelContext -> Maybe PGListener -> Request -> IO Request Source #

Run a request through the test middleware stack. This applies the same middlewares that IHP.Server uses. Used for initial setup only - actual request params are handled in callActionWithParams.

mockContextNoDatabase :: InitControllerContext application => application -> ConfigBuilder -> IO (MockContext application) Source #

Deprecated: Use withMockContext instead for bracket-style resource management

withMockContext :: InitControllerContext application => application -> ConfigBuilder -> (MockContext application -> IO a) -> IO a Source #

Bracket-style mock context creation with proper resource cleanup.

Uses withModelContext to ensure the database pool is released when done. Prefer this over mockContextNoDatabase.

Example: Use with hspec's aroundAll:

tests :: Spec
tests = aroundAll (withMockContext WebApplication config) do
    it "should work" $ withContext do
        ...

initTestApplication :: FrontController RootApplication => MockContext application -> IO Application Source #

Build a WAI Application from a MockContext for use with runSession.

This mirrors the middleware stack from run: errorHandlerMiddleware wraps the app to catch exceptions and render error pages. EarlyReturnException is caught inside runAction/runActionWithNewContext.

withMockContextAndApp :: (InitControllerContext application, FrontController RootApplication) => application -> ConfigBuilder -> ((MockContext application, Application) -> IO a) -> IO a Source #

Combines withMockContext and initTestApplication into a single bracket.

Example: Use with hspec's aroundAll:

tests :: Spec
tests = aroundAll (withMockContextAndApp WebApplication config) do
    it "should work" $ withContextAndApp \application -> do
        runSession (testGet "/foo") application >>= assertSuccess "bar"

withContextAndApp :: (ContextParameters application => Application -> IO a) -> (MockContext application, Application) -> IO a Source #

Like withContext but for specs using withMockContextAndApp. The WAI Application is passed to the callback.

withContext :: (ContextParameters application => IO a) -> MockContext application -> IO a Source #

Run a IO action, setting implicit params based on supplied mock context

setupWithContext :: (ContextParameters application => IO a) -> MockContext application -> IO (MockContext application) Source #

callAction :: forall application controller. (Controller controller, ContextParameters application, Typeable application, Typeable controller) => controller -> IO Response Source #

Runs a controller action in a mock environment

callActionWithParams :: forall application controller. (Controller controller, ContextParameters application, Typeable application, Typeable controller) => controller -> [Param] -> IO Response Source #

Runs a controller action in a mock environment

>>> callActionWithParams CreatePostAction [("title", "Hello World"), ("body", "lorem ipsum")|
Response { .. }

callJob :: (ContextParameters application, Typeable application, Job job) => job -> IO () Source #

Run a Job in a mock environment

Example:

Let's say you have a Job called JobPost that you would like to process as part of a test.

 let postJob <- fetch ...

 callJob postJob

Note that callJob doesn't set the Job status that is initially set JobStatusNotStarted, as that is done by the Job queue (see jobDidSucceed for example).

mockAction :: forall application controller. (Controller controller, ContextParameters application, Typeable application, Typeable controller) => controller -> IO Response Source #

mockAction has been renamed to callAction

mockActionResponse :: forall application controller. (Controller controller, ContextParameters application, Typeable application, Typeable controller) => controller -> IO ByteString Source #

Get contents of response

mockActionStatus :: forall application controller. (Controller controller, ContextParameters application, Typeable application, Typeable controller) => controller -> IO Status Source #

Get HTTP status of the controller

mockOverrideVaultKey :: Key Middleware Source #

Vault key holding a Middleware that test helpers like withUser use to override request vault entries (e.g. currentUserVaultKey) *after* the production middleware stack has run. callActionWithParams reads this key and wraps the controller innermost, so the override is guaranteed to be the last writer — sidestepping sessionMiddleware/authMw, which would otherwise clobber the mock state.

withUser :: (?request :: Request, ?respond :: Respond, user ~ CurrentUserRecord, HasField "id" user (Id' (GetTableName user)), PrimaryKey (GetTableName user) ~ UUID) => user -> ((?request :: Request, ?respond :: Respond) => IO result) -> IO result Source #

Set's the current user for the application

Example:

user <- newRecord @User
    |> set #email "marc@digitallyinduced.com"
    |> createRecord

response <- withUser user do
    callAction CreatePostAction

In this example the currentUser will refer to the newly created user during the execution of CreatePostAction.

Internally this composes a Middleware into mockOverrideVaultKey that seeds currentUserVaultKey and currentUserIdVaultKey with the mock user. callActionWithParams applies that middleware *innermost*, so it runs after sessionMiddleware and authMw and wins on conflict.

idToParam :: forall (table :: Symbol). Show (Id' table) => Id' table -> ByteString Source #

Turns a record id into a value that can be used with callActionWithParams

Example:

Let's say you have a test like this:

 let postId = cs $ show $ post.id

 let params = [ ("postId", postId) ]

You can replace the cs $ show $ with a cleaner idToParam:

 let postId = idToParam (libraryOpening.id)

 let params = [ ("postId", postId) ]