Newer
Older
{-# LANGUAGE OverloadedStrings #-}
-- | Tests related to PaymentServer.Processors.Stripe.
module Stripe
( tests
) where
import Test.Tasty
( TestTree
, testGroup
)
import Test.Tasty.HUnit
( testCase
, assertEqual
)
import Control.Monad.IO.Class
( liftIO
)
import Control.Monad.Trans.Except
( runExceptT
)
import Servant.Server
( Handler(runHandler')
, ServerError(ServerError)
)
import Web.Stripe.Types
( Currency(USD, AED)
)
import Network.Wai.Test
( SRequest(SRequest)
, runSession
, request
, srequest
, defaultRequest
, assertHeader
, setPath
)
import Network.Wai
( requestMethod
, requestHeaders
)
import PaymentServer.Persistence
( memory
)
import PaymentServer.Processors.Stripe
( Charges(Charges)
, Acknowledgement(Ok)
, charge
)
import PaymentServer.Issuer
( trivialIssue
)
import PaymentServer.Server
( paymentServerApp
)
import FakeStripe
( withFakeStripe
, chargeOkay
)
tests :: TestTree
tests = testGroup "Stripe"
[ chargeTests
, corsTests
]
corsTests :: TestTree
corsTests =
testGroup "CORS"
[ testCase "a request with the wrong content-type receives a CORS-enabled response" $
assertCORSHeader "POST" textPlain validChargeBytes
, testCase "a request without a valid charge in the body receives a CORS-enabled response" $
assertCORSHeader "POST" applicationJSON invalidChargeBytes
, testCase "a request with the wrong request method receives a CORS-enabled response" $
assertCORSHeader "GET" applicationJSON validChargeBytes
, testCase "a request with a valid charge in the body receives a CORS-enabled response" $
assertCORSHeader "POST" applicationJSON validChargeBytes
where
textPlain = [("content-type", "text/plain")]
applicationJSON = [("content-type", "application/json")]
validChargeBytes = "{\"token\": \"abcdef\", \"voucher\": \"lmnopqrst\", \"amount\": \"650\", \"currency\": \"USD\"}"
invalidChargeBytes = "[1, 2, 3]"
assertCORSHeader method headers body =
withFakeStripe (return chargeOkay) $
\stripeConfig -> do
db <- memory
let origins = ["example.invalid"]
let app = paymentServerApp origins stripeConfig trivialIssue db
let path = "/v1/stripe/charge"
let theRequest = setPath defaultRequest
{ requestMethod = method
, requestHeaders = ("origin", "example.invalid"):headers
} path
let theSRequest = SRequest theRequest body
(flip runSession) app $ do
response <- srequest theSRequest
assertHeader "Access-Control-Allow-Origin" "example.invalid" response
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
chargeTests :: TestTree
chargeTests =
testGroup "Charges"
[ testCase "non-USD currency is rejected" $
withFakeStripe (return chargeOkay) $ \stripeConfig -> do
let amount = 650
let currency = AED
db <- memory
(Left (ServerError code _ _ _)) <- runExceptT . runHandler' $ charge stripeConfig db (Charges token voucher amount currency)
assertEqual "The result is an error" 400 code
, testCase "incorrect USD amount is rejected" $
withFakeStripe (return chargeOkay) $ \stripeConfig -> do
let amount = 649
let currency = USD
db <- memory
(Left (ServerError code _ _ _)) <- runExceptT . runHandler' $ charge stripeConfig db (Charges token voucher amount currency)
assertEqual "The result is an error" 400 code
, testCase "currect USD amount is accepted" $
withFakeStripe (return chargeOkay) $ \stripeConfig -> do
let amount = 650
let currency = USD
db <- memory
result <- runExceptT . runHandler' $ charge stripeConfig db (Charges token voucher amount currency)
assertEqual "The result is Ok" (Right Ok) result
]
where
token = "foo"
voucher = "bar"