packages feed

line-bot-sdk-0.4.0.0: test/Line/Bot/ClientSpec.hs

{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE TypeFamilies      #-}
{-# LANGUAGE TypeOperators     #-}

module Line.Bot.ClientSpec (spec) where

import           Control.Arrow                    (left)
import           Control.Monad.Trans.Reader       (runReaderT)
import           Data.Aeson                       (Value)
import           Data.Aeson.QQ
import           Data.ByteString                  as B (stripPrefix)
import           Data.Text
import           Data.Text.Encoding
import           Line.Bot.Client                  hiding (runLine)
import           Line.Bot.Client.Auth
import           Line.Bot.Endpoints               (ChannelAuth)
import           Line.Bot.Types
import           Network.HTTP.Client              (defaultManagerSettings,
                                                   newManager)
import           Network.HTTP.Types               (hAuthorization)
import           Network.Wai                      (Request, requestHeaders)
import           Network.Wai.Handler.Warp         (Port, withApplication)
import           Servant
import           Servant.Client
import           Servant.Client.Core.Reexport
import           Servant.Server                   (Context (..))
import           Servant.Server.Experimental.Auth (AuthHandler, AuthServerData,
                                                   mkAuthHandler)
import           Test.Hspec
import           Test.Hspec.Expectations.Contrib
import           Test.Hspec.Wai

type instance AuthServerData ChannelAuth = ChannelToken

-- a dummy auth handler that returns the channel access token
authHandler :: AuthHandler Request ChannelToken
authHandler = mkAuthHandler $ \request -> do
  case lookup hAuthorization (requestHeaders request) >>= B.stripPrefix "Bearer " of
    Nothing -> throwError $ err401 { errBody = "Bad" }
    Just t  -> return $ ChannelToken $ decodeUtf8 t

serverContext :: Context '[AuthHandler Request ChannelToken]
serverContext = authHandler :. EmptyContext

type API =
       ChannelAuth :> "v2" :> "bot" :> "profile" :> "1" :> Get '[JSON] Value
  :<|> ChannelAuth :> "v2" :> "bot" :> "group" :> "1" :> "member" :> "1" :> Get '[JSON] Value

testProfile :: Value
testProfile = [aesonQQ|
  {
      displayName: "LINE taro",
      userId: "U4af4980629...",
      pictureUrl: "https://obs.line-apps.com/...",
      statusMessage: "Hello, LINE!"
  }
|]

withPort :: Port -> (ClientEnv -> IO a) -> IO a
withPort port app = do
  manager <- newManager defaultManagerSettings
  app $ mkClientEnv manager $ BaseUrl Http "localhost" port ""

runLine :: Line a -> Port -> IO (Either ServantError a)
runLine comp port = withPort port $ runClientM $ runReaderT comp "fake"

app :: Application
app = serveWithContext (Proxy :: Proxy API) serverContext $
       (\_ -> return testProfile)
  :<|> (\_ -> return testProfile)

spec :: Spec
spec = describe "Line client" $ do
  it "should return user profile" $ do
    withApplication (pure app) $ \port -> do
      runLine (getProfile "1") port >>= \x -> x `shouldSatisfy` isRight

  it "should return group user profile" $ do
    withApplication (pure app) $ \port -> do
      runLine (getGroupMemberProfile "1" "1") port >>= \x -> x `shouldSatisfy` isRight