{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} module SpecHelper ( -- * Expectations Fold , shouldHaveResponse , shouldHaveJson , shouldHaveJson_ , shouldHaveXml , shouldHaveXml_ -- * public data , publicly , publicKey -- * private data -- $awful , privately , privateAPIKey , privateSessionKey , privateSecret ) where import Control.Exception (Exception, throwIO) import Control.Lens import Data.Aeson (Value) import Data.Aeson.Lens import Data.Text (Text, pack) import Data.Typeable (Typeable) import Network.Lastfm import System.Environment import System.IO.Unsafe (unsafePerformIO) import Test.Hspec import Test.HUnit (assertFailure) import Text.Printf import Text.Xml.Lens infixl 1 `shouldHaveJson`, `shouldHaveXml` -- | Inspect 'Response' with 'Query' shouldHaveResponse :: (Show r, Supported f r) => Request f Ready -> Fold r a -> Expectation shouldHaveResponse q l = do r <- lastfm q case preview (_Right.l) r of Just _ -> return () Nothing -> assertFailure (printf "Query failed on %s" (show r)) shouldHaveJson :: Request JSON Ready -> Fold Value a -> Expectation shouldHaveJson = shouldHaveResponse shouldHaveXml :: Request XML Ready -> Fold Document a -> Expectation shouldHaveXml = shouldHaveResponse -- | Check success stuff for POST requests shouldHaveJson_ :: Request JSON Ready -> Expectation shouldHaveJson_ l = shouldHaveResponse l (key "status".only "ok") shouldHaveXml_ :: Request XML Ready -> Expectation shouldHaveXml_ l = shouldHaveResponse l (root.attributed (ix "status".only "ok")) -- | Make a request using public API key publicly :: Request f (APIKey -> Ready) -> Request f Ready publicly r = r <*> publicKey -- | API Key used for requests that do not require authentification publicKey :: Request f APIKey publicKey = apiKey "234fc6e0f41f6ef99b7bd62ebaf8d318" -- | Environment is missing a variable data EnvironmentMissing = EnvironmentMissing String deriving (Show, Eq, Typeable) instance Exception EnvironmentMissing -- $awful -- | Make a request signed by a secret using private API and session keys privately :: Request f (APIKey -> SessionKey -> Sign) -> Request f Ready privately r = sign privateSecret $ r <*> privateAPIKey <*> privateSessionKey privateAPIKey :: Request f APIKey privateAPIKey = apiKey (liblastfmEnv "HASKELL_LIBLASTFM_APIKEY") privateSessionKey :: Request f SessionKey privateSessionKey = sessionKey (liblastfmEnv "HASKELL_LIBLASTFM_SESSIONKEY") privateSecret :: Secret privateSecret = Secret (liblastfmEnv "HASKELL_LIBLASTFM_SECRET") -- | Get an environment variable or throw a 'EnvironmentMissing' exception liblastfmEnv :: String -> Text liblastfmEnv var = unsafePerformIO $ do mv <- lookupEnv var case mv of Just v -> return (pack v) Nothing -> throwIO (EnvironmentMissing var)