2021-12-30 22:42:49 +03:00
|
|
|
module ServerRequestTest exposing (all)
|
|
|
|
|
2022-02-26 20:38:03 +03:00
|
|
|
import Dict exposing (Dict)
|
2021-12-30 22:42:49 +03:00
|
|
|
import Expect exposing (Expectation)
|
2022-07-09 04:00:30 +03:00
|
|
|
import Form
|
2022-07-09 03:56:52 +03:00
|
|
|
import Form.Field as Field
|
2022-07-09 03:51:26 +03:00
|
|
|
import Form.Validation as Validation
|
2022-02-26 20:38:03 +03:00
|
|
|
import FormData
|
2022-03-09 20:29:11 +03:00
|
|
|
import Internal.Request exposing (Parser(..))
|
2022-02-26 20:38:03 +03:00
|
|
|
import Json.Decode as Decode
|
2021-12-30 22:42:49 +03:00
|
|
|
import Json.Encode
|
|
|
|
import Server.Request as Request
|
2022-02-26 20:48:36 +03:00
|
|
|
import Test exposing (Test, describe, test)
|
2021-12-30 22:42:49 +03:00
|
|
|
|
|
|
|
|
|
|
|
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
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString = Nothing
|
2021-12-30 22:42:49 +03:00
|
|
|
}
|
|
|
|
, test "accept GET" <|
|
|
|
|
\() ->
|
|
|
|
Request.succeed ()
|
|
|
|
|> Request.acceptMethod ( Request.Get, [] )
|
|
|
|
|> expectMatch
|
|
|
|
{ method = Request.Get
|
|
|
|
, headers = []
|
2022-01-24 06:30:48 +03:00
|
|
|
, body = Nothing
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString = Nothing
|
2021-12-30 22:42:49 +03:00
|
|
|
}
|
|
|
|
, 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
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString = Nothing
|
2021-12-30 22:42:49 +03:00
|
|
|
}
|
|
|
|
"Expected HTTP method POST but was GET"
|
2022-07-05 19:56:27 +03:00
|
|
|
, test "formData extracts fields from query params for GET" <|
|
2021-12-30 22:42:49 +03:00
|
|
|
\() ->
|
2022-07-09 18:03:02 +03:00
|
|
|
Request.rawFormData
|
2022-06-30 18:18:53 +03:00
|
|
|
|> Request.map
|
2022-07-05 19:56:27 +03:00
|
|
|
(\formData ->
|
|
|
|
formData
|
2022-06-30 18:18:53 +03:00
|
|
|
)
|
2022-07-05 19:56:27 +03:00
|
|
|
|> expectMatchWith
|
2021-12-30 22:42:49 +03:00
|
|
|
{ method = Request.Get
|
2022-07-05 19:56:27 +03:00
|
|
|
, headers = []
|
2022-01-24 06:30:48 +03:00
|
|
|
, body = Nothing
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString = Just "q=hello"
|
2021-12-30 22:42:49 +03:00
|
|
|
}
|
2022-07-05 19:56:27 +03:00
|
|
|
[ ( "q", "hello" ) ]
|
2022-01-25 02:43:05 +03:00
|
|
|
, test "tries multiple form post formats" <|
|
|
|
|
\() ->
|
2022-08-03 11:01:22 +03:00
|
|
|
Request.formData
|
2022-07-24 10:11:12 +03:00
|
|
|
[ Form.init
|
2022-06-30 18:18:53 +03:00
|
|
|
(\bar ->
|
2022-07-23 21:29:03 +03:00
|
|
|
{ combine =
|
|
|
|
Validation.succeed identity
|
|
|
|
|> Validation.andMap bar
|
|
|
|
, view =
|
|
|
|
\_ -> ()
|
|
|
|
}
|
2022-06-30 18:18:53 +03:00
|
|
|
)
|
2022-07-24 10:11:12 +03:00
|
|
|
|> Form.field "bar" Field.text
|
|
|
|
, Form.init
|
2022-06-30 18:18:53 +03:00
|
|
|
(\bar ->
|
2022-07-23 21:29:03 +03:00
|
|
|
{ combine =
|
|
|
|
Validation.succeed identity
|
|
|
|
|> Validation.andMap bar
|
|
|
|
, view =
|
|
|
|
\_ -> ()
|
|
|
|
}
|
2022-06-30 18:18:53 +03:00
|
|
|
)
|
2022-07-24 10:11:12 +03:00
|
|
|
|> Form.field "foo" Field.text
|
2022-01-25 02:43:05 +03:00
|
|
|
]
|
|
|
|
|> 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
|
2022-06-30 20:54:24 +03:00
|
|
|
(Dict.fromList [ ( "foo", ( "bar", [] ) ) ])
|
2022-02-26 20:38:03 +03:00
|
|
|
)
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString = Nothing
|
2022-01-25 02:43:05 +03:00
|
|
|
}
|
2022-04-07 19:24:32 +03:00
|
|
|
, test "expectFormPost with missing content-type" <|
|
|
|
|
\() ->
|
2022-08-03 11:01:22 +03:00
|
|
|
Request.formData
|
2022-07-24 10:11:12 +03:00
|
|
|
[ Form.init
|
2022-06-30 18:18:53 +03:00
|
|
|
(\bar ->
|
2022-07-23 21:29:03 +03:00
|
|
|
{ combine =
|
|
|
|
Validation.succeed identity
|
|
|
|
|> Validation.andMap bar
|
|
|
|
, view =
|
|
|
|
\_ -> ()
|
|
|
|
}
|
2022-06-30 18:18:53 +03:00
|
|
|
)
|
2022-07-24 10:11:12 +03:00
|
|
|
|> Form.field "bar" Field.text
|
2022-06-30 18:18:53 +03:00
|
|
|
]
|
2022-04-07 19:24:32 +03:00
|
|
|
|> expectNoMatch
|
|
|
|
{ method = Request.Post
|
|
|
|
, headers =
|
|
|
|
[ ( "content_type", "application/x-www-form-urlencoded" )
|
|
|
|
]
|
|
|
|
, body =
|
|
|
|
Just
|
|
|
|
(FormData
|
2022-06-30 20:54:24 +03:00
|
|
|
(Dict.fromList [ ( "foo", ( "bar", [] ) ) ])
|
2022-04-07 19:24:32 +03:00
|
|
|
)
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString = Nothing
|
2022-04-07 19:24:32 +03:00
|
|
|
}
|
|
|
|
"""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
|
|
|
|
2022-06-30 18:18:53 +03:00
|
|
|
-- , test "one of no match" <|
|
|
|
|
-- \() ->
|
|
|
|
-- Request.oneOf
|
|
|
|
-- [ --Request.formParserResultNew
|
|
|
|
-- -- [ Form.init
|
|
|
|
-- -- (\bar ->
|
|
|
|
-- -- Validation.succeed identity
|
2022-07-09 18:30:13 +03:00
|
|
|
-- -- |> Validation.andMap bar
|
2022-06-30 18:18:53 +03:00
|
|
|
-- -- )
|
|
|
|
-- -- (\_ _ -> ())
|
|
|
|
-- -- |> Form.field "first" Field.text
|
|
|
|
-- -- ],
|
|
|
|
-- Request.expectJsonBody (Decode.field "first" Decode.string)
|
|
|
|
-- , Request.expectQueryParam "first"
|
|
|
|
-- , Request.expectMultiPartFormPost
|
|
|
|
-- (\{ field } ->
|
|
|
|
-- field "first"
|
|
|
|
-- )
|
|
|
|
-- ]
|
|
|
|
-- |> expectNoMatch
|
|
|
|
-- { method = Request.Get
|
|
|
|
-- , headers =
|
|
|
|
-- [ ( "content-type", "application/x-www-form-urlencoded" )
|
|
|
|
-- ]
|
|
|
|
-- , body = Nothing
|
|
|
|
-- }
|
|
|
|
-- """Server.Request.oneOf failed in the following 4 ways:
|
|
|
|
--
|
|
|
|
--(1) expectFormPost did not match - expected method POST, but the method was GET
|
|
|
|
--
|
|
|
|
--(2) Expected content-type to be application/json but it was application/x-www-form-urlencoded
|
|
|
|
--
|
|
|
|
--(3) Internal error - expected rawUrl field but the adapter script didn't provide one.
|
|
|
|
--
|
|
|
|
--(4) Expected content-type to be multipart/form-data but it was application/x-www-form-urlencoded
|
|
|
|
--Expected HTTP method POST but was GET"""
|
2021-12-30 22:42:49 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
type alias Request =
|
|
|
|
{ method : Request.Method
|
|
|
|
, headers : List ( String, String )
|
2022-02-26 20:38:03 +03:00
|
|
|
, body : Maybe Body
|
2022-07-05 19:56:27 +03:00
|
|
|
, urlQueryString : Maybe String
|
2021-12-30 22:42:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-02-26 20:38:03 +03:00
|
|
|
type Body
|
2022-06-30 20:54:24 +03:00
|
|
|
= FormData (Dict String ( String, List String ))
|
2022-02-26 20:38:03 +03:00
|
|
|
| JsonBody Decode.Value
|
|
|
|
| StringBody String
|
|
|
|
|
|
|
|
|
2022-03-08 19:57:46 +03:00
|
|
|
expectMatch : Request -> Request.Parser value -> Expectation
|
2022-03-09 20:29:11 +03:00
|
|
|
expectMatch request (Parser decoder) =
|
2021-12-30 22:42:49 +03:00
|
|
|
case
|
|
|
|
request
|
|
|
|
|> requestToJson
|
2022-02-26 20:38:03 +03:00
|
|
|
|> Decode.decodeValue decoder
|
2021-12-30 22:42:49 +03:00
|
|
|
of
|
|
|
|
Ok ok ->
|
|
|
|
case ok of
|
2022-01-28 03:03:42 +03:00
|
|
|
( Ok _, [] ) ->
|
2021-12-30 22:42:49 +03:00
|
|
|
Expect.pass
|
|
|
|
|
2021-12-31 06:53:37 +03:00
|
|
|
( 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
|
2021-12-30 22:42:49 +03:00
|
|
|
|
|
|
|
Err error ->
|
2022-02-26 20:38:03 +03:00
|
|
|
Expect.fail (Decode.errorToString error)
|
2021-12-30 22:42:49 +03:00
|
|
|
|
|
|
|
|
2022-07-05 19:56:27 +03:00
|
|
|
expectMatchWith : Request -> value -> Request.Parser value -> Expectation
|
|
|
|
expectMatchWith request expected (Parser decoder) =
|
|
|
|
case
|
|
|
|
request
|
|
|
|
|> requestToJson
|
|
|
|
|> Decode.decodeValue decoder
|
|
|
|
of
|
|
|
|
Ok ok ->
|
|
|
|
case ok of
|
|
|
|
( Ok actual, [] ) ->
|
|
|
|
actual
|
|
|
|
|> Expect.equal expected
|
|
|
|
|
|
|
|
( 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 ->
|
|
|
|
Expect.fail (Decode.errorToString error)
|
|
|
|
|
|
|
|
|
2022-03-08 19:57:46 +03:00
|
|
|
expectNoMatch : Request -> String -> Request.Parser value -> Expectation
|
2022-03-09 20:29:11 +03:00
|
|
|
expectNoMatch request expectedErrorString (Parser decoder) =
|
2021-12-30 22:42:49 +03:00
|
|
|
case
|
|
|
|
request
|
|
|
|
|> requestToJson
|
2022-02-26 20:38:03 +03:00
|
|
|
|> Decode.decodeValue decoder
|
2021-12-30 22:42:49 +03:00
|
|
|
of
|
|
|
|
Ok ok ->
|
|
|
|
case ok of
|
2022-01-28 03:03:42 +03:00
|
|
|
( Ok _, [] ) ->
|
2021-12-30 22:42:49 +03:00
|
|
|
Expect.fail "Expected this request not to match, but instead it did match."
|
|
|
|
|
2021-12-31 06:53:37 +03:00
|
|
|
( 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
|
2021-12-30 22:42:49 +03:00
|
|
|
|
|
|
|
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
|
2021-12-30 22:42:49 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
)
|
2022-07-05 19:56:27 +03:00
|
|
|
, ( "query"
|
|
|
|
, Json.Encode.object
|
|
|
|
[ ( "q", Json.Encode.string "hello" )
|
|
|
|
]
|
|
|
|
)
|
|
|
|
, ( "rawUrl"
|
|
|
|
, Json.Encode.string
|
|
|
|
("http://localhost:1234/"
|
|
|
|
++ (request.urlQueryString |> Maybe.map (\q -> "?" ++ q) |> Maybe.withDefault "")
|
|
|
|
)
|
|
|
|
)
|
2021-12-31 07:22:26 +03:00
|
|
|
, ( "multiPartFormData", Json.Encode.null )
|
2021-12-30 22:42:49 +03:00
|
|
|
]
|
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
|