Add chat image upload support
This commit is contained in:
@@ -358,6 +358,64 @@ class TestAsyncChatClient:
|
||||
assert response.status_code == 200
|
||||
await client.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_presign_chat_file_post_url(self, api_key):
|
||||
"""Test async presigned chat file upload URL creation."""
|
||||
client = AsyncChatClient(api_key)
|
||||
|
||||
mock_response = Mock(spec=httpx.Response)
|
||||
mock_response.status_code = 200
|
||||
mock_response.json = Mock(return_value={
|
||||
"code": 200,
|
||||
"message": "",
|
||||
"data": {"url": "https://s3.example/upload", "fields": {"key": "chat/file.png"}},
|
||||
})
|
||||
|
||||
with patch.object(client, "_send_request", AsyncMock(return_value=mock_response)) as mock_send:
|
||||
result = await client.presign_chat_file_post_url(
|
||||
appId="app-123",
|
||||
chatId="chat-123",
|
||||
filename="file.png",
|
||||
fileSelectConfig={"canSelectImg": True},
|
||||
)
|
||||
|
||||
assert result["fields"]["key"] == "chat/file.png"
|
||||
assert mock_send.call_args[0][1] == "/api/core/chat/presignChatFilePostUrl"
|
||||
await client.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_upload_chat_image_with_fields_gets_preview_url(self, api_key, tmp_path):
|
||||
"""Test async upload_chat_image normalizes presigned POST uploads."""
|
||||
client = AsyncChatClient(api_key)
|
||||
file_path = tmp_path / "file.png"
|
||||
file_path.write_bytes(b"png")
|
||||
|
||||
with patch.object(client, "_get_chat_file_select_config", AsyncMock(return_value={"canSelectImg": True})), \
|
||||
patch.object(client, "presign_chat_file_post_url", AsyncMock(return_value={
|
||||
"url": "https://s3.example/upload",
|
||||
"fields": {"key": "chat/file.png"},
|
||||
"maxSize": 100,
|
||||
})) as mock_presign, \
|
||||
patch.object(client, "upload_to_presigned_url", AsyncMock()) as mock_upload, \
|
||||
patch.object(client, "presign_chat_file_get_url", AsyncMock(return_value="https://s3.example/preview.png")) as mock_get:
|
||||
result = await client.upload_chat_image(
|
||||
appId="app-123",
|
||||
chatId="chat-123",
|
||||
file_path=file_path,
|
||||
)
|
||||
|
||||
assert result == {
|
||||
"type": "img",
|
||||
"name": "file.png",
|
||||
"key": "chat/file.png",
|
||||
"url": "https://s3.example/preview.png",
|
||||
"previewUrl": "https://s3.example/preview.png",
|
||||
}
|
||||
assert mock_presign.call_args[1]["fileSelectConfig"] == {"canSelectImg": True}
|
||||
mock_upload.assert_awaited_once()
|
||||
mock_get.assert_awaited_once_with(appId="app-123", key="chat/file.png", outLinkAuthData=None)
|
||||
await client.close()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_chat_histories_basic(self, api_key, sample_chat_histories_response):
|
||||
"""Test getting chat histories with basic parameters."""
|
||||
|
||||
@@ -162,6 +162,120 @@ class TestChatClientCreateChatCompletion:
|
||||
mock_send.assert_called_once()
|
||||
|
||||
|
||||
class TestChatClientFileUpload:
|
||||
"""Test suite for ChatClient chat file upload helpers."""
|
||||
|
||||
def test_presign_chat_file_post_url_uses_local_path(self, api_key):
|
||||
client = ChatClient(api_key)
|
||||
|
||||
mock_response = Mock(spec=httpx.Response)
|
||||
mock_response.status_code = 200
|
||||
mock_response.json = Mock(return_value={
|
||||
"code": 200,
|
||||
"message": "",
|
||||
"data": {"url": "https://s3.example/upload", "fields": {"key": "chat/file.png"}},
|
||||
})
|
||||
|
||||
with patch.object(client, "_send_request", return_value=mock_response) as mock_send:
|
||||
result = client.presign_chat_file_post_url(
|
||||
appId="app-123",
|
||||
chatId="chat-123",
|
||||
filename="file.png",
|
||||
fileSelectConfig={"canSelectImg": True},
|
||||
)
|
||||
|
||||
assert result["fields"]["key"] == "chat/file.png"
|
||||
assert mock_send.call_args[0][1] == "/api/core/chat/presignChatFilePostUrl"
|
||||
assert mock_send.call_args[1]["json"]["fileSelectConfig"] == {"canSelectImg": True}
|
||||
|
||||
def test_presign_chat_file_get_url_unwraps_string(self, api_key):
|
||||
client = ChatClient(api_key)
|
||||
|
||||
mock_response = Mock(spec=httpx.Response)
|
||||
mock_response.status_code = 200
|
||||
mock_response.json = Mock(return_value={
|
||||
"code": 200,
|
||||
"message": "",
|
||||
"data": "https://s3.example/preview.png",
|
||||
})
|
||||
|
||||
with patch.object(client, "_send_request", return_value=mock_response) as mock_send:
|
||||
result = client.presign_chat_file_get_url(appId="app-123", key="chat/file.png")
|
||||
|
||||
assert result == "https://s3.example/preview.png"
|
||||
assert mock_send.call_args[0][1] == "/api/core/chat/presignChatFileGetUrl"
|
||||
|
||||
def test_upload_to_presigned_url_with_post_fields(self, api_key, tmp_path):
|
||||
client = ChatClient(api_key)
|
||||
file_path = tmp_path / "file.png"
|
||||
file_path.write_bytes(b"png")
|
||||
|
||||
mock_response = Mock(spec=httpx.Response)
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
with patch("fastgpt_client.client.httpx.post", return_value=mock_response) as mock_post:
|
||||
response = client.upload_to_presigned_url(
|
||||
upload_url="https://s3.example/upload",
|
||||
file_path=file_path,
|
||||
fields={"key": "chat/file.png", "policy": "abc"},
|
||||
)
|
||||
|
||||
assert response is mock_response
|
||||
mock_post.assert_called_once()
|
||||
assert mock_post.call_args[1]["data"] == {"key": "chat/file.png", "policy": "abc"}
|
||||
assert "file" in mock_post.call_args[1]["files"]
|
||||
|
||||
def test_upload_to_presigned_url_with_put_headers(self, api_key, tmp_path):
|
||||
client = ChatClient(api_key)
|
||||
file_path = tmp_path / "file.png"
|
||||
file_path.write_bytes(b"png")
|
||||
|
||||
mock_response = Mock(spec=httpx.Response)
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
with patch("fastgpt_client.client.httpx.put", return_value=mock_response) as mock_put:
|
||||
response = client.upload_to_presigned_url(
|
||||
upload_url="https://s3.example/upload",
|
||||
file_path=file_path,
|
||||
headers={"x-amz-meta-test": "1"},
|
||||
)
|
||||
|
||||
assert response is mock_response
|
||||
mock_put.assert_called_once()
|
||||
assert mock_put.call_args[1]["headers"]["x-amz-meta-test"] == "1"
|
||||
assert mock_put.call_args[1]["headers"]["Content-Type"] == "image/png"
|
||||
|
||||
def test_upload_chat_image_with_fields_gets_preview_url(self, api_key, tmp_path):
|
||||
client = ChatClient(api_key)
|
||||
file_path = tmp_path / "file.png"
|
||||
file_path.write_bytes(b"png")
|
||||
|
||||
with patch.object(client, "_get_chat_file_select_config", return_value={"canSelectImg": True}), \
|
||||
patch.object(client, "presign_chat_file_post_url", return_value={
|
||||
"url": "https://s3.example/upload",
|
||||
"fields": {"key": "chat/file.png"},
|
||||
"maxSize": 100,
|
||||
}) as mock_presign, \
|
||||
patch.object(client, "upload_to_presigned_url") as mock_upload, \
|
||||
patch.object(client, "presign_chat_file_get_url", return_value="https://s3.example/preview.png") as mock_get:
|
||||
result = client.upload_chat_image(
|
||||
appId="app-123",
|
||||
chatId="chat-123",
|
||||
file_path=file_path,
|
||||
)
|
||||
|
||||
assert result == {
|
||||
"type": "img",
|
||||
"name": "file.png",
|
||||
"key": "chat/file.png",
|
||||
"url": "https://s3.example/preview.png",
|
||||
"previewUrl": "https://s3.example/preview.png",
|
||||
}
|
||||
assert mock_presign.call_args[1]["fileSelectConfig"] == {"canSelectImg": True}
|
||||
mock_upload.assert_called_once()
|
||||
mock_get.assert_called_once_with(appId="app-123", key="chat/file.png", outLinkAuthData=None)
|
||||
|
||||
|
||||
class TestChatClientGetChatHistories:
|
||||
"""Test suite for ChatClient.get_chat_histories method."""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user