crem-0.1.1.0: spec/Crem/RiskManagerSpec.hs
{-# LANGUAGE OverloadedStrings #-}
module Crem.RiskManagerSpec where
import Crem.Example.RiskManager.Application
import Crem.Example.RiskManager.Domain
import Crem.Example.RiskManager.Projection (ReceivedData (..))
import Crem.StateMachineSpec (shouldOutput)
import "crem" Crem.StateMachine (run, runMultiple)
import "hspec" Test.Hspec (Spec, describe, it)
myUserData :: UserData
myUserData =
UserData
{ name = "Marco"
, surname = "Perone"
, taxCode = "ABCDEF12T34J987H"
}
notMyUserData :: UserData
notMyUserData =
UserData
{ name = "Gigi"
, surname = "Zucon"
, taxCode = "ABCDEF12T34J987H"
}
loanDetails :: LoanDetails
loanDetails =
LoanDetails
{ amount = EuroCents 10000
, instalments = InstalmentsNumber 10
}
otherLoanDetails :: LoanDetails
otherLoanDetails =
LoanDetails
{ amount = EuroCents 20000
, instalments = InstalmentsNumber 5
}
creditBureauData :: CreditBureauData
creditBureauData =
CreditBureauData
{ missedPaymentDeadlines = MissedPaymentDeadlines 2
, arrears = EuroCents 100000
}
spec :: Spec
spec =
describe "RiskManager" $ do
describe "aggregate" $ do
it "emits a registered event when a registration command is received" $ do
run aggregate (RegisterUserData myUserData)
`shouldOutput` [UserDataRegistered myUserData]
it "emits two registered events when two registration commands are received" $ do
runMultiple aggregate [RegisterUserData myUserData, RegisterUserData notMyUserData]
`shouldOutput` [UserDataRegistered myUserData, UserDataRegistered notMyUserData]
it "does not emit anything when a loan details command is received" $ do
run aggregate (ProvideLoanDetails loanDetails)
`shouldOutput` []
it "emits a loan details event when a registration command and a loan detail command are received" $ do
runMultiple aggregate [RegisterUserData myUserData, ProvideLoanDetails loanDetails]
`shouldOutput` [UserDataRegistered myUserData, LoanDetailsProvided loanDetails]
describe "policy" $ do
it "emits a credit bureau command when a user registration event is received for a user named Marco" $ do
run policy (UserDataRegistered myUserData)
`shouldOutput` [ProvideCreditBureauData creditBureauData]
it "emits no command when a user registration event is received for a user not named Marco" $ do
run policy (UserDataRegistered notMyUserData)
`shouldOutput` []
it "emits two credit bureau command when two user registration events are received" $ do
runMultiple policy [UserDataRegistered myUserData, UserDataRegistered myUserData]
`shouldOutput` [ ProvideCreditBureauData creditBureauData
, ProvideCreditBureauData creditBureauData
]
it "emits one credit bureau command when two user registration events are received but only one for a user named Marco" $ do
runMultiple policy [UserDataRegistered myUserData, UserDataRegistered notMyUserData]
`shouldOutput` [ProvideCreditBureauData creditBureauData]
runMultiple policy [UserDataRegistered notMyUserData, UserDataRegistered myUserData]
`shouldOutput` [ProvideCreditBureauData creditBureauData]
it "emits no command when two user registration events are received for a user not named Marco" $ do
runMultiple policy [UserDataRegistered notMyUserData, UserDataRegistered notMyUserData]
`shouldOutput` []
it "emits no command when a loan details event is registered" $ do
run policy (LoanDetailsProvided loanDetails)
`shouldOutput` []
it "emits no command when a credit bureau data is registered" $ do
run policy (CreditBureauDataReceived creditBureauData)
`shouldOutput` []
describe "writeModel" $ do
it "emits a registered event when a registration command is received" $ do
run writeModel (RegisterUserData myUserData)
`shouldOutput` [ UserDataRegistered myUserData
, CreditBureauDataReceived creditBureauData
]
it "emits two registered events when two registration command are received" $ do
runMultiple writeModel [RegisterUserData myUserData, RegisterUserData myUserData]
`shouldOutput` [ UserDataRegistered myUserData
, CreditBureauDataReceived creditBureauData
, UserDataRegistered myUserData
, CreditBureauDataReceived creditBureauData
]
describe "riskProjection" $ do
it "registers one user when a registration event is received" $ do
run projection (UserDataRegistered myUserData)
`shouldOutput` ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
it "updates the user data when two registration events are received" $ do
runMultiple projection [UserDataRegistered myUserData, UserDataRegistered notMyUserData]
`shouldOutput` ReceivedData
{ receivedUserData = Just notMyUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
describe "readModel" $ do
it "registers one user when a registration event is received" $ do
run readModel (UserDataRegistered myUserData)
`shouldOutput` [ ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
]
it "registers two users when two registration events are received" $ do
runMultiple readModel [UserDataRegistered myUserData, UserDataRegistered notMyUserData]
`shouldOutput` [ ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
, ReceivedData
{ receivedUserData = Just notMyUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
]
describe "whole" $ do
it "registers one user when a registration command is received" $ do
run whole (RegisterUserData myUserData)
`shouldOutput` [ ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
, ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Just creditBureauData
}
]
it "registers two users when two registration commands are received" $ do
runMultiple whole [RegisterUserData myUserData, RegisterUserData notMyUserData]
`shouldOutput` [ ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Nothing
}
, ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Just creditBureauData
}
, ReceivedData
{ receivedUserData = Just notMyUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Just creditBureauData
}
]
describe "riskApplication" $ do
it "registers one user" $ do
run riskApplication (RegisterUserData myUserData)
`shouldOutput` ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Just creditBureauData
}
it "updates the user data" $ do
runMultiple riskApplication [RegisterUserData notMyUserData, RegisterUserData myUserData]
`shouldOutput` ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Nothing
, receivedCreditBureauData = Just creditBureauData
}
it "collects the user data and the loan details" $ do
runMultiple riskApplication [RegisterUserData myUserData, ProvideLoanDetails loanDetails]
`shouldOutput` ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Just loanDetails
, receivedCreditBureauData = Just creditBureauData
}
it "updates the loan details" $ do
runMultiple
riskApplication
[ RegisterUserData myUserData
, ProvideLoanDetails loanDetails
, ProvideLoanDetails otherLoanDetails
]
`shouldOutput` ReceivedData
{ receivedUserData = Just myUserData
, receivedLoanDetails = Just otherLoanDetails
, receivedCreditBureauData = Just creditBureauData
}