use super::parse_graceful;
use crate::uri::Uri;
#[test]
fn push_pair_into_empty_query() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut().push_pair("a", "1");
assert_eq!(uri.to_string(), "/p?a=1");
}
#[test]
fn push_pair_appends_with_ampersand() {
let mut uri: Uri = parse_graceful("/p?a=1").unwrap();
uri.query_mut().push_pair("b", "2").push_pair("c", "3");
assert_eq!(uri.to_string(), "/p?a=1&b=2&c=3");
}
#[test]
fn push_key_bare() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut().push_key("foo");
assert_eq!(uri.to_string(), "/p?foo");
uri.query_mut().push_key("bar").push_pair("x", "1");
assert_eq!(uri.to_string(), "/p?foo&bar&x=1");
}
#[test]
fn push_pair_integer_and_bool() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut()
.push_pair("page", 3_u32)
.push_pair("offset", -1_i32)
.push_pair("active", true);
assert_eq!(uri.to_string(), "/p?page=3&offset=-1&active=true");
}
#[test]
fn push_pair_auto_encodes_structural_bytes() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut()
.push_pair("a&b", "c=d")
.push_pair("plus", "a+b");
assert_eq!(uri.to_string(), "/p?a%26b=c%3Dd&plus=a%2Bb");
}
#[test]
fn push_pair_auto_encodes_space_and_non_ascii() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut()
.push_pair("hello world", "caf\u{e9}")
.push_pair("ctrl", "\n");
assert_eq!(uri.to_string(), "/p?hello%20world=caf%C3%A9&ctrl=%0A");
}
#[test]
fn push_pair_pchar_passes_through() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut()
.push_pair("Aa0-._~!$'()*,;:@/?", "Aa0-._~!$'()*,;:@/?");
assert_eq!(
uri.to_string(),
"/p?Aa0-._~!$'()*,;:@/?=Aa0-._~!$'()*,;:@/?",
);
}
#[test]
fn pop_returns_last_pair() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2&c=3").unwrap();
let pair = uri.query_mut().pop().unwrap();
assert_eq!(pair.name_encoded(), "c");
assert_eq!(pair.value_encoded().as_deref(), Some("3"));
assert_eq!(uri.to_string(), "/p?a=1&b=2");
}
#[test]
fn pop_bare_key() {
let mut uri: Uri = parse_graceful("/p?a=1&bare").unwrap();
let pair = uri.query_mut().pop().unwrap();
assert_eq!(pair.name_encoded(), "bare");
assert!(pair.value_encoded().is_none());
assert!(!pair.has_value());
assert_eq!(uri.to_string(), "/p?a=1");
}
#[test]
fn pop_decodes_through_helpers() {
let mut uri: Uri = parse_graceful("/p?msg=hello%20world").unwrap();
let pair = uri.query_mut().pop().unwrap();
assert_eq!(pair.value_decoded().unwrap(), "hello world");
}
#[test]
fn pop_until_empty() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2").unwrap();
{
let mut g = uri.query_mut();
assert_eq!(g.pop().unwrap().name_encoded(), "b");
assert_eq!(g.pop().unwrap().name_encoded(), "a");
assert!(g.pop().is_none());
}
assert_eq!(uri.to_string(), "/p?");
}
#[test]
fn pop_skips_trailing_empty_fragment() {
let mut uri: Uri = parse_graceful("/p?a=1&").unwrap();
let pair = uri.query_mut().pop().unwrap();
assert_eq!(pair.name_encoded(), "a");
}
#[test]
fn pop_returns_none_when_no_query() {
let mut uri: Uri = parse_graceful("/p").unwrap();
assert!(uri.query_mut().pop().is_none());
assert_eq!(uri.to_string(), "/p");
}
#[test]
fn drain_yields_all_pairs_in_order() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2&c=3").unwrap();
let pairs: Vec<_> = uri
.query_mut()
.drain()
.map(|p| {
(
p.name_encoded().into_owned(),
p.value_encoded().map(|v| v.into_owned()),
)
})
.collect();
assert_eq!(
pairs,
vec![
("a".to_owned(), Some("1".to_owned())),
("b".to_owned(), Some("2".to_owned())),
("c".to_owned(), Some("3".to_owned())),
],
);
assert_eq!(uri.to_string(), "/p?");
}
#[test]
fn drain_dropped_unread_still_clears() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2").unwrap();
{
let _ = uri.query_mut().drain(); }
assert_eq!(uri.to_string(), "/p?");
}
#[test]
fn drain_skips_empty_fragments() {
let mut uri: Uri = parse_graceful("/p?&a=1&&b=2&").unwrap();
let names: Vec<_> = uri
.query_mut()
.drain()
.map(|p| p.name_encoded().into_owned())
.collect();
assert_eq!(names, vec!["a", "b"]);
}
#[test]
fn drain_on_no_query_yields_nothing() {
let mut uri: Uri = parse_graceful("/p").unwrap();
let pairs: Vec<_> = uri.query_mut().drain().collect();
assert!(pairs.is_empty());
assert_eq!(uri.to_string(), "/p");
}
#[test]
fn push_then_pop_yields_encoded_form() {
let mut uri: Uri = parse_graceful("/p").unwrap();
{
let mut g = uri.query_mut();
g.push_pair("a", "hello world").push_pair("b", "x&y");
}
assert_eq!(uri.to_string(), "/p?a=hello%20world&b=x%26y");
let pair = uri.query_mut().pop().unwrap();
assert_eq!(pair.name_encoded(), "b");
assert_eq!(pair.value_encoded().as_deref(), Some("x%26y"));
assert_eq!(pair.value_decoded().unwrap(), "x&y");
}
#[test]
fn iterator_yields_query_pair_ref() {
use crate::uri::QueryPairRef;
let uri: Uri = parse_graceful("/p?a=1").unwrap();
let pair: QueryPairRef<'_> = uri.query().unwrap().pairs().next().unwrap();
assert_eq!(pair.name_encoded(), "a");
}
#[test]
fn query_pair_ref_to_owned_round_trip() {
let uri: Uri = parse_graceful("/p?key=value").unwrap();
let ref_pair = uri.query().unwrap().pairs().next().unwrap();
let owned = ref_pair.into_owned();
assert_eq!(owned.name_encoded(), "key");
assert_eq!(owned.value_encoded().as_deref(), Some("value"));
let back = owned.view();
assert_eq!(back.name_encoded(), "key");
assert_eq!(back.value_encoded().as_deref(), Some("value"));
}
#[test]
fn multi_key_push_then_pop_returns_lifo() {
let mut uri: Uri = parse_graceful("/p").unwrap();
{
let mut g = uri.query_mut();
g.push_pair("a", "1");
g.push_pair("a", "2");
}
assert_eq!(uri.to_string(), "/p?a=1&a=2");
{
let mut g = uri.query_mut();
let last = g.pop().unwrap();
assert_eq!(last.name_encoded(), "a");
assert_eq!(last.value_encoded().as_deref(), Some("2"));
let first = g.pop().unwrap();
assert_eq!(first.name_encoded(), "a");
assert_eq!(first.value_encoded().as_deref(), Some("1"));
assert!(g.pop().is_none());
}
}
#[test]
fn drain_then_push_repopulates_query() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2").unwrap();
{
let mut g = uri.query_mut();
for _ in g.drain() {}
}
assert_eq!(uri.to_string(), "/p?", "drain leaves an empty query");
{
let mut g = uri.query_mut();
g.push_pair("c", "3");
g.push_pair("d", "4");
}
assert_eq!(uri.to_string(), "/p?c=3&d=4");
}
#[test]
fn remove_deletes_every_pair_with_name() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2&a=3&c=4").unwrap();
assert_eq!(uri.query_mut().remove("a"), 2);
assert_eq!(uri.to_string(), "/p?b=2&c=4");
}
#[test]
fn remove_matches_bare_keys_and_decoded_names() {
let mut uri: Uri = parse_graceful("/p?foo&a%20b=1&a+b=2&keep=3").unwrap();
assert_eq!(uri.query_mut().remove("foo"), 1);
assert_eq!(uri.query_mut().remove("a b"), 2);
assert_eq!(uri.to_string(), "/p?keep=3");
}
#[test]
fn remove_nonexistent_returns_zero_and_keeps_query() {
let mut uri: Uri = parse_graceful("/p?a=1").unwrap();
assert_eq!(uri.query_mut().remove("zz"), 0);
assert_eq!(uri.to_string(), "/p?a=1");
}
#[test]
fn remove_last_pair_keeps_question_mark() {
let mut uri: Uri = parse_graceful("/p?a=1").unwrap();
assert_eq!(uri.query_mut().remove("a"), 1);
assert_eq!(uri.to_string(), "/p?");
assert!(uri.query().unwrap().is_empty());
}
#[test]
fn remove_on_absent_query_is_noop() {
let mut uri: Uri = parse_graceful("/p").unwrap();
assert_eq!(uri.query_mut().remove("a"), 0);
assert!(uri.query().is_none());
assert_eq!(uri.to_string(), "/p");
}
#[test]
fn retain_keeps_matching_pairs_in_order() {
let mut uri: Uri = parse_graceful("/p?a=1&b=2&c=3&b=4").unwrap();
uri.query_mut().retain(|p| p.name_decoded() != "b");
assert_eq!(uri.to_string(), "/p?a=1&c=3");
}
#[test]
fn retain_preserves_raw_pair_bytes() {
let mut uri: Uri = parse_graceful("/p?a=%41&b=2").unwrap();
uri.query_mut().retain(|p| p.name_decoded() != "b");
assert_eq!(uri.to_string(), "/p?a=%41");
}
#[test]
fn retain_drops_empty_fragments() {
let mut uri: Uri = parse_graceful("/p?a=1&&b=2&").unwrap();
uri.query_mut().retain(|_| true);
assert_eq!(uri.to_string(), "/p?a=1&b=2");
}
#[test]
fn set_pair_replaces_all_and_appends_last() {
let mut uri: Uri = parse_graceful("/p?page=1&sort=asc&page=2").unwrap();
uri.query_mut().set_pair("page", 3);
assert_eq!(uri.to_string(), "/p?sort=asc&page=3");
}
#[test]
fn set_pair_appends_when_absent_and_encodes() {
let mut uri: Uri = parse_graceful("/p").unwrap();
uri.query_mut().set_pair("a b", "1&2");
assert_eq!(uri.to_string(), "/p?a%20b=1%262");
uri.query_mut().set_pair("a b", "x");
assert_eq!(uri.to_string(), "/p?a%20b=x");
}
#[test]
fn remove_normalizes_component_patterns() {
let mut uri: Uri = parse_graceful("/p?a%20b=1&a+b=2&keep=3").unwrap();
assert_eq!(uri.query_mut().remove("a+b"), 2);
assert_eq!(uri.to_string(), "/p?keep=3");
}