packages feed

servant-hmac-auth-0.1.4: test/Servant/Auth/Hmac/CryptoSpec.hs

{-# LANGUAGE TemplateHaskellQuotes #-}

module Servant.Auth.Hmac.CryptoSpec (spec) where

import Data.CaseInsensitive
import Data.Text (Text)
import qualified Data.Text as Text
import qualified Data.Text.Encoding as TE
import qualified Data.Text.IO as TIO
import Network.HTTP.Types
import Servant.Auth.Hmac.Crypto (RequestPayload (..), SecretKey (..), Signature (..), requestSignature, signSHA256)
import System.FilePath
import Test.Hspec
import Test.Hspec.Golden

goldenTest :: String -> Text -> Golden Text
goldenTest name actualOutput =
    Golden
        { output = actualOutput
        , encodePretty = Text.unpack
        , writeToFile = TIO.writeFile
        , readFromFile = TIO.readFile
        , goldenFile = ".golden" </> name </> "golden"
        , actualFile = Just (".golden" </> name </> "actual")
        , failFirstTime = False
        }

sha256Scenarios :: [(SecretKey, RequestPayload)]
sha256Scenarios =
    [ (SecretKey "Some-s3cr3t", RequestPayload methodGet "" [(mk "Host", "my-server.local")] "my-server.local/test")
    , (SecretKey "s3cret2!", RequestPayload methodPost "This is a text content." [(mk "Host", "www.haskell.server"), (mk "Authentication", "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==")] "www.haskell.server/test")
    , (SecretKey "123456789abcdef", RequestPayload methodPatch "\00HellowORLD" [(mk "Host", "files.myrepository.org"), (mk "Accept-Encoding", "gzip")] "files.myrepository.org/files/4601237722")
    ]

formatResponse :: [Signature] -> Text
formatResponse = Text.unlines . fmap (TE.decodeLatin1 . unSignature)

spec :: Spec
spec =
    describe "requestSignature" $
        context "when using SHA256 for signature" $
            it "should compute the request's signature" $
                let signatures = uncurry (requestSignature signSHA256) <$> sha256Scenarios
                    actualOutput = formatResponse signatures
                 in goldenTest (show 'requestSignature) actualOutput