import unittest from contextlib import contextmanager from unittest.mock import patch from fastapi.testclient import TestClient from ca_api.app import app class _FakeCursor: pass @contextmanager def _fake_db_cursor(): # Mimics ca_api.db.db_cursor() which yields a cursor yield _FakeCursor() class TestApiUnit(unittest.TestCase): @classmethod def setUpClass(cls): cls.client = TestClient(app) def test_create_creator_201(self): with patch("ca_api.app.db_cursor", _fake_db_cursor), \ patch("ca_api.app.entity_core.insert_creator", return_value=123) as m_insert: payload = {"name": "Alice", "public_key": "pk-alice"} r = self.client.post("/creators", json=payload) self.assertEqual(r.status_code, 201) self.assertEqual(r.json(), {"id": 123}) # Ensure core called with (cursor, name, public_key) args, kwargs = m_insert.call_args self.assertIsInstance(args[0], _FakeCursor) self.assertEqual(args[1], "Alice") self.assertEqual(args[2], "pk-alice") self.assertEqual(kwargs, {}) def test_get_entity_404(self): with patch("ca_api.app.db_cursor", _fake_db_cursor), \ patch("ca_api.app.entity_core.get_entity", return_value=None): r = self.client.get("/entities/99999") self.assertEqual(r.status_code, 404) self.assertEqual(r.json()["detail"], "Entity not found") def test_get_entity_200(self): # FastAPI returns dict(row), so return any mapping-like object here with patch("ca_api.app.db_cursor", _fake_db_cursor), \ patch("ca_api.app.entity_core.get_entity", return_value={"id": 7, "name": "Bob"}): r = self.client.get("/entities/7") self.assertEqual(r.status_code, 200) self.assertEqual(r.json()["id"], 7) self.assertEqual(r.json()["name"], "Bob") def test_set_property_400_on_value_error(self): def _raise(*args, **kwargs): raise ValueError("bad property") with patch("ca_api.app.db_cursor", _fake_db_cursor), \ patch("ca_api.app.property_core.set_property", side_effect=_raise): payload = {"entity_id": 1, "property_name": "email", "validation_policy": "default"} r = self.client.post("/properties", json=payload) self.assertEqual(r.status_code, 400) self.assertEqual(r.json()["detail"], "bad property") def test_add_member_201(self): with patch("ca_api.app.db_cursor", _fake_db_cursor), \ patch("ca_api.app.group_core.add_group_member", return_value=None) as m_add: payload = {"group_id": 10, "member_id": 20, "role": "admin"} r = self.client.post("/groups/members", json=payload) self.assertEqual(r.status_code, 201) self.assertEqual(r.json(), {"ok": True}) args, kwargs = m_add.call_args self.assertIsInstance(args[0], _FakeCursor) self.assertEqual(args[1:], (10, 20, "admin")) self.assertEqual(kwargs, {})