diff --git a/tests/test_url_query.py b/tests/test_url_query.py index 1a7407a..1336fd5 100644 --- a/tests/test_url_query.py +++ b/tests/test_url_query.py @@ -65,3 +65,33 @@ def test_path_and_scheme_are_preserved() -> None: assert out.startswith("https://example.com:8443/api/v1/foo?") parsed = dict(parse_qsl(urlparse(out).query)) assert parsed == {"token": MASK, "page": "1"} + + +# ── IPv6 host edge cases (issue #4) ────────────────────────────────────── + + +def test_ipv6_loopback_with_port_token_redacted() -> None: + """IPv6 loopback with port: token redacted, host/port preserved.""" + out = redact_url_query("http://[::1]:8080/api?token=abc") + assert "abc" not in out + parsed = dict(parse_qsl(urlparse(out).query)) + assert parsed == {"token": MASK} + assert "[::1]" in out + assert ":8080" in out + + +def test_ipv6_full_address_without_port() -> None: + """Full IPv6 address without port: api_key redacted, page preserved.""" + out = redact_url_query("http://[2001:db8::1]/api?api_key=abc&page=1") + assert "abc" not in out + parsed = dict(parse_qsl(urlparse(out).query)) + assert parsed == {"api_key": MASK, "page": "1"} + + +def test_ipv6_no_misparse_brackets() -> None: + """IPv6 brackets must not be confused with query delimiters.""" + out = redact_url_query("http://[fe80::1%25eth0]/path?token=secret") + assert "secret" not in out + parsed = dict(parse_qsl(urlparse(out).query)) + assert parsed == {"token": MASK} + assert "[fe80::1%25eth0]" in out