|
1 | | -"""Unit tests for shared/url_utils.py — extract_hostname + extract_fqdn.""" |
| 1 | +"""Unit tests for shared/url_utils.py — extract_hostname + extract_fqdn + normalise_fqdn.""" |
2 | 2 |
|
3 | | -from shared.url_utils import extract_fqdn, extract_hostname |
| 3 | +import pytest |
| 4 | + |
| 5 | +from shared.url_utils import extract_fqdn, extract_hostname, normalise_fqdn |
4 | 6 |
|
5 | 7 |
|
6 | 8 | class TestExtractHostname: |
@@ -49,3 +51,45 @@ def test_idempotent(self): |
49 | 51 | # so the cache key, the seeded custom_domains row, and the request |
50 | 52 | # middleware all agree on the canonical form. |
51 | 53 | assert extract_fqdn("HTTPS://Spoo.Me./") == extract_fqdn("https://spoo.me") |
| 54 | + |
| 55 | + |
| 56 | +class TestNormaliseFqdn: |
| 57 | + @pytest.mark.parametrize( |
| 58 | + "value, expected", |
| 59 | + [ |
| 60 | + ("links.acme.com", "links.acme.com"), |
| 61 | + ("LINKS.ACME.COM", "links.acme.com"), |
| 62 | + (" links.acme.com ", "links.acme.com"), |
| 63 | + ("links.acme.com.", "links.acme.com"), |
| 64 | + ("acme.co", "acme.co"), |
| 65 | + # Punycode TLD (encoded `.中国`) — required for IDN custom domains. |
| 66 | + ("links.xn--fiqs8s", "links.xn--fiqs8s"), |
| 67 | + # Multi-level subdomain |
| 68 | + ("a.b.c.example.com", "a.b.c.example.com"), |
| 69 | + ], |
| 70 | + ) |
| 71 | + def test_accepts_valid_inputs(self, value, expected): |
| 72 | + assert normalise_fqdn(value) == expected |
| 73 | + |
| 74 | + @pytest.mark.parametrize( |
| 75 | + "value", |
| 76 | + [ |
| 77 | + None, |
| 78 | + "", |
| 79 | + " ", |
| 80 | + "no_underscores_allowed.com", |
| 81 | + "-leading-hyphen.com", |
| 82 | + "trailing-hyphen-.com", |
| 83 | + "single-label", |
| 84 | + "two..consecutive.dots.com", |
| 85 | + "evil<script>.com", |
| 86 | + "evil`backtick.com", |
| 87 | + "evil\\backslash.com", |
| 88 | + "evil\x00null.com", |
| 89 | + "a" * 64 + ".com", # label > 63 chars |
| 90 | + "a" * 254 + ".com", # total > 253 chars |
| 91 | + ], |
| 92 | + ) |
| 93 | + def test_rejects_invalid_inputs(self, value): |
| 94 | + with pytest.raises(ValueError): |
| 95 | + normalise_fqdn(value) |
0 commit comments