mirror of
https://github.com/dillonkearns/elm-pages-v3-beta.git
synced 2024-12-23 20:03:31 +03:00
177 lines
4.7 KiB
Elm
177 lines
4.7 KiB
Elm
module RouteTests exposing (..)
|
|
|
|
import Expect
|
|
import List.Extra
|
|
import Regex
|
|
import Test exposing (Test, describe, test)
|
|
|
|
|
|
all : Test
|
|
all =
|
|
describe "routes"
|
|
[ test "test 1" <|
|
|
\() ->
|
|
"/cats/larry"
|
|
|> tryMatch
|
|
{ pattern = "^cats(?:\\/([^/]+))?$"
|
|
, toRoute =
|
|
\matches ->
|
|
case matches of
|
|
[ name ] ->
|
|
Cats__Name__ { name = name } |> Just
|
|
|
|
_ ->
|
|
Nothing
|
|
}
|
|
|> Expect.equal (Cats__Name__ { name = Just "larry" } |> Just)
|
|
, test "test 2" <|
|
|
\() ->
|
|
"/cats"
|
|
|> tryMatch
|
|
{ pattern = "^cats(?:\\/([^/]+))?$"
|
|
, toRoute =
|
|
\matches ->
|
|
case matches of
|
|
[ name ] ->
|
|
Cats__Name__ { name = name } |> Just
|
|
|
|
_ ->
|
|
Nothing
|
|
}
|
|
|> Expect.equal (Cats__Name__ { name = Nothing } |> Just)
|
|
, test "multiple matchers" <|
|
|
\() ->
|
|
"/slide/123"
|
|
|> firstMatch exampleMatchers
|
|
|> Expect.equal (Slide__Number_ { number = "123" } |> Just)
|
|
, test "hardcoded routes have precedence over dynamic segments" <|
|
|
\() ->
|
|
"/post/create"
|
|
|> firstMatch postPrecedenceExample
|
|
|> Expect.equal (Post__Create {} |> Just)
|
|
, test "dynamic segments match when they are not overshadowed by a hardcoded route" <|
|
|
\() ->
|
|
"/post/update"
|
|
|> firstMatch postPrecedenceExample
|
|
|> Expect.equal (Post__Slug_ { slug = "update" } |> Just)
|
|
]
|
|
|
|
|
|
exampleMatchers : List (Matcher Route)
|
|
exampleMatchers =
|
|
[ { pattern = "^cats(?:\\/([^/]+))?$"
|
|
, toRoute =
|
|
\matches ->
|
|
case matches of
|
|
[ name ] ->
|
|
Cats__Name__ { name = name } |> Just
|
|
|
|
_ ->
|
|
Nothing
|
|
}
|
|
, { pattern = "^slide\\/(?:([^/]+))$"
|
|
, toRoute =
|
|
\matches ->
|
|
case matches of
|
|
[ Just number ] ->
|
|
Slide__Number_ { number = number } |> Just
|
|
|
|
_ ->
|
|
Nothing
|
|
}
|
|
]
|
|
|
|
|
|
postPrecedenceExample : List (Matcher Route)
|
|
postPrecedenceExample =
|
|
[ { pattern = "^post\\/create$"
|
|
, toRoute =
|
|
\_ ->
|
|
Just (Post__Create {})
|
|
}
|
|
, { pattern = "^post\\/(?:([^/]+))$"
|
|
, toRoute =
|
|
\matches ->
|
|
case matches of
|
|
[ Just slug ] ->
|
|
Post__Slug_ { slug = slug } |> Just
|
|
|
|
_ ->
|
|
Nothing
|
|
}
|
|
]
|
|
|
|
|
|
firstMatch : List (Matcher Route) -> String -> Maybe Route
|
|
firstMatch matchers path =
|
|
List.Extra.findMap
|
|
(\matcher ->
|
|
if Regex.contains (matcher.pattern |> toRegex) (normalizePath path) then
|
|
tryMatch matcher path
|
|
|
|
else
|
|
Nothing
|
|
)
|
|
matchers
|
|
|
|
|
|
toRegex : String -> Regex.Regex
|
|
toRegex pattern =
|
|
Regex.fromString pattern
|
|
|> Maybe.withDefault Regex.never
|
|
|
|
|
|
type alias Matcher route =
|
|
{ pattern : String, toRoute : List (Maybe String) -> Maybe route }
|
|
|
|
|
|
tryMatch : { pattern : String, toRoute : List (Maybe String) -> Maybe Route } -> String -> Maybe Route
|
|
tryMatch { pattern, toRoute } path =
|
|
path
|
|
|> normalizePath
|
|
|> submatches pattern
|
|
|> toRoute
|
|
|
|
|
|
submatches : String -> String -> List (Maybe String)
|
|
submatches pattern path =
|
|
Regex.find
|
|
(Regex.fromString pattern
|
|
|> Maybe.withDefault Regex.never
|
|
)
|
|
path
|
|
|> List.concatMap .submatches
|
|
|
|
|
|
normalizePath : String -> String
|
|
normalizePath path =
|
|
path
|
|
|> stripLeadingSlash
|
|
|> stripTrailingSlash
|
|
|
|
|
|
stripLeadingSlash : String -> String
|
|
stripLeadingSlash path =
|
|
if path |> String.startsWith "/" then
|
|
String.dropLeft 1 path
|
|
|
|
else
|
|
path
|
|
|
|
|
|
stripTrailingSlash : String -> String
|
|
stripTrailingSlash path =
|
|
if path |> String.endsWith "/" then
|
|
String.dropRight 1 path
|
|
|
|
else
|
|
path
|
|
|
|
|
|
type Route
|
|
= Slide {}
|
|
| Cats__Name__ { name : Maybe String }
|
|
| Slide__Number_ { number : String }
|
|
| Post__Create {}
|
|
| Post__Slug_ { slug : String }
|