116 lines
4 KiB
Python
116 lines
4 KiB
Python
import unittest
|
|
import importlib
|
|
from fastapi.testclient import TestClient
|
|
|
|
import tests.test_data as test_data
|
|
|
|
from db import connect, create
|
|
import main
|
|
|
|
|
|
def reload_test_data():
|
|
global test_data
|
|
test_data = importlib.reload(test_data)
|
|
|
|
|
|
@unittest.skip("Legacy v1 API removed; covered by v2 household-scoped tests")
|
|
class TestV1API(unittest.IsolatedAsyncioTestCase):
|
|
async def asyncSetUp(self):
|
|
self.conn = await connect(":memory:")
|
|
await create(self.conn)
|
|
await test_data.create_test_data(self.conn)
|
|
reload_test_data()
|
|
|
|
async def override_get_db():
|
|
try:
|
|
yield self.conn
|
|
finally:
|
|
pass
|
|
|
|
main.app.dependency_overrides[main.get_db] = override_get_db
|
|
self.client = TestClient(main.app)
|
|
return await super().asyncSetUp()
|
|
|
|
async def asyncTearDown(self) -> None:
|
|
await self.conn.close()
|
|
main.app.dependency_overrides.clear()
|
|
return await super().asyncTearDown()
|
|
|
|
def test_v1_recipes_page_envelope(self):
|
|
resp = self.client.get("/api/v1/recipes")
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
assert isinstance(body, dict)
|
|
assert "items" in body
|
|
assert isinstance(body["items"], list)
|
|
assert len(body["items"]) >= 0
|
|
|
|
def test_v1_persons_page_envelope(self):
|
|
resp = self.client.get("/api/v1/persons")
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
assert isinstance(body, dict)
|
|
assert "items" in body
|
|
assert isinstance(body["items"], list)
|
|
|
|
def test_v1_recipe_not_found_problem(self):
|
|
resp = self.client.get("/api/v1/recipes/999999")
|
|
assert resp.status_code == 404
|
|
assert "application/problem+json" in resp.headers.get("content-type", "")
|
|
prob = resp.json()
|
|
assert prob.get("status") == 404
|
|
assert "title" in prob
|
|
assert "type" in prob
|
|
|
|
def test_v1_meal_create_no_chefs_problem(self):
|
|
meal_data = {
|
|
"id": -1,
|
|
"suggestedDate": "2024-06-01T18:00:00+00:00",
|
|
"chefs": [],
|
|
"cleanup": [{"id": 1, "name": "Ryan"}],
|
|
"consumers": [{"id": 1, "name": "Ellie"}],
|
|
"recipes": [],
|
|
"extraIngredients": [],
|
|
}
|
|
resp = self.client.post("/api/v1/meals", json=meal_data)
|
|
assert resp.status_code == 400
|
|
assert "application/problem+json" in resp.headers.get("content-type", "")
|
|
prob = resp.json()
|
|
assert prob.get("status") == 400
|
|
assert "title" in prob
|
|
|
|
def test_v1_login_not_found_problem(self):
|
|
resp = self.client.post("/api/v1/auth/login", json={"username": "nope"})
|
|
assert resp.status_code == 404
|
|
assert "application/problem+json" in resp.headers.get("content-type", "")
|
|
prob = resp.json()
|
|
assert prob.get("status") == 404
|
|
assert prob.get("title")
|
|
|
|
def test_v1_camel_case_keys(self):
|
|
# persons endpoint should return camelCase in v1
|
|
resp = self.client.get("/api/v1/persons")
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
assert "items" in body # Page envelope
|
|
if body["items"]:
|
|
# pick first person
|
|
person = body["items"][0]
|
|
assert "id" in person
|
|
assert "name" in person
|
|
|
|
def test_v1_cursor_edge_cases(self):
|
|
# invalid cursor should be treated as start
|
|
resp = self.client.get("/api/v1/recipes?cursor=notanint&limit=1")
|
|
assert resp.status_code == 200
|
|
body = resp.json()
|
|
assert "items" in body
|
|
# end-of-list cursor
|
|
# get all to compute a large cursor
|
|
all_resp = self.client.get("/api/v1/recipes?limit=200")
|
|
items = all_resp.json()["items"]
|
|
if items:
|
|
last_id = items[-1]["id"]
|
|
after_last = self.client.get(f"/api/v1/recipes?cursor={last_id}&limit=200")
|
|
after_body = after_last.json()
|
|
assert after_body["items"] == [] or after_body.get("nextCursor") is None
|