Skip to content

Commit 61a328c

Browse files
committed
test: add Open WebUI service tests
Tests for: - Config openwebui_available property - OpenWebUI service upload - Storage service integration with Open WebUI - Fallback to local URL on upload failure
1 parent d72a2ad commit 61a328c

1 file changed

Lines changed: 162 additions & 0 deletions

File tree

tests/test_openwebui.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
from unittest.mock import AsyncMock, MagicMock, patch
2+
3+
import pytest
4+
5+
6+
def test_openwebui_available_property():
7+
"""Test openwebui_available property."""
8+
from app.core.config import Settings
9+
10+
# Not available when URL missing
11+
settings = Settings(OPENWEBUI_API_URL=None, OPENWEBUI_API_KEY="key")
12+
assert settings.openwebui_available is False
13+
14+
# Not available when key missing
15+
settings = Settings(OPENWEBUI_API_URL="http://localhost", OPENWEBUI_API_KEY=None)
16+
assert settings.openwebui_available is False
17+
18+
# Available when both set
19+
settings = Settings(
20+
OPENWEBUI_API_URL="http://localhost", OPENWEBUI_API_KEY="key"
21+
)
22+
assert settings.openwebui_available is True
23+
24+
25+
@pytest.mark.asyncio
26+
async def test_openwebui_service_upload():
27+
"""Test Open WebUI upload service."""
28+
from app.services.openwebui_service import OpenWebUIService
29+
30+
with patch("app.services.openwebui_service.settings") as mock_settings:
31+
mock_settings.OPENWEBUI_API_URL = "https://chat.example.com"
32+
mock_settings.OPENWEBUI_API_KEY = "test-key"
33+
34+
service = OpenWebUIService()
35+
36+
# Mock httpx client
37+
mock_response = MagicMock()
38+
mock_response.json.return_value = {"id": "file-123"}
39+
mock_response.raise_for_status = MagicMock()
40+
41+
mock_client = MagicMock()
42+
mock_client.post = AsyncMock(return_value=mock_response)
43+
mock_client.__aenter__ = AsyncMock(return_value=mock_client)
44+
mock_client.__aexit__ = AsyncMock(return_value=None)
45+
46+
with patch(
47+
"app.services.openwebui_service.httpx.AsyncClient",
48+
return_value=mock_client,
49+
):
50+
url = await service.upload_image(b"test image data", "test.png")
51+
52+
assert url == "https://chat.example.com/api/v1/files/file-123/content"
53+
mock_client.post.assert_called_once()
54+
55+
# Verify the request
56+
call_args = mock_client.post.call_args
57+
assert call_args[0][0] == "https://chat.example.com/api/v1/files/"
58+
assert "Authorization" in call_args[1]["headers"]
59+
assert call_args[1]["headers"]["Authorization"] == "Bearer test-key"
60+
61+
62+
@pytest.mark.asyncio
63+
async def test_openwebui_service_upload_no_file_id():
64+
"""Test Open WebUI upload when response has no file ID."""
65+
from app.services.openwebui_service import OpenWebUIService
66+
67+
with patch("app.services.openwebui_service.settings") as mock_settings:
68+
mock_settings.OPENWEBUI_API_URL = "https://chat.example.com"
69+
mock_settings.OPENWEBUI_API_KEY = "test-key"
70+
71+
service = OpenWebUIService()
72+
73+
mock_response = MagicMock()
74+
mock_response.json.return_value = {} # No file ID
75+
mock_response.raise_for_status = MagicMock()
76+
77+
mock_client = MagicMock()
78+
mock_client.post = AsyncMock(return_value=mock_response)
79+
mock_client.__aenter__ = AsyncMock(return_value=mock_client)
80+
mock_client.__aexit__ = AsyncMock(return_value=None)
81+
82+
with patch(
83+
"app.services.openwebui_service.httpx.AsyncClient",
84+
return_value=mock_client,
85+
):
86+
with pytest.raises(ValueError, match="No file ID"):
87+
await service.upload_image(b"test", "test.png")
88+
89+
90+
@pytest.mark.asyncio
91+
async def test_storage_with_openwebui(temp_storage):
92+
"""Test storage service uploads to Open WebUI when configured."""
93+
from app.services.storage_service import StorageService
94+
95+
with patch("app.services.storage_service.settings") as mock_settings:
96+
mock_settings.STORAGE_PATH = str(temp_storage)
97+
mock_settings.IMAGE_BASE_URL = "http://localhost:8000"
98+
mock_settings.openwebui_available = True
99+
100+
service = StorageService()
101+
102+
# Mock the Open WebUI service
103+
mock_webui_service = MagicMock()
104+
mock_webui_service.upload_image = AsyncMock(
105+
return_value="https://chat.example.com/api/v1/files/123/content"
106+
)
107+
108+
with patch(
109+
"app.services.openwebui_service.get_openwebui_service",
110+
return_value=mock_webui_service,
111+
):
112+
url = await service.save_image(b"test image", "png")
113+
114+
# Should return Open WebUI URL
115+
assert url == "https://chat.example.com/api/v1/files/123/content"
116+
mock_webui_service.upload_image.assert_called_once()
117+
118+
119+
@pytest.mark.asyncio
120+
async def test_storage_fallback_on_openwebui_error(temp_storage):
121+
"""Test storage falls back to local URL when Open WebUI upload fails."""
122+
from app.services.storage_service import StorageService
123+
124+
with patch("app.services.storage_service.settings") as mock_settings:
125+
mock_settings.STORAGE_PATH = str(temp_storage)
126+
mock_settings.IMAGE_BASE_URL = "http://localhost:8000"
127+
mock_settings.openwebui_available = True
128+
129+
service = StorageService()
130+
131+
# Mock the Open WebUI service to fail
132+
mock_webui_service = MagicMock()
133+
mock_webui_service.upload_image = AsyncMock(
134+
side_effect=Exception("Upload failed")
135+
)
136+
137+
with patch(
138+
"app.services.openwebui_service.get_openwebui_service",
139+
return_value=mock_webui_service,
140+
):
141+
url = await service.save_image(b"test image", "png")
142+
143+
# Should fall back to local URL
144+
assert url.startswith("http://localhost:8000/images/")
145+
assert url.endswith(".png")
146+
147+
148+
@pytest.mark.asyncio
149+
async def test_storage_without_openwebui(temp_storage):
150+
"""Test storage service uses local URL when Open WebUI not configured."""
151+
from app.services.storage_service import StorageService
152+
153+
with patch("app.services.storage_service.settings") as mock_settings:
154+
mock_settings.STORAGE_PATH = str(temp_storage)
155+
mock_settings.IMAGE_BASE_URL = "http://localhost:8000"
156+
mock_settings.openwebui_available = False
157+
158+
service = StorageService()
159+
url = await service.save_image(b"test image", "png")
160+
161+
# Should return local URL
162+
assert url.startswith("http://localhost:8000/images/")

0 commit comments

Comments
 (0)