///|
/// Test URL encoding functionality
test "url_encoding" {
// Test basic encoding
let encoded = Uri::encode("hello world!")
json_inspect(encoded, content="hello%20world%21")
// Test unreserved characters (should not be encoded)
let unreserved = "hello-world_123.test~"
let encoded_unreserved = Uri::encode(unreserved)
json_inspect(encoded_unreserved, content="hello-world_123.test~")
// Test special characters
let special = "user@domain.com:password"
let encoded_special = Uri::encode(special)
json_inspect(encoded_special, content="user%40domain.com%3Apassword")
}
///|
/// Test URL decoding functionality
test "url_decoding" {
// Test basic decoding
let decoded = Uri::decode("hello%20world%21")
json_inspect(decoded, content="hello world!")
// Test invalid hex sequences (should be left as-is)
let invalid_hex = Uri::decode("hello%ZZ")
json_inspect(invalid_hex, content="hello%ZZ")
// Test incomplete percent encoding
let incomplete = Uri::decode("hello%2")
json_inspect(incomplete, content="hello%2")
// Test mixed content
let mixed = Uri::decode("user%40domain.com%3Apass%20word")
json_inspect(mixed, content="user@domain.com:pass word")
}
///|
/// Test URL encoding/decoding round trip
test "url_encoding_round_trip" {
let original = "Hello World! @#$%^&*()"
let encoded = Uri::encode(original)
let decoded = Uri::decode(encoded)
json_inspect(decoded, content="Hello World! @#$%^&*()")
// Test with Unicode-like content
let unicode_like = "café naïve résumé"
let encoded_unicode = Uri::encode(unicode_like)
let decoded_unicode = Uri::decode(encoded_unicode)
json_inspect(decoded_unicode, content="café naïve résumé")
}
///|
/// Test query string parsing
test "query_string_parsing" {
// Test basic query parsing
let query = "name=John&age=30&city=New%20York"
let params = Uri::parse_query(query)
json_inspect(params, content=[
["name", "John"],
["age", "30"],
["city", "New York"],
])
// Test empty query
let empty_params = Uri::parse_query("")
json_inspect(empty_params.length(), content=0)
// Test query with empty values
let empty_value_query = "key1=&key2=value2&key3"
let empty_value_params = Uri::parse_query(empty_value_query)
json_inspect(empty_value_params, content=[
["key1", ""],
["key2", "value2"],
["key3", ""],
])
}
///|
/// Test query string building
test "query_string_building" {
// Test basic query building
let params = [("name", "John Doe"), ("age", "30"), ("active", "")]
let query = Uri::build_query(params)
json_inspect(query, content="name=John%20Doe&age=30&active")
// Test empty params
let empty_query = Uri::build_query([])
json_inspect(empty_query, content="")
// Test special characters in keys and values
let special_params = [
("user@email", "test+value"),
("key with spaces", "value&more"),
]
let special_query = Uri::build_query(special_params)
json_inspect(
special_query,
content="user%40email=test%2Bvalue&key%20with%20spaces=value%26more",
)
}
///|
/// Test path segments functionality
test "path_segments" {
// Test basic path segments
let uri = parse("/path/to/resource")
let segments = uri.path_segments()
json_inspect(segments, content=["path", "to", "resource"])
// Test empty path
let empty_uri = empty()
let empty_segments = empty_uri.path_segments()
json_inspect(empty_segments.length(), content=0)
// Test path with encoded segments
let encoded_uri = parse("/path/with%20spaces/and%2Bplus")
let encoded_segments = encoded_uri.path_segments()
json_inspect(encoded_segments, content=["path", "with spaces", "and+plus"])
// Test root path
let root_uri = parse("/")
let root_segments = root_uri.path_segments()
json_inspect(root_segments.length(), content=0)
}
///|
/// Test path segments building
test "path_segments_building" {
// Test basic path building
let uri = empty().with_path_segments(["api", "v1", "users"])
json_inspect(uri.path(), content="/api/v1/users")
// Test empty segments
let empty_path_uri = empty().with_path_segments([])
json_inspect(empty_path_uri.path(), content="")
// Test segments with special characters
let special_uri = empty().with_path_segments([
"path with spaces", "file+name", "resource@id",
])
json_inspect(
special_uri.path(),
content="/path%20with%20spaces/file%2Bname/resource%40id",
)
// Test single segment
let single_uri = empty().with_path_segments(["resource"])
json_inspect(single_uri.path(), content="/resource")
}
///|
/// Test userinfo components parsing
test "userinfo_components" {
// Test username and password
let uri_with_pass = parse("https://user:pass@example.com")
match uri_with_pass.userinfo_components() {
Some((user, Some(pass))) => {
json_inspect(user, content="user")
json_inspect(pass, content="pass")
}
_ => fail("Expected username and password")
}
// Test username only
let uri_user_only = parse("https://user@example.com")
match uri_user_only.userinfo_components() {
Some((user, None)) => json_inspect(user, content="user")
_ => fail("Expected username only")
}
// Test no userinfo
let uri_no_user = parse("https://example.com")
match uri_no_user.userinfo_components() {
None => () // Expected
_ => fail("Expected no userinfo")
}
// Test encoded userinfo
let uri_encoded = parse("https://user%40domain:pass%20word@example.com")
match uri_encoded.userinfo_components() {
Some((user, Some(pass))) => {
json_inspect(user, content="user@domain")
json_inspect(pass, content="pass word")
}
_ => fail("Expected encoded userinfo")
}
}
///|
/// Test userinfo building
test "userinfo_building" {
// Test setting username and password
let uri = empty()
.with_host(Some("example.com"))
.with_userinfo(Some("user"), Some("pass"))
match uri.userinfo_components() {
Some((user, Some(pass))) => {
json_inspect(user, content="user")
json_inspect(pass, content="pass")
}
_ => fail("Expected username and password")
}
// Test setting username only
let uri_user_only = empty()
.with_host(Some("example.com"))
.with_userinfo(Some("user"), None)
match uri_user_only.userinfo_components() {
Some((user, None)) => json_inspect(user, content="user")
_ => fail("Expected username only")
}
// Test removing userinfo
let uri_removed = uri.with_userinfo(None, None)
match uri_removed.userinfo_components() {
None => () // Expected
_ => fail("Expected no userinfo")
}
// Test special characters in userinfo
let uri_special = empty()
.with_host(Some("example.com"))
.with_userinfo(Some("user@domain"), Some("pass word"))
let uri_string = uri_special.to_string()
if !uri_string.contains("user%40domain:pass%20word@") {
fail("Expected encoded userinfo in URI string")
}
}
///|
/// Test comprehensive URI building with all components
test "comprehensive_uri_building" {
let uri = empty()
.with_scheme(Some("https"))
.with_userinfo(Some("admin"), Some("secret"))
.with_host(Some("api.example.com"))
.with_port(Some(8443))
.with_path_segments(["v2", "users", "profile"])
.with_query_param("format", "json")
.with_query_param("include", "permissions")
.with_fragment(Some("section1"))
let uri_string = uri.to_string()
json_inspect(
uri_string,
content="https://admin:secret@api.example.com:8443/v2/users/profile?format=json&include=permissions#section1",
)
// Verify all components
json_inspect(uri.scheme(), content=["https"])
json_inspect(uri.host(), content=["api.example.com"])
json_inspect(uri.port(), content=[8443])
json_inspect(uri.path_segments(), content=["v2", "users", "profile"])
json_inspect(uri.get_query_param("format"), content=["json"])
json_inspect(uri.get_query_param("include"), content=["permissions"])
json_inspect(uri.fragment(), content=["section1"])
}
///|
/// Test edge cases and error conditions
test "edge_cases" {
// Test malformed percent encoding in existing functions
let malformed_uri = parse("https://example.com/path%ZZ")
// Should parse successfully but keep malformed encoding
json_inspect(malformed_uri.path(), content="/path%ZZ")
// Test very long URI components
let long_segment = "a".repeat(1000)
let long_uri = empty().with_path_segments([long_segment])
let segments = long_uri.path_segments()
json_inspect(segments[0].length(), content=1000)
// Test empty components
let empty_components_uri = empty()
.with_scheme(Some(""))
.with_host(Some(""))
.with_path("")
json_inspect(empty_components_uri.scheme(), content=[""])
json_inspect(empty_components_uri.host(), content=[""])
json_inspect(empty_components_uri.path(), content="")
}
///|
/// Test RFC 3986 compliance scenarios
test "rfc3986_compliance" {
// Test reserved characters in different components
let uri = parse(
"https://example.com/path?query=value%3Dwith%26special&other=normal#frag%23ment",
)
// Query should be parsed correctly
let query_params = Uri::parse_query(uri.query().unwrap_or(""))
json_inspect(query_params, content=[
["query", "value=with&special"],
["other", "normal"],
])
// Test case sensitivity in scheme (should be case-insensitive in practice, but we store as-is)
let upper_scheme = parse("HTTPS://example.com")
json_inspect(upper_scheme.scheme(), content=["HTTPS"])
// Test IPv6 addresses (basic support)
let ipv6_uri = parse("http://[2001:db8::1]:8080/path")
json_inspect(ipv6_uri.host(), content=["[2001:db8::1]"])
json_inspect(ipv6_uri.port(), content=[8080])
}