Add prepare_url_slash to string_helpers.py and tests

Function cleans up url paths (without domain) by ensuring they start with a single slash and removing double slashes.
This commit is contained in:
Clemens Schwaighofer
2025-10-23 15:47:19 +09:00
parent fe69530b38
commit 53cf2a6f48
3 changed files with 121 additions and 2 deletions

View File

@@ -2,6 +2,7 @@
String helpers
"""
import re
from decimal import Decimal, getcontext
from textwrap import shorten
@@ -101,4 +102,21 @@ def format_number(number: float, precision: int = 0) -> str:
"f}"
).format(_number)
def prepare_url_slash(url: str) -> str:
"""
if the URL does not start with /, add slash
strip all double slashes in URL
Arguments:
url {str} -- _description_
Returns:
str -- _description_
"""
url = re.sub(r'\/+', '/', url)
if not url.startswith("/"):
url = "/" + url
return url
# __END__

View File

@@ -5,7 +5,7 @@ Test string_handling/string_helpers
import sys
from decimal import Decimal, getcontext
from textwrap import shorten
from corelibs.string_handling.string_helpers import shorten_string, format_number
from corelibs.string_handling.string_helpers import shorten_string, format_number, prepare_url_slash
from corelibs.string_handling.text_colors import Colors
@@ -73,6 +73,18 @@ def __sh_colors():
print(f"Underline/Yellow/Bold: {Colors.underline}{Colors.bold}{Colors.yellow}UNDERLINE YELLOW BOLD{Colors.reset}")
def __prepare_url_slash():
urls = [
"api/v1/resource",
"/api/v1/resource",
"///api//v1//resource//",
"api//v1/resource/",
]
for url in urls:
prepared = prepare_url_slash(url)
print(f"IN: {url} -> OUT: {prepared}")
def main():
"""
Test: corelibs.string_handling.string_helpers
@@ -80,6 +92,7 @@ def main():
__sh_shorten_string()
__sh_format_number()
__sh_colors()
__prepare_url_slash()
if __name__ == "__main__":

View File

@@ -5,7 +5,7 @@ PyTest: string_handling/string_helpers
from textwrap import shorten
import pytest
from corelibs.string_handling.string_helpers import (
shorten_string, left_fill, format_number
shorten_string, left_fill, format_number, prepare_url_slash
)
@@ -191,6 +191,75 @@ class TestFormatNumber:
assert result == "0.001"
class TestPrepareUrlSlash:
"""Tests for prepare_url_slash function"""
def test_url_without_leading_slash(self):
"""Test that URL without leading slash gets one added"""
result = prepare_url_slash("api/users")
assert result == "/api/users"
def test_url_with_leading_slash(self):
"""Test that URL with leading slash remains unchanged"""
result = prepare_url_slash("/api/users")
assert result == "/api/users"
def test_url_with_double_slashes(self):
"""Test that double slashes are reduced to single slash"""
result = prepare_url_slash("/api//users")
assert result == "/api/users"
def test_url_with_multiple_slashes(self):
"""Test that multiple consecutive slashes are reduced to single slash"""
result = prepare_url_slash("api///users////data")
assert result == "/api/users/data"
def test_url_with_leading_double_slash(self):
"""Test URL starting with double slash"""
result = prepare_url_slash("//api/users")
assert result == "/api/users"
def test_url_without_slash_and_double_slashes(self):
"""Test URL without leading slash and containing double slashes"""
result = prepare_url_slash("api//users//data")
assert result == "/api/users/data"
def test_single_slash(self):
"""Test single slash URL"""
result = prepare_url_slash("/")
assert result == "/"
def test_multiple_slashes_only(self):
"""Test URL with only multiple slashes"""
result = prepare_url_slash("///")
assert result == "/"
def test_empty_string(self):
"""Test empty string"""
result = prepare_url_slash("")
assert result == "/"
def test_url_with_query_params(self):
"""Test URL with query parameters"""
result = prepare_url_slash("/api/users?id=1")
assert result == "/api/users?id=1"
def test_url_with_double_slashes_and_query(self):
"""Test URL with double slashes and query parameters"""
result = prepare_url_slash("api//users?id=1")
assert result == "/api/users?id=1"
def test_complex_url_path(self):
"""Test complex URL path with multiple segments"""
result = prepare_url_slash("api/v1/users/123/profile")
assert result == "/api/v1/users/123/profile"
def test_complex_url_with_multiple_issues(self):
"""Test URL with both missing leading slash and multiple double slashes"""
result = prepare_url_slash("api//v1///users//123////profile")
assert result == "/api/v1/users/123/profile"
# Additional integration tests
class TestIntegration:
"""Integration tests combining functions"""
@@ -236,4 +305,23 @@ def test_format_number_parametrized(number: float | int, precision: int, expecte
"""Parametrized test for format_number"""
assert format_number(number, precision) == expected
@pytest.mark.parametrize("input_url,expected", [
("api/users", "/api/users"),
("/api/users", "/api/users"),
("api//users", "/api/users"),
("/api//users", "/api/users"),
("//api/users", "/api/users"),
("api///users////data", "/api/users/data"),
("/", "/"),
("///", "/"),
("", "/"),
("api/v1/users/123", "/api/v1/users/123"),
("/api/users?id=1&name=test", "/api/users?id=1&name=test"),
("api//users//123//profile", "/api/users/123/profile"),
])
def test_prepare_url_slash_parametrized(input_url: str, expected: str):
"""Parametrized test for prepare_url_slash"""
assert prepare_url_slash(input_url) == expected
# __END__