"""Tests for ledgrab.utils.url_scheme.infer_http_scheme.""" import pytest from ledgrab.utils.url_scheme import infer_http_scheme @pytest.mark.parametrize( "url", [ "http://192.168.1.10", "https://wled.example.com", "HTTP://wled.local", "HTTPS://example.com/api", "ws://device.local", "openrgb://localhost:6742/0", ], ) def test_preserves_existing_scheme(url): assert infer_http_scheme(url) == url @pytest.mark.parametrize( "raw", [ "192.168.1.10", "192.168.1.10:8080", "10.0.0.5", "172.16.1.1", "127.0.0.1", "localhost", "localhost:8080", "wled-desk.local", "wled-desk.local:80", "wled", # bare label ⇒ mDNS-style "kitchen-strip", "[::1]", "[fe80::1]:80", "fe80::1", # bracketless link-local IPv6 "device.lan", "rack.home", "service.internal", ], ) def test_local_targets_get_http(raw): assert infer_http_scheme(raw) == f"http://{raw}" @pytest.mark.parametrize( "raw", [ "example.com", "wled.example.com", "wled.example.com:443", "wled.example.com/api", "1.2.3.4", # public IPv4 "8.8.8.8:80", "my-host.io/path?x=1", ], ) def test_external_targets_get_https(raw): assert infer_http_scheme(raw) == f"https://{raw}" def test_trims_whitespace_before_inference(): assert infer_http_scheme(" 192.168.0.1 ") == "http://192.168.0.1" assert infer_http_scheme(" example.com ") == "https://example.com" def test_empty_string_returns_unchanged(): assert infer_http_scheme("") == "" def test_none_returns_unchanged(): # Callers occasionally hand us None; preserve it so the validator can complain. assert infer_http_scheme(None) is None def test_whitespace_only_collapses_to_empty(): # Whitespace alone has no host to infer a scheme for — trim and bail out. assert infer_http_scheme(" ") == "" # --------------------------------------------------------------------------- # Malicious / hostile inputs — must round-trip *unchanged* (no scheme # coerced onto them) so the downstream validator surfaces a clean error # rather than letting a coerced scheme slip past as a "valid" URL. # --------------------------------------------------------------------------- @pytest.mark.parametrize( "raw", [ "javascript:alert(1)", # already has a scheme — must pass through "data:text/html,