packages feed

plaid-0.1.0.3: test/Plaid/PlaidSpec.hs

module Plaid.PlaidSpec (spec) where

import qualified Control.Error as ER
import           Data.Aeson (FromJSON (..), ToJSON (..), eitherDecode')
import           Data.ByteString.Char8 (unpack)
import           Data.ByteString.Lazy (ByteString, toStrict)
import           Data.Either (isRight)
import           Data.Plaid
import           Data.Text (Text)
import qualified Data.Text as T
import           Data.Time (fromGregorian)
import           Test.Hspec

_runTestGetRequest :: PlaidHttp m => Text -> m ByteString
_runTestGetRequest url = executeGet url

runTestPostRequest :: (PlaidHttp m, ToJSON a) => Text -> a -> m ByteString
runTestPostRequest url postBody = executePost url postBody

checkResult :: FromJSON a => ByteString -> Either PlaidError a
checkResult result =
  case result of
    "" -> Left (PlaidError $ T.pack $ "Failed to decode bytestring " ++ (unpack $ toStrict result))
    _  ->
      case eitherDecode' result of
        Left e   -> Left $ PlaidError (T.pack e)
        Right ok -> Right ok

env :: PlaidEnv
env = PlaidEnv "" (ClientId "") (Secret "") Sandbox

publicTokenBody :: Either PlaidError (PlaidBody PublicTokenCreate)
publicTokenBody =
  mkCreatePublicTokenEnv env
    (InstitutionId "ins_3")
    ["transactions"]
    Nothing
    -- (Just $
    --   PlaidOptions
    --   "http://bogicevicsasa.com"
    --   "user_good"
    --   "pass_good"
    -- )

spec :: Spec
spec = do
  describe "Create public token" $ do
    it "/public_token/create" $ do
      let result = runTestPlaid $ runTestPostRequest "/public_token/create" publicTokenBody
          testResult = checkResult result :: Either PlaidError PlaidPublicTokenResponse
      isRight testResult `shouldBe` True

  describe "Exchange public token" $ do
    it "/item/public_token/exchange" $ do
      let result = runTestPlaid $ runTestPostRequest "/public_token/create" publicTokenBody
      testResult <- ER.runExceptT $ do
        PlaidPublicTokenResponse {..} <- ER.hoistEither (checkResult result :: Either PlaidError PlaidPublicTokenResponse)
        exchangeBody <- ER.hoistEither (mkExchangePublicTokenEnv env _plaidPublicTokenResponsePublicToken)
        let result' = runTestPlaid $ runTestPostRequest "/item/public_token/exchange" exchangeBody
        ER.hoistEither (checkResult result' :: Either PlaidError PlaidAccessTokenResponse)
      isRight testResult `shouldBe` True

  describe "Auth get" $ do
    it "/auth/get" $ do
      let result = runTestPlaid $ runTestPostRequest "/public_token/create" publicTokenBody
      testResult <- ER.runExceptT $ do
        PlaidPublicTokenResponse {..} <- ER.hoistEither (checkResult result :: Either PlaidError PlaidPublicTokenResponse)
        exchangeBody <- ER.hoistEither (mkExchangePublicTokenEnv env _plaidPublicTokenResponsePublicToken)
        let result' = runTestPlaid $ runTestPostRequest "/item/public_token/exchange" exchangeBody
        PlaidAccessTokenResponse {..} <- ER.hoistEither (checkResult result' :: Either PlaidError PlaidAccessTokenResponse)
        authBody <- ER.hoistEither (mkGetAuthEnv env _plaidAccessTokenResponseAccessToken)
        let authGetResult = runTestPlaid $ runTestPostRequest "/auth/get" authBody
        ER.hoistEither (checkResult authGetResult :: Either PlaidError PlaidAuthGetResponse)
      isRight testResult `shouldBe` True

  describe "Identity get" $ do
    it "/identity/get" $ do
      let result = runTestPlaid $ runTestPostRequest "/public_token/create" publicTokenBody
      testResult <- ER.runExceptT $ do
        PlaidPublicTokenResponse {..} <- ER.hoistEither (checkResult result :: Either PlaidError PlaidPublicTokenResponse)
        exchangeBody <- ER.hoistEither (mkExchangePublicTokenEnv env _plaidPublicTokenResponsePublicToken)
        let result' = runTestPlaid $ runTestPostRequest "/item/public_token/exchange" exchangeBody
        PlaidAccessTokenResponse {..} <- ER.hoistEither (checkResult result' :: Either PlaidError PlaidAccessTokenResponse)
        identityBody <- ER.hoistEither (mkCreateIdentityGetEnv env _plaidAccessTokenResponseAccessToken)
        let identityGetResult = runTestPlaid $ runTestPostRequest "/identity/get" identityBody
        ER.hoistEither (checkResult identityGetResult :: Either PlaidError PlaidIdentityGetResponse)
      isRight testResult `shouldBe` True
  describe "Transactions get" $ do
    it "/transactions/get" $ do
      let result = runTestPlaid $ runTestPostRequest "/public_token/create" publicTokenBody
      testResult <- ER.runExceptT $ do
        PlaidPublicTokenResponse {..} <- ER.hoistEither (checkResult result :: Either PlaidError PlaidPublicTokenResponse)
        exchangeBody <- ER.hoistEither (mkExchangePublicTokenEnv env _plaidPublicTokenResponsePublicToken)
        let result' = runTestPlaid $ runTestPostRequest "/item/public_token/exchange" exchangeBody
        PlaidAccessTokenResponse {..} <- ER.hoistEither (checkResult result' :: Either PlaidError PlaidAccessTokenResponse)
        authBody <- ER.hoistEither (mkGetAuthEnv env _plaidAccessTokenResponseAccessToken)
        let authGetResult = runTestPlaid $ runTestPostRequest "/auth/get" authBody
        PlaidAuthGetResponse {..} <- ER.hoistEither (checkResult authGetResult :: Either PlaidError PlaidAuthGetResponse)
        let startTime = fromGregorian 2018 1 1
        let endTime   = fromGregorian 2019 1 1
        transactionBody <-
          ER.hoistEither (mkCreateTransactionsGetEnv
                           env
                           _plaidAccessTokenResponseAccessToken
                           startTime
                           endTime
                           Nothing
                           Nothing
                         )

        let transactionsGetResult =
              runTestPlaid $ runTestPostRequest "/transactions/get" transactionBody
        ER.hoistEither (checkResult transactionsGetResult :: Either PlaidError PlaidTransactionsGetResponse)
      isRight testResult `shouldBe` True
  describe "Balance json" $ do
    it "should be able to decode Balance" $ do
      let result = eitherDecode' balanceJson :: Either String Balance
      isRight result `shouldBe` True
  describe "Account json" $ do
    it "should be able to decode Account" $ do
      let result = eitherDecode' accountJson :: Either String Account
      isRight result `shouldBe` True
  describe "Account list json" $ do
    it "should be able to decode Account list" $ do
      let result = eitherDecode' accountListJson :: Either String [Account]
      isRight result `shouldBe` True
  describe "PaymentMeta json" $ do
    it "should be able to decode PaymentMeta" $ do
      let result = eitherDecode' accountJson :: Either String PaymentMeta
      isRight result `shouldBe` True
  describe "Item json" $ do
    it "should be able to decode Item" $ do
      let result = eitherDecode' itemJson :: Either String Item
      isRight result `shouldBe` True
  describe "Transaction json" $ do
    it "should be able to decode Transaction" $ do
      let result = eitherDecode' transactionJson :: Either String Transaction
      isRight result `shouldBe` True
  describe "TransactionLocation json" $ do
    it "should be able to decode TransactionLocation" $ do
      let result = eitherDecode' transactionLocationJson :: Either String TransactionLocation
      isRight result `shouldBe` True
  describe "email json" $ do
    it "should be able to decode Email" $ do
      let result = eitherDecode' emailJson :: Either String Email
      isRight result `shouldBe` True
  describe "phone json" $ do
    it "should be able to decode Phone" $ do
      let result = eitherDecode' phoneNumberJson :: Either String PhoneNumber
      isRight result `shouldBe` True
  describe "address json" $ do
    it "should be able to decode Addresses" $ do
      let result = eitherDecode' addressesJson :: Either String Addresses
      isRight result `shouldBe` True
  describe "Accounts json" $ do
    it "should be able to decode Accounts" $ do
      let result = eitherDecode' accountsJson :: Either String Accounts
      isRight result `shouldBe` True
  describe "Owners json" $ do
    it "should be able to decode Owners" $ do
      let result = eitherDecode' ownersJson :: Either String Owners
      isRight result `shouldBe` True