Files
hao-ai-lab-FastVideo/fastvideo/tests/entrypoints/test_image_response_format_validation.py
T
Davids048andClaude Opus 5.5 96b7c0d223 [refactor]: build OpenAI image requests as typed requests
The image routes call VideoGenerator.generate with a GenerationRequest
instead of passing flat generate_video keywords. The flat projection
_build_generation_kwargs in video_api.py had no runtime caller, so it is
removed, and its tests exercise build_generation_request instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012M91wnVFmPEvJ9h39r5BH7
2026-10-03 02:03:51 +00:00

102 lines
4.1 KiB
Python

# SPDX-License-Identifier: Apache-2.0
"""Validate image response formats before invoking the generator."""
import base64
from pathlib import Path
from types import SimpleNamespace
from unittest.mock import AsyncMock, Mock
import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from fastvideo.entrypoints.openai import image_api
from fastvideo.entrypoints.openai.stores import AsyncDictStore
@pytest.fixture
def image_client(monkeypatch, tmp_path):
generate = Mock(side_effect=lambda request: Path(request.output.output_path).write_bytes(b"test-image-content"))
async def run_serialized(fn, *args, **kwargs):
return fn(*args, **kwargs)
engine = SimpleNamespace(
generator=SimpleNamespace(generate=generate),
run_serialized=AsyncMock(side_effect=run_serialized),
)
monkeypatch.setattr(image_api, "get_serving_engine", lambda: engine)
monkeypatch.setattr(image_api, "get_output_dir", lambda: str(tmp_path))
monkeypatch.setattr(image_api, "IMAGE_STORE", AsyncDictStore())
app = FastAPI()
app.include_router(image_api.router)
with TestClient(app) as client:
yield client, engine
@pytest.mark.parametrize("response_format", ["invalid", "INVALID"])
def test_invalid_response_format_does_not_generate(image_client, response_format, tmp_path):
client, engine = image_client
response = client.post("/v1/images", json={"prompt": "a cat", "response_format": response_format})
assert response.status_code == 400
assert response.json()["detail"] == "response_format=invalid is not supported"
engine.run_serialized.assert_not_awaited()
engine.generator.generate.assert_not_called()
assert not (tmp_path / "images").exists()
def test_edits_invalid_response_format_does_not_generate(image_client, tmp_path):
client, engine = image_client
response = client.post(
"/v1/images/edits",
data={"prompt": "a cat", "response_format": "invalid"},
files={"image": ("cat.png", b"fake-image", "image/png")},
)
assert response.status_code == 400
assert response.json()["detail"] == "response_format=invalid is not supported"
engine.run_serialized.assert_not_awaited()
engine.generator.generate.assert_not_called()
assert not (tmp_path / "uploads").exists()
@pytest.mark.parametrize(
"payload,expected",
[
pytest.param({"prompt": "a cat"}, "url", id="omitted-uses-protocol-default"),
pytest.param({"prompt": "a cat", "response_format": None}, "b64_json", id="null-falls-back-to-b64-json"),
pytest.param({"prompt": "a cat", "response_format": ""}, "b64_json", id="empty-falls-back-to-b64-json"),
pytest.param({"prompt": "a cat", "response_format": "b64_json"}, "b64_json", id="b64-json"),
pytest.param({"prompt": "a cat", "response_format": "B64_JSON"}, "b64_json", id="b64-json-uppercase"),
pytest.param({"prompt": "a cat", "response_format": "url"}, "url", id="url"),
pytest.param({"prompt": "a cat", "response_format": "URL"}, "url", id="url-uppercase"),
],
)
def test_supported_response_formats_still_generate(image_client, payload, expected):
client, engine = image_client
response = client.post("/v1/images", json=payload)
assert response.status_code == 200, response.text
body = response.json()
if expected == "url":
assert body["data"][0]["url"] == f"/v1/images/{body['id']}/content"
else:
assert base64.b64decode(body["data"][0]["b64_json"]) == b"test-image-content"
engine.run_serialized.assert_awaited_once()
engine.generator.generate.assert_called_once()
def test_edits_supported_response_format_still_generates(image_client):
client, engine = image_client
response = client.post(
"/v1/images/edits",
data={"prompt": "a cat", "response_format": "b64_json"},
files={"image": ("cat.png", b"fake-image", "image/png")},
)
assert response.status_code == 200, response.text
assert base64.b64decode(response.json()["data"][0]["b64_json"]) == b"test-image-content"
engine.run_serialized.assert_awaited_once()
engine.generator.generate.assert_called_once()