#[cfg(test)] mod tests { use fancy_regex::Regex; use normalize_url_rs::*; use rstest::rstest; #[rstest] #[case("sindresorhus.com", "http://sindresorhus.com")] #[case("sindresorhus.com ", "http://sindresorhus.com")] #[case("sindresorhus.com.", "http://sindresorhus.com")] #[case("SindreSorhus.com", "http://sindresorhus.com")] #[case("HTTP://sindresorhus.com", "http://sindresorhus.com")] #[case("//sindresorhus.com", "http://sindresorhus.com")] #[case("http://sindresorhus.com", "http://sindresorhus.com")] #[case("http://sindresorhus.com:80", "http://sindresorhus.com")] #[case("https://sindresorhus.com:443", "https://sindresorhus.com")] #[case("http://www.sindresorhus.com", "http://sindresorhus.com")] #[case("www.com", "http://www.com")] #[case("http://www.www.sindresorhus.com", "http://www.www.sindresorhus.com")] #[case("www.sindresorhus.com", "http://sindresorhus.com")] #[case("http://sindresorhus.com/foo/", "http://sindresorhus.com/foo")] #[case( "sindresorhus.com/?foo=bar baz", "http://sindresorhus.com/?foo=bar+baz" )] #[case("https://foo.com/https://bar.com", "https://foo.com/https://bar.com")] #[case( "https://foo.com/https://bar.com/foo//bar", "https://foo.com/https://bar.com/foo/bar" )] #[case("https://foo.com/http://bar.com", "https://foo.com/http://bar.com")] #[case( "https://foo.com/http://bar.com/foo//bar", "https://foo.com/http://bar.com/foo/bar" )] #[case("http://sindresorhus.com/%7Efoo/", "http://sindresorhus.com/~foo")] #[case( "https://foo.com/%FAIL%/07/94/ca/55.jpg", "https://foo.com/%FAIL%/07/94/ca/55.jpg" )] #[case("http://sindresorhus.com/?", "http://sindresorhus.com")] #[case("êxample.com", "http://xn--xample-hva.com")] #[case( "http://sindresorhus.com/?b=bar&a=foo", "http://sindresorhus.com/?a=foo&b=bar" )] #[case( r#"http://sindresorhus.com/?foo=bar*|<>:""#, "http://sindresorhus.com/?foo=bar*|%3C%3E:%22" )] #[case("http://sindresorhus.com:5000", "http://sindresorhus.com:5000")] #[case("http://sindresorhus.com/foo#bar", "http://sindresorhus.com/foo#bar")] #[case( "http://sindresorhus.com/foo/bar/../baz", "http://sindresorhus.com/foo/baz" )] #[case( "http://sindresorhus.com/foo/bar/./baz", "http://sindresorhus.com/foo/bar/baz" )] #[case("https://i.vimeocdn.com/filter/overlay?src0=https://i.vimeocdn.com/video/598160082_1280x720.jpg&src1=https://f.vimeocdn.com/images_v6/share/play_icon_overlay.png", "https://i.vimeocdn.com/filter/overlay?src0=https://i.vimeocdn.com/video/598160082_1280x720.jpg&src1=https://f.vimeocdn.com/images_v6/share/play_icon_overlay.png")] fn main_tests(#[case] input: String, #[case] expected: String) { let result = normalize_url(&input, &OptionsBuilder::default().build().unwrap()) .expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("sindresorhus.com", "http", "http://sindresorhus.com")] #[case("sindresorhus.com", "https", "https://sindresorhus.com")] fn default_protocol_tests( #[case] input: String, #[case] protocol: String, #[case] expected: String, ) { let options = OptionsBuilder::default() .default_protocol(protocol) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case( "http://user:password@www.sindresorhus.com", true, "http://sindresorhus.com" )] #[case( "https://user:password@www.sindresorhus.com", true, "https://sindresorhus.com" )] #[case( "https://user:password@www.sindresorhus.com/@user", true, "https://sindresorhus.com/@user" )] #[case( "http://user:password@www.êxample.com", true, "http://xn--xample-hva.com" )] #[case( "http://user:password@www.sindresorhus.com", false, "http://user:password@sindresorhus.com" )] #[case( "https://user:password@www.sindresorhus.com", false, "https://user:password@sindresorhus.com" )] #[case( "https://user:password@www.sindresorhus.com/@user", false, "https://user:password@sindresorhus.com/@user" )] #[case( "http://user:password@www.êxample.com", false, "http://user:password@xn--xample-hva.com" )] fn strip_auth_tests(#[case] input: String, #[case] strip_auth: bool, #[case] expected: String) { let options = OptionsBuilder::default() .strip_authentication(strip_auth) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://www.sindresorhus.com", "sindresorhus.com")] #[case("http://sindresorhus.com", "sindresorhus.com")] #[case("https://www.sindresorhus.com", "sindresorhus.com")] #[case("//www.sindresorhus.com", "sindresorhus.com")] fn strip_protocols_tests(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .strip_protocol(true) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com", false, true, "http://sindresorhus.com")] #[case( "http://sindresorhus.com/about#", false, true, "http://sindresorhus.com/about" )] #[case( "http://sindresorhus.com/about#:~:text=hello", false, true, "http://sindresorhus.com/about" )] #[case( "http://sindresorhus.com/about#main", false, true, "http://sindresorhus.com/about#main" )] #[case( "http://sindresorhus.com/about#main:~:text=hello", false, true, "http://sindresorhus.com/about#main" )] #[case( "http://sindresorhus.com/about#main:~:text=hello%20world", false, true, "http://sindresorhus.com/about#main" )] #[case("http://sindresorhus.com", false, false, "http://sindresorhus.com")] #[case( "http://sindresorhus.com/about#:~:text=hello", false, false, "http://sindresorhus.com/about#:~:text=hello" )] #[case( "http://sindresorhus.com/about#main", false, false, "http://sindresorhus.com/about#main" )] #[case( "http://sindresorhus.com/about#main:~:text=hello", false, false, "http://sindresorhus.com/about#main:~:text=hello" )] #[case( "http://sindresorhus.com/about#main:~:text=hello%20world", false, false, "http://sindresorhus.com/about#main:~:text=hello%20world" )] #[case("http://sindresorhus.com", true, false, "http://sindresorhus.com")] #[case( "http://sindresorhus.com/about#:~:text=hello", true, false, "http://sindresorhus.com/about" )] #[case( "http://sindresorhus.com/about#main", true, false, "http://sindresorhus.com/about" )] #[case( "http://sindresorhus.com/about#main:~:text=hello", true, false, "http://sindresorhus.com/about" )] #[case( "http://sindresorhus.com/about#main:~:text=hello%20world", true, false, "http://sindresorhus.com/about" )] fn strip_text_fragment_tests( #[case] input: String, #[case] strip_hash: bool, #[case] strip_text_fragment: bool, #[case] expected: String, ) { let options = OptionsBuilder::default() .strip_hash(strip_hash) .strip_text_fragment(strip_text_fragment) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://www.sindresorhus.com", false, "http://www.sindresorhus.com")] #[case("www.sindresorhus.com", false, "http://www.sindresorhus.com")] #[case("http://www.êxample.com", false, "http://www.xn--xample-hva.com")] #[case("http://www.vue.amsterdam", true, "http://vue.amsterdam")] #[case( "http://www.sorhus.xx--bck1b9a5dre4c", true, "http://sorhus.xx--bck1b9a5dre4c" )] fn strip_www_tests(#[case] input: String, #[case] strip: bool, #[case] expected: String) { let options = OptionsBuilder::default().strip_www(strip).build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case( "www.sindresorhus.com?foo=bar&utm_medium=test", "http://sindresorhus.com/?foo=bar" )] fn remove_query_parameters_tests_1(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://www.sindresorhus.com", "http://www.sindresorhus.com")] #[case("www.sindresorhus.com?foo=bar", "http://www.sindresorhus.com/?foo=bar")] #[case( "www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref", "http://www.sindresorhus.com/?foo=bar" )] fn remove_query_parameters_tests_2(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .strip_www(false) .remove_query_parameters(RemoveQueryParametersOptions::List(vec![ Regex::new(r"^utm_\w+").unwrap(), Regex::new("ref").unwrap(), ])) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://www.sindresorhus.com", "http://www.sindresorhus.com")] #[case("www.sindresorhus.com?foo=bar", "http://www.sindresorhus.com")] #[case( "www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref", "http://www.sindresorhus.com" )] fn remove_query_parameters_tests_3(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .strip_www(false) .remove_query_parameters(RemoveQueryParametersOptions::All) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://www.sindresorhus.com", "http://www.sindresorhus.com")] #[case("www.sindresorhus.com?foo=bar", "http://www.sindresorhus.com/?foo=bar")] #[case( "www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref", "http://www.sindresorhus.com/?foo=bar&ref=test_ref&utm_medium=test" )] fn remove_query_parameters_tests_4(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .strip_www(false) .remove_query_parameters(RemoveQueryParametersOptions::None) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("https://sindresorhus.com", "https://sindresorhus.com")] #[case("www.sindresorhus.com?foo=bar", "http://www.sindresorhus.com")] #[case( "www.sindresorhus.com?foo=bar&utm_medium=test&ref=test_ref", "http://www.sindresorhus.com/?ref=test_ref&utm_medium=test" )] fn keep_query_parameters_tests(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .strip_www(false) .remove_query_parameters(RemoveQueryParametersOptions::None) .keep_query_parameters(vec![ Regex::new(r"^utm_\w+").unwrap(), Regex::new("ref").unwrap(), ]) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("https://sindresorhus.com", "https://sindresorhus.com")] fn force_http_tests_1(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com", "http://sindresorhus.com")] #[case("https://www.sindresorhus.com", "http://sindresorhus.com")] #[case("//sindresorhus.com", "http://sindresorhus.com")] fn force_http_tests_2(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().force_http(true).build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("https://sindresorhus.com", "https://sindresorhus.com")] fn force_https_tests_1(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com", "https://sindresorhus.com")] #[case("https://www.sindresorhus.com", "https://sindresorhus.com")] #[case("//sindresorhus.com", "https://sindresorhus.com")] fn force_https_tests_2(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().force_https(true).build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com", "http://sindresorhus.com")] #[case("http://sindresorhus.com/", "http://sindresorhus.com")] #[case("http://sindresorhus.com/redirect", "http://sindresorhus.com/redirect")] #[case( "http://sindresorhus.com/redirect/", "http://sindresorhus.com/redirect" )] #[case("http://sindresorhus.com/#/", "http://sindresorhus.com/#/")] #[case( "http://sindresorhus.com/?unicorns=true", "http://sindresorhus.com/?unicorns=true" )] fn remove_trailing_slash_tests_1(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com", "http://sindresorhus.com")] #[case("http://sindresorhus.com/", "http://sindresorhus.com")] #[case( "http://sindresorhus.com/redirect/", "http://sindresorhus.com/redirect/" )] #[case("http://sindresorhus.com/#/", "http://sindresorhus.com/#/")] #[case( "http://sindresorhus.com/?unicorns=true", "http://sindresorhus.com/?unicorns=true" )] fn remove_trailing_slash_tests_2(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .remove_trailing_slash(false) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com:123", "http://sindresorhus.com")] #[case("https://sindresorhus.com:123", "https://sindresorhus.com")] #[case("http://sindresorhus.com:443", "http://sindresorhus.com")] #[case("https://sindresorhus.com:80", "https://sindresorhus.com")] fn remove_explicit_port(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .remove_explicit_port(true) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("https://sindresorhus.com", "https://sindresorhus.com")] #[case("https://sindresorhus.com/", "https://sindresorhus.com/")] #[case( "https://sindresorhus.com/redirect", "https://sindresorhus.com/redirect" )] #[case( "https://sindresorhus.com/redirect/", "https://sindresorhus.com/redirect" )] #[case("https://sindresorhus.com/#/", "https://sindresorhus.com/#/")] #[case( "https://sindresorhus.com/?unicorns=true", "https://sindresorhus.com/?unicorns=true" )] fn remove_single_slash_tests(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .remove_single_slash(false) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("https://sindresorhus.com", "https://sindresorhus.com")] #[case("https://sindresorhus.com/", "https://sindresorhus.com/")] #[case( "https://sindresorhus.com/redirect", "https://sindresorhus.com/redirect" )] #[case( "https://sindresorhus.com/redirect/", "https://sindresorhus.com/redirect/" )] #[case("https://sindresorhus.com/#/", "https://sindresorhus.com/#/")] #[case( "https://sindresorhus.com/?unicorns=true", "https://sindresorhus.com/?unicorns=true" )] fn remove_single_slash_with_remove_trailing_slash_tests( #[case] input: String, #[case] expected: String, ) { let options = OptionsBuilder::default() .remove_single_slash(false) .remove_trailing_slash(false) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case( "http://sindresorhus.com/index.html", "http://sindresorhus.com/index.html" )] #[case( "http://sindresorhus.com/path/index.html", "http://sindresorhus.com/path/index.html" )] fn remove_directory_index_tests_1(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com/index.html", "http://sindresorhus.com")] #[case( "http://sindresorhus.com/index.htm", "http://sindresorhus.com/index.htm" )] #[case("http://sindresorhus.com/index.php", "http://sindresorhus.com")] #[case( "http://sindresorhus.com/path/index.html", "http://sindresorhus.com/path" )] #[case( "http://sindresorhus.com/path/index.htm", "http://sindresorhus.com/path/index.htm" )] #[case( "http://sindresorhus.com/path/index.php", "http://sindresorhus.com/path" )] #[case( "http://sindresorhus.com/foo/bar/index.html", "http://sindresorhus.com/foo/bar" )] fn remove_directory_index_tests_2(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .remove_directory_index(RemoveDirectoryIndexOptions::List(vec![ Regex::new(r"index\.html").unwrap(), Regex::new(r"index\.php").unwrap(), ])) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com/index.html", "http://sindresorhus.com")] #[case( "http://sindresorhus.com/index/index.html", "http://sindresorhus.com/index" )] #[case("http://sindresorhus.com/remove.html", "http://sindresorhus.com")] #[case( "http://sindresorhus.com/default.htm", "http://sindresorhus.com/default.htm" )] #[case("http://sindresorhus.com/index.php", "http://sindresorhus.com")] fn remove_directory_index_tests_3(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .remove_directory_index(RemoveDirectoryIndexOptions::List(vec![ Regex::new(r"^index\.[a-z]+$").unwrap(), Regex::new(r"remove\.html").unwrap(), ])) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com/index.html", "http://sindresorhus.com")] #[case("http://sindresorhus.com/index.htm", "http://sindresorhus.com")] #[case("http://sindresorhus.com/index.php", "http://sindresorhus.com")] fn remove_directory_index_tests_4(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .remove_directory_index(RemoveDirectoryIndexOptions::Default) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com/path/", "http://sindresorhus.com/path")] #[case( "http://sindresorhus.com/path/index.html", "http://sindresorhus.com/path" )] #[case("http://sindresorhus.com/#/path/", "http://sindresorhus.com/#/path/")] #[case( "http://sindresorhus.com/foo/#/bar/", "http://sindresorhus.com/foo#/bar/" )] fn remove_trailing_slash_and_directory_index_tests_1( #[case] input: String, #[case] expected: String, ) { let options = OptionsBuilder::default() .remove_directory_index(RemoveDirectoryIndexOptions::Default) .remove_trailing_slash(true) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://sindresorhus.com/path/", "http://sindresorhus.com/path/")] #[case( "http://sindresorhus.com/path/index.html", "http://sindresorhus.com/path/" )] #[case("http://sindresorhus.com/#/path/", "http://sindresorhus.com/#/path/")] fn remove_trailing_slash_and_directory_index_tests_2( #[case] input: String, #[case] expected: String, ) { let options = OptionsBuilder::default() .remove_directory_index(RemoveDirectoryIndexOptions::Default) .remove_trailing_slash(false) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case( "http://sindresorhus.com/?a=Z&b=Y&c=X&d=W", "http://sindresorhus.com/?a=Z&b=Y&c=X&d=W" )] #[case( "http://sindresorhus.com/?b=Y&c=X&a=Z&d=W", "http://sindresorhus.com/?a=Z&b=Y&c=X&d=W" )] #[case( "http://sindresorhus.com/?a=Z&d=W&b=Y&c=X", "http://sindresorhus.com/?a=Z&b=Y&c=X&d=W" )] #[case("http://sindresorhus.com/", "http://sindresorhus.com")] fn sort_query_parameters_tests_1(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .sort_query_parameters(true) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case( "http://sindresorhus.com/?a=Z&b=Y&c=X&d=W", "http://sindresorhus.com/?a=Z&b=Y&c=X&d=W" )] #[case( "http://sindresorhus.com/?b=Y&c=X&a=Z&d=W", "http://sindresorhus.com/?b=Y&c=X&a=Z&d=W" )] #[case( "http://sindresorhus.com/?a=Z&d=W&b=Y&c=X", "http://sindresorhus.com/?a=Z&d=W&b=Y&c=X" )] #[case("http://sindresorhus.com/", "http://sindresorhus.com")] fn sort_query_parameters_tests_2(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .sort_query_parameters(false) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("http://")] #[case("/")] #[case("/relative/path/")] fn invalid_url_tests(#[case] input: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect_err("Normalization succeeded"); assert!(matches!(result, NormalizeUrlError::UnexpectedError(_))); } #[rstest] #[case( "http://sindresorhus.com////foo/bar", "http://sindresorhus.com/foo/bar" )] #[case( "http://sindresorhus.com////foo////bar", "http://sindresorhus.com/foo/bar" )] #[case( "http://sindresorhus.com:5000///foo", "http://sindresorhus.com:5000/foo" )] #[case("http://sindresorhus.com///foo", "http://sindresorhus.com/foo")] #[case( "http://sindresorhus.com:5000//foo", "http://sindresorhus.com:5000/foo" )] #[case("http://sindresorhus.com//foo", "http://sindresorhus.com/foo")] #[case( "http://sindresorhus.com/s3://sindresorhus.com", "http://sindresorhus.com/s3://sindresorhus.com" )] #[case( "http://sindresorhus.com/s3://sindresorhus.com//foo", "http://sindresorhus.com/s3://sindresorhus.com/foo" )] #[case( "http://sindresorhus.com//foo/s3://sindresorhus.com", "http://sindresorhus.com/foo/s3://sindresorhus.com" )] #[case( "http://sindresorhus.com/git://sindresorhus.com", "http://sindresorhus.com/git://sindresorhus.com" )] #[case( "http://sindresorhus.com/git://sindresorhus.com//foo", "http://sindresorhus.com/git://sindresorhus.com/foo" )] #[case( "http://sindresorhus.com//foo/git://sindresorhus.com//foo", "http://sindresorhus.com/foo/git://sindresorhus.com/foo" )] #[case( "http://sindresorhus.com/a://sindresorhus.com//foo", "http://sindresorhus.com/a:/sindresorhus.com/foo" )] #[case("http://sindresorhus.com/alongprotocolwithin50charlimitxxxxxxxxxxxxxxxxxxxx://sindresorhus.com//foo", "http://sindresorhus.com/alongprotocolwithin50charlimitxxxxxxxxxxxxxxxxxxxx://sindresorhus.com/foo")] #[case("http://sindresorhus.com/alongprotocolexceeds50charlimitxxxxxxxxxxxxxxxxxxxxx://sindresorhus.com//foo", "http://sindresorhus.com/alongprotocolexceeds50charlimitxxxxxxxxxxxxxxxxxxxxx:/sindresorhus.com/foo")] #[case( "http://sindresorhus.com/a2-.+://sindresorhus.com", "http://sindresorhus.com/a2-.+://sindresorhus.com" )] #[case( "http://sindresorhus.com/a2-.+_://sindresorhus.com", "http://sindresorhus.com/a2-.+_:/sindresorhus.com" )] #[case( "http://sindresorhus.com/2abc://sindresorhus.com", "http://sindresorhus.com/2abc:/sindresorhus.com" )] fn remove_duplicate_slashes_tests(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default().build().unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[rstest] #[case("https://ebаy.com", "https://xn--eby-7cd.com")] fn prevents_homograph_attacks(#[case] input: String, #[case] expected: String) { let options = OptionsBuilder::default() .sort_query_parameters(true) .build() .unwrap(); let result = normalize_url(&input, &options).expect("Normalization failed"); assert_eq!(result, expected); } #[test] fn returns_error_if_force_http_and_force_https_are_both_set() { let result = normalize_url( "", &OptionsBuilder::default() .force_http(true) .force_https(true) .build() .unwrap(), ); assert_eq!(result.is_err(), true); assert!(matches!( result, Err(NormalizeUrlError::ForceHttpAndHttpAreExclusive) )); } }