elm-pages-v3-beta/tests/ServerRequestTest.elm

245 lines
8.3 KiB
Elm
Raw Normal View History

module ServerRequestTest exposing (all)
2022-02-26 20:38:03 +03:00
import Dict exposing (Dict)
import Expect exposing (Expectation)
2022-02-26 20:38:03 +03:00
import FormData
import Internal.Request exposing (Parser(..))
2022-02-26 20:38:03 +03:00
import Json.Decode as Decode
import Json.Encode
2022-02-26 20:38:03 +03:00
import List.NonEmpty as NonEmpty exposing (NonEmpty)
import Server.Request as Request
2022-02-26 20:48:36 +03:00
import Test exposing (Test, describe, test)
all : Test
all =
describe "Server.Request matching"
[ test "succeed always matches" <|
\() ->
Request.succeed ()
|> expectMatch
{ method = Request.Get
, headers = []
2022-01-24 06:30:48 +03:00
, body = Nothing
}
, test "accept GET" <|
\() ->
Request.succeed ()
|> Request.acceptMethod ( Request.Get, [] )
|> expectMatch
{ method = Request.Get
, headers = []
2022-01-24 06:30:48 +03:00
, body = Nothing
}
, test "accept GET doesn't match POST" <|
\() ->
Request.succeed ()
|> Request.acceptMethod ( Request.Post, [] )
|> expectNoMatch
{ method = Request.Get
, headers = []
2022-01-24 06:30:48 +03:00
, body = Nothing
}
"Expected HTTP method POST but was GET"
, test "unexpected method for form POST" <|
\() ->
Request.expectFormPost
(\_ ->
Request.succeed ()
)
|> expectNoMatch
{ method = Request.Get
, headers =
[ ( "content-type", "application/x-www-form-urlencoded" )
]
2022-01-24 06:30:48 +03:00
, body = Nothing
}
"expectFormPost did not match - expected method POST, but the method was GET"
2022-01-25 02:43:05 +03:00
, test "tries multiple form post formats" <|
\() ->
Request.oneOf
[ Request.oneOf
[ Request.expectFormPost
(\{ field } ->
field "bar"
)
, Request.expectFormPost
(\{ field } ->
field "foo"
)
]
]
|> expectMatch
{ method = Request.Post
, headers =
[ ( "content-type", "application/x-www-form-urlencoded" )
]
2022-02-26 20:38:03 +03:00
, body =
2022-01-25 02:43:05 +03:00
Just
2022-02-26 20:38:03 +03:00
(FormData
(Dict.fromList [ ( "foo", NonEmpty.singleton "bar" ) ])
)
2022-01-25 02:43:05 +03:00
}
, test "expectFormPost with missing content-type" <|
\() ->
Request.expectFormPost
(\{ field } ->
field "bar"
)
|> expectNoMatch
{ method = Request.Post
, headers =
[ ( "content_type", "application/x-www-form-urlencoded" )
]
, body =
Just
(FormData
(Dict.fromList [ ( "foo", NonEmpty.singleton "bar" ) ])
)
}
"""expectFormPost did not match - Was form POST but expected content-type `application/x-www-form-urlencoded` but the request didn't have a content-type header"""
2021-12-31 07:22:26 +03:00
, test "one of no match" <|
\() ->
Request.oneOf
[ Request.expectFormPost
2022-01-28 03:03:42 +03:00
(\{ field } ->
2021-12-31 07:22:26 +03:00
field "first"
)
2022-02-26 20:38:03 +03:00
, Request.expectJsonBody (Decode.field "first" Decode.string)
2021-12-31 07:22:26 +03:00
, Request.expectQueryParam "first"
, Request.expectMultiPartFormPost
2022-01-28 03:03:42 +03:00
(\{ field } ->
2021-12-31 07:22:26 +03:00
field "first"
)
]
|> expectNoMatch
{ method = Request.Get
, headers =
[ ( "content-type", "application/x-www-form-urlencoded" )
]
2022-01-24 06:30:48 +03:00
, body = Nothing
2021-12-31 07:22:26 +03:00
}
"""Server.Request.oneOf failed in the following 4 ways:
(1) expectFormPost did not match - expected method POST, but the method was GET
2021-12-31 07:22:26 +03:00
2022-03-09 20:50:34 +03:00
(2) Expected content-type to be application/json but it was application/x-www-form-urlencoded
2021-12-31 07:22:26 +03:00
2022-02-27 00:32:34 +03:00
(3) Internal error - expected rawUrl field but the adapter script didn't provide one.
2021-12-31 07:22:26 +03:00
2022-03-09 20:50:34 +03:00
(4) Expected content-type to be multipart/form-data but it was application/x-www-form-urlencoded
2021-12-31 07:22:26 +03:00
Expected HTTP method POST but was GET"""
]
type alias Request =
{ method : Request.Method
, headers : List ( String, String )
2022-02-26 20:38:03 +03:00
, body : Maybe Body
}
2022-02-26 20:38:03 +03:00
type Body
= FormData (Dict String (NonEmpty String))
| JsonBody Decode.Value
| StringBody String
expectMatch : Request -> Request.Parser value -> Expectation
expectMatch request (Parser decoder) =
case
request
|> requestToJson
2022-02-26 20:38:03 +03:00
|> Decode.decodeValue decoder
of
Ok ok ->
case ok of
2022-01-28 03:03:42 +03:00
( Ok _, [] ) ->
Expect.pass
( Err innerError, otherErrors ) ->
(innerError :: otherErrors)
|> List.map Request.errorToString
|> String.join "\n"
|> Expect.fail
( Ok _, nonEmptyErrors ) ->
nonEmptyErrors
|> List.map Request.errorToString
|> String.join "\n"
|> Expect.fail
Err error ->
2022-02-26 20:38:03 +03:00
Expect.fail (Decode.errorToString error)
expectNoMatch : Request -> String -> Request.Parser value -> Expectation
expectNoMatch request expectedErrorString (Parser decoder) =
case
request
|> requestToJson
2022-02-26 20:38:03 +03:00
|> Decode.decodeValue decoder
of
Ok ok ->
case ok of
2022-01-28 03:03:42 +03:00
( Ok _, [] ) ->
Expect.fail "Expected this request not to match, but instead it did match."
( Err innerError, otherErrors ) ->
(innerError :: otherErrors)
|> List.map Request.errorToString
|> String.join "\n"
|> Expect.equal expectedErrorString
( Ok _, nonEmptyErrors ) ->
nonEmptyErrors
|> List.map Request.errorToString
|> String.join "\n"
|> Expect.equal expectedErrorString
Err error ->
Expect.fail
("Expected this request to not match, but instead there was an internal error: "
2022-02-26 20:38:03 +03:00
++ Decode.errorToString error
)
requestToJson : Request -> Json.Encode.Value
requestToJson request =
Json.Encode.object
[ ( "method"
, request.method
|> Request.methodToString
|> Json.Encode.string
)
, ( "headers"
, Json.Encode.object
(List.map
(Tuple.mapSecond
Json.Encode.string
)
request.headers
)
)
2022-02-26 20:38:03 +03:00
, ( "body"
, request.body
|> Maybe.map encodeBody
2022-01-24 07:05:05 +03:00
|> Maybe.withDefault Json.Encode.null
)
2021-12-31 07:22:26 +03:00
, ( "query", Json.Encode.null )
, ( "multiPartFormData", Json.Encode.null )
]
2022-02-26 20:38:03 +03:00
encodeBody : Body -> Decode.Value
encodeBody body =
case body of
JsonBody json ->
json
FormData formData ->
formData |> FormData.encode |> Json.Encode.string
StringBody string ->
string |> Json.Encode.string