hal-0.4.7: test/Spec.hs
import AWS.Lambda.Context (ClientApplication (..),
ClientContext (..),
CognitoIdentity (..),
LambdaContext (..))
import AWS.Lambda.Internal (StaticContext (..))
import AWS.Lambda.RuntimeClient.Internal (eventResponseToNextData)
import Data.Aeson (Value (Null))
import Data.Map (singleton)
import Data.Semigroup ((<>))
import Data.Time.Clock.POSIX (posixSecondsToUTCTime)
import Network.HTTP.Client.Internal (Response (..))
import Network.HTTP.Types (Header)
import Test.Hspec (describe, it, shouldBe,
shouldStartWith)
import Test.Hspec.Runner (hspec)
main :: IO ()
main =
hspec $ do
describe "Event Response Data" $ do
let staticContext =
StaticContext
{ functionName = "name"
, functionVersion = "version"
, functionMemorySize = 128
, logGroupName = "logGroupName"
, logStreamName = "logStreamName"
}
let basicValidHeaders =
[ ("Lambda-Runtime-Aws-Request-Id", "abc")
, ("Lambda-Runtime-Trace-Id", "123")
, ("Lambda-Runtime-Invoked-Function-Arn", "arn")
, ("Lambda-Runtime-Deadline-Ms", "12332000")
]
it "Works given valid inputs" $ do
let inputBody = Null
let response = minResponse basicValidHeaders inputBody
let (id, outputBody, context) =
eventResponseToNextData staticContext response
id `shouldBe` "abc"
outputBody `shouldBe` inputBody
context `shouldBe`
(Right
(LambdaContext
{ functionName = "name"
, functionVersion = "version"
, functionMemorySize = 128
, logGroupName = "logGroupName"
, logStreamName = "logStreamName"
, awsRequestId = "abc"
, invokedFunctionArn = "arn"
, xRayTraceId = "123"
, deadline = posixSecondsToUTCTime 12332
, clientContext = Nothing
, identity = Nothing
}))
it "has clientContext if it was provided" $ do
let headers =
( "Lambda-Runtime-Client-Context"
, "{ \"client\": { \"appTitle\": \"title\", \"appVersionName\": \"versionName\", \"appVersionCode\": \"versionCode\", \"appPackageName\": \"packageName\" }, \"custom\": { \"key1\": \"value1\" }, \"environment\": { \"key2\": \"value2\" } }") :
basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
fmap clientContext context `shouldBe`
(Right
(Just
(ClientContext
{ client =
ClientApplication
{ appTitle = "title"
, appVersionName = "versionName"
, appVersionCode = "versionCode"
, appPackageName = "packageName"
}
, custom = singleton "key1" "value1"
, environment = singleton "key2" "value2"
})))
it "fails to construct the Context if the client context can't be parsed" $ do
let headers =
("Lambda-Runtime-Client-Context", "{}") : basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
let msg = either id (const (error "Was able to parse a context that should have failed!")) context
msg `shouldStartWith`
"Runtime Error: Unable to decode Context from event response.\nCould not JSON decode header Lambda-Runtime-Client-Context: "
it
"fails to construct the Context if there are two client context headers" $ do
let headers =
[ ("Lambda-Runtime-Client-Context", "{}")
, ("Lambda-Runtime-Client-Context", "{}")
] <>
basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
fmap clientContext context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nToo many values for header Lambda-Runtime-Client-Context")
it "has identity if it was provided" $ do
let headers =
( "Lambda-Runtime-Cognito-Identity"
, "{ \"identityId\": \"identityId\", \"identityPoolId\": \"identityPoolId\" }") :
basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
fmap identity context `shouldBe`
(Right
(Just
(CognitoIdentity
{ identityId = "identityId"
, identityPoolId = "identityPoolId"
})))
it
"fails to construct the Context if the cognito identity can't be parsed" $ do
let headers =
("Lambda-Runtime-Cognito-Identity", "{}") : basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
let msg = either id (const (error "Was able to parse a context that should have failed!")) context
msg `shouldStartWith`
"Runtime Error: Unable to decode Context from event response.\nCould not JSON decode header Lambda-Runtime-Cognito-Identity: "
it
"fails to construct the Context if there are two cognito identity headers" $ do
let headers =
[ ("Lambda-Runtime-Cognito-Identity", "{}")
, ("Lambda-Runtime-Cognito-Identity", "{}")
] <>
basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
fmap clientContext context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nToo many values for header Lambda-Runtime-Cognito-Identity")
it "fails to create the context if trace Id is not provided" $ do
let headers =
[ ("Lambda-Runtime-Aws-Request-Id", "abc")
, ("Lambda-Runtime-Invoked-Function-Arn", "arn")
, ("Lambda-Runtime-Deadline-Ms", "12332000")
]
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nMissing response header Lambda-Runtime-Trace-Id")
it "fails to create the context if trace id has multiple values" $ do
let headers = ("Lambda-Runtime-Trace-Id", "123") : basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nToo many values for header Lambda-Runtime-Trace-Id")
it "fails to create the context if function ARN is not provided" $ do
let headers =
[ ("Lambda-Runtime-Aws-Request-Id", "abc")
, ("Lambda-Runtime-Trace-Id", "123")
, ("Lambda-Runtime-Deadline-Ms", "12332000")
]
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nMissing response header Lambda-Runtime-Invoked-Function-Arn")
it "fails to create the context if function ARN has multiple values" $ do
let headers =
("Lambda-Runtime-Invoked-Function-Arn", "arn") : basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nToo many values for header Lambda-Runtime-Invoked-Function-Arn")
it "fails to create the context if a deadline is not provided" $ do
let headers =
[ ("Lambda-Runtime-Aws-Request-Id", "abc")
, ("Lambda-Runtime-Trace-Id", "123")
, ("Lambda-Runtime-Invoked-Function-Arn", "arn")
]
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nMissing response header Lambda-Runtime-Deadline-Ms")
it "fails to create the context if the deadline has multiple values" $ do
let headers =
("Lambda-Runtime-Deadline-Ms", "12332000") : basicValidHeaders
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nToo many values for header Lambda-Runtime-Deadline-Ms")
it "fails to create the context if the deadline is not a valid timestamp" $ do
let headers =
[ ("Lambda-Runtime-Aws-Request-Id", "abc")
, ("Lambda-Runtime-Trace-Id", "123")
, ("Lambda-Runtime-Invoked-Function-Arn", "arn")
, ("Lambda-Runtime-Deadline-Ms", "not a timestamp")
]
let (_, _, context) =
eventResponseToNextData staticContext (minJsonResponse headers)
context `shouldBe`
(Left
"Runtime Error: Unable to decode Context from event response.\nCould not parse deadline")
minResponse :: [Header] -> a -> Response a
minResponse headers body =
Response
{ responseStatus = undefined
, responseVersion = undefined
, responseHeaders = headers
, responseBody = body
, responseCookieJar = undefined
, responseClose' = undefined
}
minJsonResponse :: [Header] -> Response Value
minJsonResponse = flip minResponse Null