aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bin/run-tests.js6
-rw-r--r--src/gleam/should.gleam5
-rw-r--r--src/gleam/uri.gleam110
-rw-r--r--test/gleam/uri_test.gleam94
4 files changed, 145 insertions, 70 deletions
diff --git a/bin/run-tests.js b/bin/run-tests.js
index 46e7963..a142944 100644
--- a/bin/run-tests.js
+++ b/bin/run-tests.js
@@ -11,17 +11,17 @@ async function main() {
for await (let entry of await opendir(dir)) {
if (!entry.name.endsWith("_test.js")) continue;
let path = "../" + dir + entry.name;
- process.stdout.write("\ngleam/" + entry.name.slice(0, -3) + ":\n ");
+ // process.stdout.write("\ngleam/" + entry.name.slice(0, -3) + ":\n ");
let module = await import(path);
for (let fnName of Object.keys(module)) {
if (!fnName.endsWith("_test")) continue;
try {
module[fnName]();
- process.stdout.write("✨");
+ process.stdout.write(`\u001b[${32}m.\u001b[${0}m`);
passes++;
} catch (error) {
- process.stdout.write(`❌ ${fnName}: ${error}\n `);
+ process.stdout.write(`\n❌ ${fnName}: ${error}\n`);
failures++;
}
}
diff --git a/src/gleam/should.gleam b/src/gleam/should.gleam
index 3566dc2..5a636d0 100644
--- a/src/gleam/should.gleam
+++ b/src/gleam/should.gleam
@@ -34,11 +34,10 @@ if javascript {
True -> Nil
_ ->
crash(string.concat([
- "\n",
+ "\n\t",
stringify(a),
- "\nshould equal \n",
+ "\n\tshould equal \n\t",
stringify(b),
- "\n",
]))
}
}
diff --git a/src/gleam/uri.gleam b/src/gleam/uri.gleam
index b40b381..882f17e 100644
--- a/src/gleam/uri.gleam
+++ b/src/gleam/uri.gleam
@@ -7,31 +7,35 @@
//// Query encoding (Form encoding) is defined in the w3c specification.
//// https://www.w3.org/TR/html52/sec-forms.html#urlencoded-form-data
+import gleam/option.{None, Option, Some}
+import gleam/string
+import gleam/int
+
if erlang {
import gleam/list
import gleam/result
- import gleam/option.{None, Option, Some}
- import gleam/string
import gleam/dynamic.{Dynamic}
import gleam/map.{Map}
import gleam/function
import gleam/pair
+}
- /// Type representing holding the parsed components of an URI.
- /// All components of a URI are optional, except the path.
- ///
- pub type Uri {
- Uri(
- scheme: Option(String),
- userinfo: Option(String),
- host: Option(String),
- port: Option(Int),
- path: String,
- query: Option(String),
- fragment: Option(String),
- )
- }
+/// Type representing holding the parsed components of an URI.
+/// All components of a URI are optional, except the path.
+///
+pub type Uri {
+ Uri(
+ scheme: Option(String),
+ userinfo: Option(String),
+ host: Option(String),
+ port: Option(Int),
+ path: String,
+ query: Option(String),
+ fragment: Option(String),
+ )
+}
+if erlang {
pub external fn erl_parse(String) -> Dynamic =
"uri_string" "parse"
@@ -220,47 +224,45 @@ if erlang {
external fn erl_to_string(Map(UriKey, Dynamic)) -> Dynamic =
"uri_string" "recompose"
+}
- /// Encodes a `Uri` value as a URI string.
- ///
- /// The opposite operation is `uri.parse`.
- ///
- /// ## Examples
- ///
- /// ```
- /// > let uri = Uri(Some("http"), None, Some("example.com"), ...)
- /// > to_string(uri)
- ///
- /// "https://example.com"
- /// ```
- ///
- pub fn to_string(uri: Uri) -> String {
- let field = fn(key: UriKey, value: Option(anything)) -> Result(
- #(UriKey, Dynamic),
- Nil,
- ) {
- case value {
- Some(v) -> Ok(#(key, dynamic.from(v)))
- None -> Error(Nil)
- }
- }
-
- [
- field(Scheme, uri.scheme),
- field(Userinfo, uri.userinfo),
- field(Host, uri.host),
- field(Port, uri.port),
- field(Path, option.Some(uri.path)),
- field(Query, uri.query),
- field(Fragment, uri.fragment),
- ]
- |> list.filter_map(fn(x) { x })
- |> map.from_list
- |> erl_to_string
- |> dynamic.string
- |> result.unwrap("")
+/// Encodes a `Uri` value as a URI string.
+///
+/// The opposite operation is `uri.parse`.
+///
+/// ## Examples
+///
+/// ```
+/// > let uri = Uri(Some("http"), None, Some("example.com"), ...)
+/// > to_string(uri)
+///
+/// "https://example.com"
+/// ```
+///
+pub fn to_string(uri: Uri) -> String {
+ // TODO: query
+ // TODO: fragment
+ let parts = []
+ let parts = [uri.path, ..parts]
+ let parts = case uri.host, string.starts_with(uri.path, "/") {
+ Some(_), False -> ["/", ..parts]
+ _, _ -> parts
+ }
+ let parts = case uri.host, uri.port {
+ Some(_), Some(port) -> [":", int.to_string(port), ..parts]
+ _, _ -> parts
}
+ let parts = case uri.scheme, uri.userinfo, uri.host {
+ Some(s), Some(u), Some(h) -> [s, ":", u, "@", h, ..parts]
+ Some(s), None, Some(h) -> [s, "://", h, ..parts]
+ Some(s), Some(_), None | Some(s), None, None -> [s, ":", ..parts]
+ None, None, Some(h) -> ["//", h, ..parts]
+ None, Some(_), None | None, None, None -> parts
+ }
+ string.concat(parts)
+}
+if erlang {
/// Fetches the origin of a uri
///
/// Return the origin of a uri as defined in
diff --git a/test/gleam/uri_test.gleam b/test/gleam/uri_test.gleam
index 9c6d2e0..45fe73e 100644
--- a/test/gleam/uri_test.gleam
+++ b/test/gleam/uri_test.gleam
@@ -1,9 +1,10 @@
+import gleam/uri
+import gleam/should
+import gleam/option.{None, Some}
+
if erlang {
- import gleam/uri
- import gleam/should
import gleam/string
import gleam/list
- import gleam/option.{None, Some}
pub fn full_parse_test() {
assert Ok(parsed) =
@@ -59,12 +60,85 @@ if erlang {
"https://foo:bar@example.com:1234/path?query=true#fragment",
)
}
+}
- pub fn path_only_uri_to_string_test() {
- let test_uri = uri.Uri(None, None, None, None, "/", None, None)
- should.equal(uri.to_string(test_uri), "/")
- }
+pub fn path_only_uri_to_string_test() {
+ uri.Uri(None, None, None, None, "/", None, None)
+ |> uri.to_string
+ |> should.equal("/")
+
+ uri.Uri(None, None, None, None, "/teapot", None, None)
+ |> uri.to_string
+ |> should.equal("/teapot")
+
+ uri.Uri(None, Some("user"), None, None, "/teapot", None, None)
+ |> uri.to_string
+ |> should.equal("/teapot")
+
+ uri.Uri(None, None, None, None, "", None, None)
+ |> uri.to_string
+ |> should.equal("")
+}
+
+pub fn scheme_to_string_test() {
+ uri.Uri(Some("ftp"), None, None, None, "thing.txt", None, None)
+ |> uri.to_string
+ |> should.equal("ftp:thing.txt")
+
+ uri.Uri(Some("ftp"), None, None, None, "", None, None)
+ |> uri.to_string
+ |> should.equal("ftp:")
+
+ uri.Uri(Some("ftp"), Some("ignored"), None, None, "", None, None)
+ |> uri.to_string
+ |> should.equal("ftp:")
+
+ uri.Uri(Some("https"), None, None, None, "/one/two", None, None)
+ |> uri.to_string
+ |> should.equal("https:/one/two")
+}
+pub fn host_to_string_test() {
+ uri.Uri(Some("ftp"), None, Some("example.com"), None, "", None, None)
+ |> uri.to_string
+ |> should.equal("ftp://example.com/")
+
+ uri.Uri(None, None, Some("example.com"), None, "", None, None)
+ |> uri.to_string
+ |> should.equal("//example.com/")
+
+ uri.Uri(None, None, Some("example.com"), None, "/slash", None, None)
+ |> uri.to_string
+ |> should.equal("//example.com/slash")
+
+ uri.Uri(None, None, Some("example.com"), None, "noslash", None, None)
+ |> uri.to_string
+ |> should.equal("//example.com/noslash")
+}
+
+pub fn port_to_string_test() {
+ uri.Uri(Some("ftp"), None, Some("example.com"), Some(80), "", None, None)
+ |> uri.to_string
+ |> should.equal("ftp://example.com:80/")
+
+ uri.Uri(None, None, Some("example.com"), Some(40), "", None, None)
+ |> uri.to_string
+ |> should.equal("//example.com:40/")
+
+ uri.Uri(None, None, Some("example.com"), Some(80), "/slash", None, None)
+ |> uri.to_string
+ |> should.equal("//example.com:80/slash")
+
+ uri.Uri(None, None, Some("example.com"), Some(81), "noslash", None, None)
+ |> uri.to_string
+ |> should.equal("//example.com:81/noslash")
+
+ uri.Uri(None, None, None, Some(81), "noslash", None, None)
+ |> uri.to_string
+ |> should.equal("noslash")
+}
+
+if erlang {
pub fn parse_query_string_test() {
assert Ok(parsed) = uri.parse_query("foo+bar=1&city=%C3%B6rebro")
should.equal(parsed, [#("foo bar", "1"), #("city", "örebro")])
@@ -190,15 +264,15 @@ if erlang {
pub fn origin_test() {
assert Ok(parsed) = uri.parse("http://example.test/path?foo#bar")
uri.origin(parsed)
- |> should.equal(Ok("http://example.test"))
+ |> should.equal(Ok("http://example.test/"))
assert Ok(parsed) = uri.parse("http://example.test:8080")
uri.origin(parsed)
- |> should.equal(Ok("http://example.test:8080"))
+ |> should.equal(Ok("http://example.test:8080/"))
assert Ok(parsed) = uri.parse("https://example.test")
uri.origin(parsed)
- |> should.equal(Ok("https://example.test"))
+ |> should.equal(Ok("https://example.test/"))
assert Ok(parsed) = uri.parse("http:///path")
uri.origin(parsed)