{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE TemplateHaskell #-}
module Test.BDD.Language
( Language (..)
, BDDPreparing
, BDDTesting
, BDDTest (..)
, TestContext (..)
, context
, when
, tests
, interpret
, Phase (..)
)
where
import Lens.Micro
import Lens.Micro.TH
data Phase = Preparing | Testing
data TestContext m = forall r. TestContext (m r) (r -> m ())
data Language m t q a where
Given
:: m ()
-> Language m t q 'Preparing
-> Language m t q 'Preparing
GivenAndAfter
:: m r
-> (r -> m ())
-> Language m t q 'Preparing
-> Language m t q 'Preparing
When
:: m t
-> Language m t q 'Testing
-> Language m t q 'Preparing
Then
:: (t -> m q)
-> Language m t q 'Testing
-> Language m t q 'Testing
End :: Language m t q 'Testing
data BDDTest m t q = BDDTest
{
_tests :: [t -> m q]
,
_context :: [TestContext m]
,
_when :: m t
}
makeLenses ''BDDTest
type BDDPreparing m t q = Language m t q 'Preparing
type BDDTesting m t q = Language m t q 'Testing
interpret :: Monad m => Language m t q a -> BDDTest m t q
interpret (Given given p) =
interpret $ GivenAndAfter given (const $ return ()) p
interpret (GivenAndAfter given after p) =
over context ((:) $ TestContext given after) $
interpret p
interpret (When fa p) =
set when fa $ interpret p
interpret (Then ca p) = over tests ((:) ca) $ interpret p
interpret End =
BDDTest [] [] $
error "End on its own does not make sense as a test"