2023-11-26 21:59:53 +00:00
|
|
|
module Test.Main where
|
|
|
|
|
|
|
|
import Prelude hiding ((/), (#))
|
|
|
|
|
|
|
|
import Control.Monad.Error.Class (liftMaybe, throwError)
|
2023-12-28 23:56:07 +00:00
|
|
|
import Data.Either (Either(..), isRight)
|
2023-11-26 21:59:53 +00:00
|
|
|
import Data.Map as Map
|
|
|
|
import Data.Maybe (Maybe(..), maybe)
|
|
|
|
import Data.Traversable (for_)
|
|
|
|
import Data.Tuple.Nested ((/\))
|
2023-12-28 23:56:07 +00:00
|
|
|
import Data.URL (Path(..), URL, pathOrURLFromString, resolveString, toString, (#), (&), (/), (?))
|
2023-11-26 21:59:53 +00:00
|
|
|
import Data.URL as URL
|
|
|
|
import Effect (Effect)
|
|
|
|
import Effect.Aff (Aff, launchAff_)
|
|
|
|
import Effect.Exception (error)
|
|
|
|
import Test.Spec (describe, it)
|
|
|
|
import Test.Spec.Assertions (shouldEqual)
|
|
|
|
import Test.Spec.Reporter.Console (consoleReporter)
|
|
|
|
import Test.Spec.Runner (runSpec)
|
|
|
|
|
|
|
|
main :: Effect Unit
|
|
|
|
main = launchAff_ $ runSpec [ consoleReporter ] do
|
|
|
|
describe "URL" do
|
|
|
|
let
|
|
|
|
fromString_ :: String -> Aff URL
|
|
|
|
fromString_ u = liftMaybe (error $ "parsing failed: " <> u) $ URL.fromString u
|
|
|
|
|
|
|
|
describe "fromString" do
|
|
|
|
it "returns Just on valid URL" do
|
|
|
|
void $ fromString_ "https://google.com"
|
|
|
|
void $ fromString_ "http://localhost?foo=bar&foo&foo&bar=baz"
|
|
|
|
void $ fromString_ "postgresql://user:pass@1.2.3.4:5432/dbname"
|
|
|
|
it "returns Nothing on invalid URL" do
|
|
|
|
let
|
|
|
|
case_ :: String -> Aff Unit
|
|
|
|
case_ u = maybe (pure unit) (const $ throwError $ error $ "parsing erroneously succeeded: " <> u) $ URL.fromString u
|
|
|
|
case_ "google.com"
|
|
|
|
case_ "localhost"
|
|
|
|
case_ "http://?feai#dfkvsj"
|
|
|
|
|
2023-12-28 23:56:07 +00:00
|
|
|
describe "pathOrURLFromString" do
|
|
|
|
it "returns Right on valid URL" do
|
|
|
|
isRight (pathOrURLFromString "https://google.com") `shouldEqual` true
|
|
|
|
isRight (pathOrURLFromString "http://localhost?foo=bar&foo&foo&bar=baz") `shouldEqual` true
|
|
|
|
isRight (pathOrURLFromString "postgresql://user:pass@1.2.3.4:5432/dbname") `shouldEqual` true
|
|
|
|
it "returns Left on anything else" do
|
|
|
|
(pathOrURLFromString "/foo") `shouldEqual` (Left $ PathAbsolute [ "foo" ])
|
|
|
|
(pathOrURLFromString "./../../foo") `shouldEqual` (Left $ PathRelative [ ".", "..", "..", "foo" ])
|
|
|
|
(pathOrURLFromString "foo") `shouldEqual` (Left $ PathRelative [ "foo" ])
|
|
|
|
(pathOrURLFromString "") `shouldEqual` (Left PathEmpty)
|
|
|
|
(pathOrURLFromString "941389dfajifdjiao34910fd#$@?!") `shouldEqual` (Left $ PathRelative [ "941389dfajifdjiao34910fd#$@?!" ])
|
|
|
|
|
|
|
|
describe "resolveString" do
|
|
|
|
it "works" do
|
|
|
|
(shouldEqual "https://google.com/foo")
|
|
|
|
=<< toString
|
|
|
|
<$> resolveString "/foo"
|
|
|
|
<$> fromString_ "https://google.com/a/b/c/d/e"
|
|
|
|
(shouldEqual "https://google.com/foo/bar/baz/a")
|
|
|
|
=<< toString
|
|
|
|
<$> resolveString "./a"
|
|
|
|
<$> fromString_ "https://google.com/foo/bar/baz"
|
|
|
|
(shouldEqual "https://google.com/foo/a")
|
|
|
|
=<< toString
|
|
|
|
<$> resolveString "../../a"
|
|
|
|
<$> fromString_ "https://google.com/foo/bar/baz"
|
|
|
|
(shouldEqual "https://cheese.com/foo/bar")
|
|
|
|
=<< toString
|
|
|
|
<$> resolveString "https://cheese.com/foo/bar"
|
|
|
|
<$> fromString_ "https://google.com/foo/bar/baz"
|
|
|
|
|
2023-11-26 21:59:53 +00:00
|
|
|
describe "toString" do
|
|
|
|
it "stringifies" do
|
|
|
|
let
|
|
|
|
case_ :: String -> Aff Unit
|
|
|
|
case_ u = do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.toString url `shouldEqual` u
|
|
|
|
case_ "https://google.com/"
|
|
|
|
case_ "http://localhost/?foo=bar&foo&foo&bar=baz"
|
|
|
|
case_ "postgresql://user:pass@1.2.3.4:5432/dbname"
|
|
|
|
|
|
|
|
describe "get" do
|
|
|
|
describe "path" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com/foo" /\ URL.PathAbsolute [ "foo" ]
|
|
|
|
, "http://localhost/bar?foo=bar" /\ URL.PathAbsolute [ "bar" ]
|
|
|
|
, "http://1.1.1.1:4142/asdf/foo/bingus#asdf" /\ URL.PathAbsolute [ "asdf", "foo", "bingus" ]
|
|
|
|
, "https://google.com/" /\ URL.PathEmpty
|
|
|
|
, "http://localhost/?foo=bar" /\ URL.PathEmpty
|
|
|
|
, "http://1.1.1.1:4142/#asdf" /\ URL.PathEmpty
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) -> it (u <> " -> " <> show expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.path url `shouldEqual` expect
|
|
|
|
|
|
|
|
describe "query" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ Map.empty
|
|
|
|
, "https://google.com?k " /\ Map.singleton "k" [ "" ]
|
|
|
|
, "https://google.com?k&k&k " /\ Map.singleton "k" [ "", "", "" ]
|
|
|
|
, "https://localhost/foo?q#a" /\ Map.singleton "q" [ "" ]
|
|
|
|
, "https://a?a=a&b=b&b=c " /\ Map.fromFoldable [ "a" /\ [ "a" ], "b" /\ [ "b", "c" ] ]
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) -> it (u <> " -> " <> show expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
let qs = URL.query url
|
|
|
|
qs `shouldEqual` expect
|
|
|
|
describe "host" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ "google.com"
|
|
|
|
, "https://localhost " /\ "localhost"
|
|
|
|
, "https://1.1.1.1 " /\ "1.1.1.1"
|
|
|
|
, "https://1.1.1.1:5432" /\ "1.1.1.1"
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) -> it (u <> " -> " <> expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.host url `shouldEqual` expect
|
|
|
|
describe "port" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ Nothing
|
|
|
|
, "https://localhost " /\ Nothing
|
|
|
|
, "https://1.1.1.1 " /\ Nothing
|
|
|
|
, "https://1.1.1.1:5432" /\ Just 5432
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) -> it (u <> " -> " <> show expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.port url `shouldEqual` expect
|
|
|
|
describe "hash" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ Nothing
|
|
|
|
, "https://google.com#foo" /\ Just "foo"
|
|
|
|
, "https://localhost " /\ Nothing
|
|
|
|
, "https://1.1.1.1:5432 " /\ Nothing
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) -> it (u <> " -> " <> show expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.hash url `shouldEqual` expect
|
|
|
|
describe "username" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ Nothing
|
|
|
|
, "https://google.com#foo " /\ Nothing
|
|
|
|
, "https://:bar@google.com " /\ Nothing
|
|
|
|
, "https://foo@localhost " /\ Just "foo"
|
|
|
|
, "https://foo:bar@localhost" /\ Just "foo"
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) -> it (u <> " -> " <> show expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.username url `shouldEqual` expect
|
|
|
|
describe "password" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ Nothing
|
|
|
|
, "https://google.com#foo " /\ Nothing
|
|
|
|
, "https://:bar@google.com " /\ Just "bar"
|
|
|
|
, "https://foo@localhost " /\ Nothing
|
|
|
|
, "https://foo:bar@localhost" /\ Just "bar"
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) ->
|
|
|
|
it (u <> " -> " <> show expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.password url `shouldEqual` expect
|
|
|
|
describe "protocol" do
|
|
|
|
let
|
|
|
|
cases =
|
|
|
|
[ "https://google.com " /\ "https"
|
|
|
|
, "https://google.com#foo" /\ "https"
|
|
|
|
, "http://:bar@google.com" /\ "http"
|
|
|
|
, "http://1.1.1.1 " /\ "http"
|
|
|
|
, "coap://1.1.1.1 " /\ "coap"
|
|
|
|
, "ssh://1.1.1.1 " /\ "ssh"
|
|
|
|
, "data:text/plain,foo " /\ "data"
|
|
|
|
]
|
|
|
|
for_ cases \(u /\ expect) ->
|
|
|
|
it (u <> " -> " <> expect) do
|
|
|
|
url <- fromString_ u
|
|
|
|
URL.protocol url `shouldEqual` expect
|
|
|
|
describe "set" do
|
|
|
|
it "resolve" do
|
|
|
|
u <- fromString_ "https://google.com/search"
|
|
|
|
let
|
|
|
|
rel = URL.resolve (URL.PathRelative [ "foo", "bar" ]) u
|
|
|
|
abs = URL.resolve (URL.PathAbsolute [ "foo", "bar" ]) u
|
|
|
|
URL.toString rel `shouldEqual` "https://google.com/search/foo/bar"
|
|
|
|
URL.toString abs `shouldEqual` "https://google.com/foo/bar"
|
|
|
|
it "setQuery" do
|
|
|
|
u <- fromString_ "https://google.com?k"
|
|
|
|
let
|
|
|
|
u' = URL.setQuery (Map.fromFoldable [ "a" /\ [ "b", "" ] ]) u
|
|
|
|
URL.toString u' `shouldEqual` "https://google.com/?a=b&a="
|
|
|
|
it "setters do not mutate original url" do
|
|
|
|
url <- fromString_ "https://google.com/"
|
|
|
|
let
|
|
|
|
foo = URL.setHost "foo.com" url
|
|
|
|
fooBuilt =
|
|
|
|
URL.setUsername "user"
|
|
|
|
$ URL.setPassword "pass"
|
|
|
|
$ URL.setProtocol "https"
|
|
|
|
$ URL.setPort 1234
|
|
|
|
$ foo / "cheese" / "brie" ? "k" /\ "v" & "k" # "foo"
|
|
|
|
URL.toString url `shouldEqual` "https://google.com/"
|
|
|
|
URL.toString fooBuilt `shouldEqual` "https://user:pass@foo.com:1234/cheese/brie?k=&k=v#foo"
|