Skip to content

Commit e54a6da

Browse files
committed
test: add 404 handler unit and integration tests
1 parent cbdf2b5 commit e54a6da

File tree

2 files changed

+573
-0
lines changed

2 files changed

+573
-0
lines changed
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
import tempfile
2+
from pathlib import Path
3+
from uuid import uuid4
4+
5+
import pytest
6+
from httpx import ASGITransport, AsyncClient
7+
from langflow.main import setup_app
8+
9+
10+
@pytest.fixture
11+
def static_files_dir():
12+
"""Create a temporary directory with a fake index.html."""
13+
with tempfile.TemporaryDirectory() as tmpdir:
14+
index_path = Path(tmpdir) / "index.html"
15+
index_path.write_text("<!DOCTYPE html><html><body>SPA App</body></html>")
16+
yield Path(tmpdir)
17+
18+
19+
@pytest.fixture
20+
async def app_with_static_files(static_files_dir):
21+
"""Create app with static files handler (production-like setup)."""
22+
return setup_app(static_files_dir=static_files_dir, backend_only=False)
23+
24+
25+
class TestProjectEndpoints404Integration:
26+
"""Integration tests for project endpoints returning JSON when ID not found."""
27+
28+
@pytest.mark.no_blockbuster
29+
async def test_get_nonexistent_project_returns_json_not_html(self, app_with_static_files):
30+
"""Test that getting a non-existent project returns JSON, not HTML."""
31+
fake_id = str(uuid4())
32+
33+
async with AsyncClient(
34+
transport=ASGITransport(app=app_with_static_files),
35+
base_url="http://testserver",
36+
) as client:
37+
response = await client.get(f"/api/v1/projects/{fake_id}")
38+
39+
assert "text/html" not in response.headers.get("content-type", "")
40+
assert "application/json" in response.headers.get("content-type", "")
41+
42+
43+
class TestFlowEndpoints404Integration:
44+
"""Integration tests for flow endpoints returning JSON when ID not found."""
45+
46+
@pytest.mark.no_blockbuster
47+
async def test_get_nonexistent_flow_returns_json_not_html(self, app_with_static_files):
48+
"""Test that getting a non-existent flow returns JSON, not HTML."""
49+
fake_id = str(uuid4())
50+
51+
async with AsyncClient(
52+
transport=ASGITransport(app=app_with_static_files),
53+
base_url="http://testserver",
54+
) as client:
55+
response = await client.get(f"/api/v1/flows/{fake_id}")
56+
57+
assert "text/html" not in response.headers.get("content-type", "")
58+
assert "application/json" in response.headers.get("content-type", "")
59+
60+
@pytest.mark.no_blockbuster
61+
async def test_delete_nonexistent_flow_returns_json_not_html(self, app_with_static_files):
62+
"""Test that deleting a non-existent flow returns JSON, not HTML."""
63+
fake_id = str(uuid4())
64+
65+
async with AsyncClient(
66+
transport=ASGITransport(app=app_with_static_files),
67+
base_url="http://testserver",
68+
) as client:
69+
response = await client.delete(f"/api/v1/flows/{fake_id}")
70+
71+
assert "text/html" not in response.headers.get("content-type", "")
72+
assert "application/json" in response.headers.get("content-type", "")
73+
74+
@pytest.mark.no_blockbuster
75+
async def test_patch_nonexistent_flow_returns_json_not_html(self, app_with_static_files):
76+
"""Test that patching a non-existent flow returns JSON, not HTML."""
77+
fake_id = str(uuid4())
78+
79+
async with AsyncClient(
80+
transport=ASGITransport(app=app_with_static_files),
81+
base_url="http://testserver",
82+
) as client:
83+
response = await client.patch(
84+
f"/api/v1/flows/{fake_id}",
85+
json={"name": "Updated Name"},
86+
)
87+
88+
assert "text/html" not in response.headers.get("content-type", "")
89+
assert "application/json" in response.headers.get("content-type", "")
90+
91+
92+
class TestVariableEndpoints404Integration:
93+
"""Integration tests for variable endpoints returning JSON when ID not found."""
94+
95+
@pytest.mark.no_blockbuster
96+
async def test_patch_nonexistent_variable_returns_json_not_html(self, app_with_static_files):
97+
"""Test that patching a non-existent variable returns JSON, not HTML."""
98+
fake_id = str(uuid4())
99+
100+
async with AsyncClient(
101+
transport=ASGITransport(app=app_with_static_files),
102+
base_url="http://testserver",
103+
) as client:
104+
response = await client.patch(
105+
f"/api/v1/variables/{fake_id}",
106+
json={"id": fake_id, "name": "updated_var", "value": "new_value"},
107+
)
108+
109+
assert "text/html" not in response.headers.get("content-type", "")
110+
assert "application/json" in response.headers.get("content-type", "")
111+
112+
@pytest.mark.no_blockbuster
113+
async def test_delete_nonexistent_variable_returns_json_not_html(self, app_with_static_files):
114+
"""Test that deleting a non-existent variable returns JSON, not HTML."""
115+
fake_id = str(uuid4())
116+
117+
async with AsyncClient(
118+
transport=ASGITransport(app=app_with_static_files),
119+
base_url="http://testserver",
120+
) as client:
121+
response = await client.delete(f"/api/v1/variables/{fake_id}")
122+
123+
assert "text/html" not in response.headers.get("content-type", "")
124+
assert "application/json" in response.headers.get("content-type", "")
125+
126+
127+
class TestUserEndpoints404Integration:
128+
"""Integration tests for user endpoints returning JSON when ID not found."""
129+
130+
@pytest.mark.no_blockbuster
131+
async def test_patch_nonexistent_user_returns_json_not_html(self, app_with_static_files):
132+
"""Test that patching a non-existent user returns JSON, not HTML."""
133+
fake_id = str(uuid4())
134+
135+
async with AsyncClient(
136+
transport=ASGITransport(app=app_with_static_files),
137+
base_url="http://testserver",
138+
) as client:
139+
response = await client.patch(
140+
f"/api/v1/users/{fake_id}",
141+
json={"username": "new_username"},
142+
)
143+
144+
assert "text/html" not in response.headers.get("content-type", "")
145+
assert "application/json" in response.headers.get("content-type", "")
146+
147+
@pytest.mark.no_blockbuster
148+
async def test_delete_nonexistent_user_returns_json_not_html(self, app_with_static_files):
149+
"""Test that deleting a non-existent user returns JSON, not HTML."""
150+
fake_id = str(uuid4())
151+
152+
async with AsyncClient(
153+
transport=ASGITransport(app=app_with_static_files),
154+
base_url="http://testserver",
155+
) as client:
156+
response = await client.delete(f"/api/v1/users/{fake_id}")
157+
158+
assert "text/html" not in response.headers.get("content-type", "")
159+
assert "application/json" in response.headers.get("content-type", "")
160+
161+
162+
class TestKnowledgeBaseEndpoints404Integration:
163+
"""Integration tests for knowledge base endpoints returning JSON when ID not found."""
164+
165+
@pytest.mark.no_blockbuster
166+
async def test_get_nonexistent_knowledge_base_returns_json_not_html(self, app_with_static_files):
167+
"""Test that getting a non-existent knowledge base returns JSON, not HTML."""
168+
fake_name = "nonexistent-kb-12345"
169+
170+
async with AsyncClient(
171+
transport=ASGITransport(app=app_with_static_files),
172+
base_url="http://testserver",
173+
) as client:
174+
response = await client.get(f"/api/v1/knowledge_bases/{fake_name}")
175+
176+
assert "text/html" not in response.headers.get("content-type", "")
177+
assert "application/json" in response.headers.get("content-type", "")
178+
179+
@pytest.mark.no_blockbuster
180+
async def test_delete_nonexistent_knowledge_base_returns_json_not_html(self, app_with_static_files):
181+
"""Test that deleting a non-existent knowledge base returns JSON, not HTML."""
182+
fake_name = "nonexistent-kb-12345"
183+
184+
async with AsyncClient(
185+
transport=ASGITransport(app=app_with_static_files),
186+
base_url="http://testserver",
187+
) as client:
188+
response = await client.delete(f"/api/v1/knowledge_bases/{fake_name}")
189+
190+
assert "text/html" not in response.headers.get("content-type", "")
191+
assert "application/json" in response.headers.get("content-type", "")
192+
193+
194+
class TestApiKeyEndpoints404Integration:
195+
"""Integration tests for API key endpoints returning JSON when ID not found."""
196+
197+
@pytest.mark.no_blockbuster
198+
async def test_delete_nonexistent_api_key_returns_json_not_html(self, app_with_static_files):
199+
"""Test that deleting a non-existent API key returns JSON, not HTML."""
200+
fake_id = str(uuid4())
201+
202+
async with AsyncClient(
203+
transport=ASGITransport(app=app_with_static_files),
204+
base_url="http://testserver",
205+
) as client:
206+
response = await client.delete(f"/api/v1/api_key/{fake_id}")
207+
208+
assert "text/html" not in response.headers.get("content-type", "")
209+
assert "application/json" in response.headers.get("content-type", "")
210+
211+
212+
class TestFilesV2Endpoints404Integration:
213+
"""Integration tests for files v2 endpoints returning JSON when ID not found."""
214+
215+
@pytest.mark.no_blockbuster
216+
async def test_get_nonexistent_file_returns_json_not_html(self, app_with_static_files):
217+
"""Test that getting a non-existent file returns JSON, not HTML."""
218+
fake_id = str(uuid4())
219+
220+
async with AsyncClient(
221+
transport=ASGITransport(app=app_with_static_files),
222+
base_url="http://testserver",
223+
) as client:
224+
response = await client.get(f"/api/v2/files/{fake_id}")
225+
226+
assert "text/html" not in response.headers.get("content-type", "")
227+
assert "application/json" in response.headers.get("content-type", "")
228+
229+
@pytest.mark.no_blockbuster
230+
async def test_put_nonexistent_file_returns_json_not_html(self, app_with_static_files):
231+
"""Test that updating a non-existent file returns JSON, not HTML."""
232+
fake_id = str(uuid4())
233+
234+
async with AsyncClient(
235+
transport=ASGITransport(app=app_with_static_files),
236+
base_url="http://testserver",
237+
) as client:
238+
response = await client.put(
239+
f"/api/v2/files/{fake_id}",
240+
params={"name": "updated_file"},
241+
)
242+
243+
assert "text/html" not in response.headers.get("content-type", "")
244+
assert "application/json" in response.headers.get("content-type", "")
245+
246+
@pytest.mark.no_blockbuster
247+
async def test_delete_nonexistent_file_returns_json_not_html(self, app_with_static_files):
248+
"""Test that deleting a non-existent file returns JSON, not HTML."""
249+
fake_id = str(uuid4())
250+
251+
async with AsyncClient(
252+
transport=ASGITransport(app=app_with_static_files),
253+
base_url="http://testserver",
254+
) as client:
255+
response = await client.delete(f"/api/v2/files/{fake_id}")
256+
257+
assert "text/html" not in response.headers.get("content-type", "")
258+
assert "application/json" in response.headers.get("content-type", "")

0 commit comments

Comments
 (0)