diff --git a/freedium-library/src/freedium_library/services/medium/container.py b/freedium-library/src/freedium_library/services/medium/container.py
index 029c085..1c0aaa1 100644
--- a/freedium-library/src/freedium_library/services/medium/container.py
+++ b/freedium-library/src/freedium_library/services/medium/container.py
@@ -1,10 +1,12 @@
from dependency_injector import containers, providers
+from freedium_library.services.medium.validators import (
+ MediumServicePathValidator,
+)
from freedium_library.utils.http import Request
from .api import MediumApiService
from .config import MediumConfig
-from .validators import MediumServicePathValidator
class MediumContainer(containers.DeclarativeContainer):
diff --git a/freedium-library/src/freedium_library/services/medium/static/__init__.py b/freedium-library/src/freedium_library/services/medium/static/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/freedium-library/src/freedium_library/services/medium/static/tests/__init__.py b/freedium-library/src/freedium_library/services/medium/static/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/freedium-library/src/freedium_library/services/medium/static/test_static.py b/freedium-library/src/freedium_library/services/medium/static/tests/test_static.py
similarity index 99%
rename from freedium-library/src/freedium_library/services/medium/static/test_static.py
rename to freedium-library/src/freedium_library/services/medium/static/tests/test_static.py
index c1eaab8..4946266 100644
--- a/freedium-library/src/freedium_library/services/medium/static/test_static.py
+++ b/freedium-library/src/freedium_library/services/medium/static/tests/test_static.py
@@ -44,7 +44,7 @@ def get_domains_from_file(filepath: str) -> list[str]:
def get_file_path(filename: str) -> str:
- return os.path.join(os.path.dirname(os.path.abspath(__file__)), filename)
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), "../", filename)
@pytest.mark.integration
diff --git a/freedium-library/src/freedium_library/services/medium/tests/__init__.py b/freedium-library/src/freedium_library/services/medium/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/freedium-library/src/freedium_library/services/medium/validators_hashes_test.py b/freedium-library/src/freedium_library/services/medium/tests/validators_hashes_test.py
similarity index 100%
rename from freedium-library/src/freedium_library/services/medium/validators_hashes_test.py
rename to freedium-library/src/freedium_library/services/medium/tests/validators_hashes_test.py
diff --git a/freedium-library/src/freedium_library/services/medium/validators_url_test.py b/freedium-library/src/freedium_library/services/medium/tests/validators_url_test.py
similarity index 100%
rename from freedium-library/src/freedium_library/services/medium/validators_url_test.py
rename to freedium-library/src/freedium_library/services/medium/tests/validators_url_test.py
diff --git a/freedium-library/src/freedium_library/utils/http/client/tests/__init__.py b/freedium-library/src/freedium_library/utils/http/client/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/freedium-library/src/freedium_library/utils/http/client/client_test.py b/freedium-library/src/freedium_library/utils/http/client/tests/client_test.py
similarity index 100%
rename from freedium-library/src/freedium_library/utils/http/client/client_test.py
rename to freedium-library/src/freedium_library/utils/http/client/tests/client_test.py
diff --git a/freedium-library/src/freedium_library/utils/meta/tests/__init__.py b/freedium-library/src/freedium_library/utils/meta/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/freedium-library/src/freedium_library/utils/meta/pydantic_test.py b/freedium-library/src/freedium_library/utils/meta/tests/pydantic_test.py
similarity index 100%
rename from freedium-library/src/freedium_library/utils/meta/pydantic_test.py
rename to freedium-library/src/freedium_library/utils/meta/tests/pydantic_test.py
diff --git a/freedium-library/src/freedium_library/utils/datetime_test.py b/freedium-library/src/freedium_library/utils/tests/datetime_test.py
similarity index 100%
rename from freedium-library/src/freedium_library/utils/datetime_test.py
rename to freedium-library/src/freedium_library/utils/tests/datetime_test.py
diff --git a/freedium-library/src/freedium_library/utils/json_test.py b/freedium-library/src/freedium_library/utils/tests/json_test.py
similarity index 100%
rename from freedium-library/src/freedium_library/utils/json_test.py
rename to freedium-library/src/freedium_library/utils/tests/json_test.py
diff --git a/freedium-library/src/freedium_library/utils/utils/test_utf_handler.py b/freedium-library/src/freedium_library/utils/utils/test_utf_handler.py
new file mode 100644
index 0000000..8a49aa1
--- /dev/null
+++ b/freedium-library/src/freedium_library/utils/utils/test_utf_handler.py
@@ -0,0 +1,145 @@
+from loguru import logger
+
+from freedium_library.utils.utils.utf_handler import UTFEncoding, UTFHandler
+
+logger.add("test.log", level="TRACE")
+
+
+def test_multibyte_emoji():
+ # Test string with emoji characters
+ text = "Noah dragged his two printers out from Settings โ๏ธ < Printers & Scanners ๐จ๏ธ and dropped them in Dock or Desktop, I donโt remember โ but you can drag to both the places.'"
+
+ # Initialize handler with UTF-16 encoding
+ handler = UTFHandler(text, UTFEncoding.UTF16)
+
+ assert str(handler) == text
+
+ # Test position mappings around emojis
+ assert handler.get_encoded_position(39) == 39 # Before "Settings โ๏ธ"
+ assert handler.get_encoded_position(76) == 77 # After "Scanners ๐จ๏ธ"
+
+ # Test string slicing around emoji
+ emoji_section = handler[39:76]
+ assert emoji_section == "Settings โ๏ธ < Printers & Scanners ๐จ๏ธ"
+
+ # Test insertion before emoji
+ handler.insert(39, "")
+ handler.insert(77, "")
+
+ expected = text[:39] + "" + text[39:76] + "" + text[76:]
+ # expected = expected.replace("๐จ๏ธ", "๐จ")
+
+ assert bytes(str(handler), "utf-8") == bytes(expected, "utf-8")
+ assert str(handler) == expected
+
+
+def test_mathematical_monospace_x():
+ text = "Whilst academic research papers have highlighted performance issues with the prophet since 2017, the propagation of package popularity through the data science community has been fueled by ๐๐ค๐ฉ๐ ๐๐ญ๐๐๐จ๐จ๐๐ซ๐ ๐๐ก๐๐๐ข๐จ ๐๐ง๐ค๐ข ๐ฉ๐๐ ๐ค๐ง๐๐๐๐ฃ๐๐ก ๐๐๐ซ๐๐ก๐ค๐ฅ๐ข๐๐ฃ๐ฉ ๐ฉ๐๐๐ข ๐๐ช๐ฉ ๐ข๐ค๐ง๐ ๐๐ข๐ฅ๐ค๐ง๐ฉ๐๐ฃ๐ฉ๐ก๐ฎ ๐๐ฎ ๐ข๐๐ง๐ ๐๐ฉ๐๐ฃ๐ ๐ค๐ ๐ฉ๐๐ ๐ฃ๐ค๐ฃ-๐ฅ๐๐ง๐๐ค๐ง๐ข๐๐ฃ๐ ๐ฅ๐๐๐ ๐๐๐ ๐ซ๐๐ ๐๐ง๐ฉ๐๐๐ก๐๐จ ๐ค๐ฃ ๐๐๐๐๐ช๐ข ๐๐ฃ๐ ๐จ๐ค๐๐๐๐ก ๐ข๐๐๐๐."
+
+ handler = UTFHandler(text, UTFEncoding.UTF16)
+
+ assert str(handler) == text
+
+ start_pos = text.index("๐")
+
+ assert handler.get_encoded_position(start_pos) == start_pos
+
+ o_multibyte = text.index("๐ค")
+ assert handler.get_encoded_position(o_multibyte) > o_multibyte
+
+ handler.insert(189, "")
+
+ expected = text[:189] + "" + text[193:]
+ assert str(handler) == expected
+
+
+def test_mathematical_monospace():
+ text = "by ๐๐ค๐ฉ๐ ๐๐ญ"
+
+ handler = UTFHandler(text, UTFEncoding.UTF16)
+
+ assert str(handler) == text
+
+ # Test encoded positions for mathematical monospace characters
+ assert handler.get_encoded_position(3) == 3 # Position before '๐'
+ assert handler.get_encoded_position(5) == 7 # Position after '๐'
+ assert handler.get_encoded_position(7) == 11 # Position after '๐ค'
+ # assert handler.get_encoded_position(9) == 15 # Position after '๐ฉ'
+
+ handler.insert(3, "")
+
+ expected = text[:3] + "" + text[7:]
+ assert str(handler) == expected
+
+
+def test_utf8_handling():
+ # Test with UTF-8 encoded text containing special characters
+ text = "Hello ไธ็! ๐"
+ handler = UTFHandler(text, UTFEncoding.UTF8)
+
+ assert str(handler) == text
+
+ # Test position mapping with UTF-8 characters
+ assert handler.get_encoded_position(6) == 6 # Position before 'ไธ'
+ assert handler.get_encoded_position(8) == 12 # Position after '็'
+
+ # Test insertion around UTF-8 characters
+ handler.insert(6, "")
+ handler.insert(17, "")
+
+ expected = "Hello ไธ็! ๐"
+ assert str(handler) == expected
+
+
+def test_utf32_handling():
+ # Test with UTF-32 encoded text
+ text = "Testing ๐ UTF-32 ๐ฏ"
+ handler = UTFHandler(text, UTFEncoding.UTF32)
+
+ assert str(handler) == text
+
+ # Test position mapping with UTF-32 characters
+ assert handler.get_encoded_position(8) == 8 # Position before rocket
+ assert handler.get_encoded_position(18) == 18 # Position before target
+
+ # Test deletion around UTF-32 characters
+ handler.delete(7, 2) # Delete " ๐ "
+ assert str(handler) == "Testing UTF-32 ๐ฏ"
+
+
+def test_edge_cases():
+ # Test empty string
+ handler = UTFHandler("", UTFEncoding.UTF16)
+ assert str(handler) == ""
+
+ # Test string with only special characters
+ handler = UTFHandler("๐โจ๐ซ", UTFEncoding.UTF16)
+ assert str(handler) == "๐โจ๐ซ"
+
+ # Test consecutive insertions
+ handler.insert(0, "<")
+ handler.insert(10, ">")
+ assert str(handler) == "<๐โจ๐ซ>"
+
+ # Test deletion at boundaries
+ handler.delete(1, 1) # Delete first emoji
+ assert str(handler) == "<โจ๐ซ>"
+
+
+def test_position_tracking():
+ text = "Mix of ASCII and ๆผขๅญ with ๐ฎ"
+ handler = UTFHandler(text, UTFEncoding.UTF16)
+
+ # Test position tracking before and after modifications
+ original_pos = handler.get_encoded_position(13) # Position before ๆผข
+ handler.insert(13, "[")
+ handler.insert(17, "]")
+
+ # Verify position tracking is maintained
+ new_pos = handler.get_encoded_position(14) # Should account for inserted '['
+ assert new_pos == original_pos + 1
+
+ expected = "Mix of ASCII [and] ๆผขๅญ with ๐ฎ"
+ assert str(handler) == expected