"""Tests for URL join utilities.""" from __future__ import annotations from shared.utils import _join_url_parts, join_url, normalize_text, soup_of # --------------------------------------------------------------------------- # _join_url_parts # --------------------------------------------------------------------------- class TestJoinUrlParts: def test_empty_list(self): assert _join_url_parts([]) == "" def test_single_part(self): assert _join_url_parts(["hello"]) == "hello" def test_two_parts(self): assert _join_url_parts(["https://example.com", "path"]) == "https://example.com/path" def test_preserves_scheme(self): assert _join_url_parts(["https://example.com/", "/api/", "v1"]) == "https://example.com/api/v1" def test_trailing_slash_preserved(self): result = _join_url_parts(["https://example.com", "path/"]) assert result.endswith("/") def test_no_trailing_slash_when_last_has_none(self): result = _join_url_parts(["https://example.com", "path"]) assert not result.endswith("/") def test_strips_internal_slashes(self): result = _join_url_parts(["https://example.com/", "/api/", "/v1"]) assert result == "https://example.com/api/v1" def test_absolute_url_mid_list_replaces(self): result = _join_url_parts(["https://old.com/foo", "https://new.com/bar"]) assert result == "https://new.com/bar" def test_query_string_attached(self): result = _join_url_parts(["https://example.com/path", "?key=val"]) assert result == "https://example.com/path?key=val" def test_fragment_attached(self): result = _join_url_parts(["https://example.com/path", "#section"]) assert result == "https://example.com/path#section" def test_filters_none_and_empty(self): result = _join_url_parts(["https://example.com", None, "", "path"]) assert result == "https://example.com/path" def test_no_scheme(self): result = _join_url_parts(["/foo", "bar", "baz/"]) assert result == "foo/bar/baz/" def test_multiple_segments(self): result = _join_url_parts(["https://example.com", "a", "b", "c/"]) assert result == "https://example.com/a/b/c/" # --------------------------------------------------------------------------- # join_url # --------------------------------------------------------------------------- class TestJoinUrl: def test_string_input(self): assert join_url("https://example.com") == "https://example.com" def test_list_input(self): assert join_url(["https://example.com", "path"]) == "https://example.com/path" def test_tuple_input(self): assert join_url(("https://example.com", "path/")) == "https://example.com/path/" # --------------------------------------------------------------------------- # normalize_text # --------------------------------------------------------------------------- class TestNormalizeText: def test_collapses_whitespace(self): assert normalize_text(" hello world ") == "hello world" def test_tabs_and_newlines(self): assert normalize_text("hello\t\nworld") == "hello world" def test_empty_string(self): assert normalize_text("") == "" def test_none_input(self): assert normalize_text(None) == "" def test_single_word(self): assert normalize_text(" word ") == "word" # --------------------------------------------------------------------------- # soup_of # --------------------------------------------------------------------------- class TestSoupOf: def test_parses_html(self): s = soup_of("

Hello world

") assert s.find("b").text == "world" def test_empty_html(self): s = soup_of("") assert s.text == ""