Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions ci/expect_scripts/url.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/expect

# uncomment line below for debugging
# exp_internal 1

set timeout 7

source ./ci/expect_scripts/shared-code.exp

spawn $env(TESTS_DIR)url

expect "Created URL: https://example.com" {
expect "Testing Url.append:" {
expect "URL with append: https://example.com/some%20stuff" {
expect "URL with query and fragment, then appended path: https://example.com/stuff?search=blah#fragment" {
expect "URL with multiple appended paths: https://example.com/things/stuff/more/etc/" {
expect "Testing Url.append_param:" {
expect "URL with appended param: https://example.com?email=someone%40example.com" {
expect "URL with multiple appended params: https://example.com?caf%C3%A9=du%20Monde&email=hi%40example.com" {
expect "Testing Url.has_query:" {
expect "URL with query has_query: Bool.true" {
expect "URL without query has_query: Bool.false" {
expect "Testing Url.has_fragment:" {
expect "URL with fragment has_fragment: Bool.true" {
expect "URL without fragment has_fragment: Bool.false" {
expect "Testing Url.query:" {
expect "Query from URL: key1=val1&key2=val2&key3=val3" {
expect "Query from URL without query: " {
expect "Testing Url.fragment:" {
expect "Fragment from URL: stuff" {
expect "Fragment from URL without fragment: " {
expect "Testing Url.reserve:" {
expect "URL with reserved capacity and params: https://example.com/stuff?caf%C3%A9=du%20Monde&email=hi%40example.com" {
expect "Testing Url.with_query:" {
expect "URL with replaced query: https://example.com?newQuery=thisRightHere#stuff" {
expect "URL with removed query: https://example.com#stuff" {
expect "Testing Url.with_fragment:" {
expect "URL with replaced fragment: https://example.com#things" {
expect "URL with added fragment: https://example.com#things" {
expect "URL with removed fragment: https://example.com" {
expect "Testing Url.query_params:" {
expect "params_dict: {\"key1\": \"val1\", \"key2\": \"val2\", \"key3\": \"val3\"}" {
expect "Testing Url.path:" {
expect "Path from URL: example.com/foo/bar" {
expect "Path from relative URL: /foo/bar" {
expect "Ran all tests." {
expect eof {
check_exit_and_segfault
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}

puts stderr "\nExpect script failed: output was different from expected value. uncomment `exp_internal 1` to debug."
exit 1
9 changes: 7 additions & 2 deletions platform/Url.roc
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ to_str = |@Url(str)| str
## |> Url.append("stuff")
##
## # Gives https://example.com/things/stuff/more/etc/"
## Url.from_str "https://example.com/things/"
## Url.from_str("https://example.com/things/")
## |> Url.append("/stuff/")
## |> Url.append("/more/etc/")
##
Expand All @@ -102,7 +102,12 @@ to_str = |@Url(str)| str
## ```
append : Url, Str -> Url
append = |@Url(url_str), suffix_unencoded|
suffix = percent_encode(suffix_unencoded)
# percent-encode the suffix but not the slashes
suffix =
suffix_unencoded
|> Str.split_on("/")
|> List.map(percent_encode)
|> Str.join_with("/")

when Str.split_first(url_str, "?") is
Ok({ before, after }) ->
Expand Down
185 changes: 185 additions & 0 deletions tests/url.roc
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
app [Model, init!, respond!] {
pf: platform "../platform/main.roc",
}

import pf.Stdout
import pf.Url
import pf.Http exposing [Request, Response]

Model : {}

init! : {} => Result Model _
init! = |{}|
when run_tests!({}) is
Ok(_) ->
Err(Exit(0, "Ran all tests."))
Err(err) ->
Err(Exit(1, "Test run failed:\n\t${Inspect.to_str(err)}"))

run_tests! : {} => Result {} _
run_tests! = |{}|
# Test Url.from_str and Url.to_str
url = Url.from_str("https://example.com")
Stdout.line!("Created URL: ${Url.to_str(url)}")?
# expects "https://example.com"

Stdout.line!("Testing Url.append:")?

urlWithPath = Url.append(url, "some stuff")
Stdout.line!("URL with append: ${Url.to_str(urlWithPath)}")?
# expects "https://example.com/some%20stuff"

url_search = Url.from_str("https://example.com?search=blah#fragment")
url_search_append = Url.append(url_search, "stuff")
Stdout.line!("URL with query and fragment, then appended path: ${Url.to_str(url_search_append)}")?
# expects "https://example.com/stuff?search=blah#fragment"

url_things = Url.from_str("https://example.com/things/")
url_things_append = Url.append(url_things, "/stuff/")
url_things_append_more = Url.append(url_things_append, "/more/etc/")
Stdout.line!("URL with multiple appended paths: ${Url.to_str(url_things_append_more)}")?
# expects "https://example.com/things/stuff/more/etc/")

# Test Url.append_param
Stdout.line!("Testing Url.append_param:")?

url_example = Url.from_str("https://example.com")
url_example_param = Url.append_param(url_example, "email", "someone@example.com")
Stdout.line!("URL with appended param: ${Url.to_str(url_example_param)}")?
# expects "https://example.com?email=someone%40example.com"

url_example_2 = Url.from_str("https://example.com")
url_example_2_cafe = Url.append_param(url_example_2, "café", "du Monde")
url_example_2_cafe_email = Url.append_param(url_example_2_cafe, "email", "hi@example.com")
Stdout.line!("URL with multiple appended params: ${Url.to_str(url_example_2_cafe_email)}")?
# expects "https://example.com?caf%C3%A9=du%20Monde&email=hi%40example.com")?

# Test Url.has_query
Stdout.line!("\nTesting Url.has_query:")?

url_with_query = Url.from_str("https://example.com?key=value#stuff")
hasQuery1 = Url.has_query(url_with_query)
Stdout.line!("URL with query has_query: ${Inspect.to_str(hasQuery1)}")?
# expects Bool.true

url_hashtag = Url.from_str("https://example.com#stuff")
hasQuery2 = Url.has_query(url_hashtag)
Stdout.line!("URL without query has_query: ${Inspect.to_str(hasQuery2)}")?
# expects Bool.false

Stdout.line!("\nTesting Url.has_fragment:")?

url_key_val_hashtag = Url.from_str("https://example.com?key=value#stuff")
has_fragment = Url.has_fragment(url_key_val_hashtag)
Stdout.line!("URL with fragment has_fragment: ${Inspect.to_str(has_fragment)}")?
# expects Bool.true

url_key_val = Url.from_str("https://example.com?key=value")
has_fragment_2 = Url.has_fragment(url_key_val)
Stdout.line!("URL without fragment has_fragment: ${Inspect.to_str(has_fragment_2)}")?
# expects Bool.false

Stdout.line!("\nTesting Url.query:")?

url_key_val_multi = Url.from_str("https://example.com?key1=val1&key2=val2&key3=val3#stuff")
query = Url.query(url_key_val_multi)
Stdout.line!("Query from URL: ${query}")?
# expects "key1=val1&key2=val2&key3=val3"

url_no_query = Url.from_str("https://example.com#stuff")
query_empty = Url.query(url_no_query)
Stdout.line!("Query from URL without query: ${query_empty}")?
# expects ""

# Test Url.fragment
Stdout.line!("\nTesting Url.fragment:")?

url_with_fragment = Url.from_str("https://example.com#stuff")
fragment = Url.fragment(url_with_fragment)
Stdout.line!("Fragment from URL: ${fragment}")?
# expects "stuff"

url_no_fragment = Url.from_str("https://example.com")
fragment_empty = Url.fragment(url_no_fragment)
Stdout.line!("Fragment from URL without fragment: ${fragment_empty}")?
# expects ""

# Test Url.reserve
Stdout.line!("\nTesting Url.reserve:")?

url_to_reserve = Url.from_str("https://example.com")
url_reserved = Url.reserve(url_to_reserve, 50)
url_with_params = url_reserved
|> Url.append("stuff")
|> Url.append_param("café", "du Monde")
|> Url.append_param("email", "hi@example.com")

Stdout.line!("URL with reserved capacity and params: ${Url.to_str(url_with_params)}")?
# expects "https://example.com/stuff?caf%C3%A9=du%20Monde&email=hi%40example.com"

# Test Url.with_query
Stdout.line!("\nTesting Url.with_query:")?

url_replace_query = Url.from_str("https://example.com?key1=val1&key2=val2#stuff")
url_with_new_query = Url.with_query(url_replace_query, "newQuery=thisRightHere")
Stdout.line!("URL with replaced query: ${Url.to_str(url_with_new_query)}")?
# expects "https://example.com?newQuery=thisRightHere#stuff"

url_remove_query = Url.from_str("https://example.com?key1=val1&key2=val2#stuff")
url_with_empty_query = Url.with_query(url_remove_query, "")
Stdout.line!("URL with removed query: ${Url.to_str(url_with_empty_query)}")?
# expects "https://example.com#stuff"

# Test Url.with_fragment
Stdout.line!("\nTesting Url.with_fragment:")?

url_replace_fragment = Url.from_str("https://example.com#stuff")
url_with_new_fragment = Url.with_fragment(url_replace_fragment, "things")
Stdout.line!("URL with replaced fragment: ${Url.to_str(url_with_new_fragment)}")?
# expects "https://example.com#things"

url_add_fragment = Url.from_str("https://example.com")
url_with_added_fragment = Url.with_fragment(url_add_fragment, "things")
Stdout.line!("URL with added fragment: ${Url.to_str(url_with_added_fragment)}")?
# expects "https://example.com#things"

url_remove_fragment = Url.from_str("https://example.com#stuff")
url_with_empty_fragment = Url.with_fragment(url_remove_fragment, "")
Stdout.line!("URL with removed fragment: ${Url.to_str(url_with_empty_fragment)}")?
# expects "https://example.com"

# Test Url.query_params
Stdout.line!("\nTesting Url.query_params:")?

url_with_many_params = Url.from_str("https://example.com?key1=val1&key2=val2&key3=val3")
params_dict = Url.query_params(url_with_many_params)

# Check if params contains expected key-value pairs
Stdout.line!("params_dict: ${Inspect.to_str(params_dict)}")?
# expects Dict with key1=val1, key2=val2, key3=val3

# Test Url.path
Stdout.line!("\nTesting Url.path:")?

url_with_path = Url.from_str("https://example.com/foo/bar?key1=val1&key2=val2#stuff")
path = Url.path(url_with_path)
Stdout.line!("Path from URL: ${path}")?
# expects "example.com/foo/bar"

url_relative = Url.from_str("/foo/bar?key1=val1&key2=val2#stuff")
path_relative = Url.path(url_relative)
Stdout.line!("Path from relative URL: ${path_relative}")?
# expects "/foo/bar"

Ok({})

respond! : Request, Model => Result Response [ServerErr Str]_
respond! = |_, _|

Ok(
{
status: 200,
headers: [],
body: Str.to_utf8("I am a test."),
},
)
1 change: 0 additions & 1 deletion tests/utc.roc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
app [Model, init!, respond!] {
pf: platform "../platform/main.roc",
json: "https://github.com/lukewilliamboswell/roc-json/releases/download/0.13.0/RqendgZw5e1RsQa3kFhgtnMP8efWoqGRsAvubx4-zus.tar.br",
}

import pf.Stdout
Expand Down