diff --git a/backend/tests/test_elements.py b/backend/tests/test_elements.py new file mode 100644 index 0000000..573a0ee --- /dev/null +++ b/backend/tests/test_elements.py @@ -0,0 +1,18 @@ +"""Test the elements API endpoints.""" + +import pytest +from httpx import ASGITransport, AsyncClient + +from app.main import app + + +@pytest.mark.asyncio +async def test_list_projects_returns_list(): + """Projects endpoint returns a list.""" + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + response = await client.get("/api/projects") + + assert response.status_code == 200 + assert isinstance(response.json(), list) + diff --git a/backend/tests/test_health.py b/backend/tests/test_health.py index fb28fc7..e3b795a 100644 --- a/backend/tests/test_health.py +++ b/backend/tests/test_health.py @@ -8,10 +8,10 @@ from app.main import app @pytest.mark.asyncio async def test_health_returns_ok(): + """Health endpoint returns status ok.""" transport = ASGITransport(app=app) async with AsyncClient(transport=transport, base_url="http://test") as client: response = await client.get("/health") assert response.status_code == 200 assert response.json() == {"status": "ok"} - diff --git a/backend/tests/test_models.py b/backend/tests/test_models.py new file mode 100644 index 0000000..e497ab7 --- /dev/null +++ b/backend/tests/test_models.py @@ -0,0 +1,46 @@ +"""Test database models and schema validation.""" + +from app.schemas.element import ProjectOut, ElementOut, PropertyOut +from uuid import uuid4 + + +def test_project_schema_validates(): + """ProjectOut schema accepts valid data.""" + data = { + "id": uuid4(), + "name": "Test Project", + "filename": "test.ifc", + "description": "A test", + "ifc_schema": "IFC4", + "element_count": 42, + } + project = ProjectOut(**data) + assert project.name == "Test Project" + assert project.element_count == 42 + + +def test_element_schema_validates(): + """ElementOut schema accepts valid data.""" + data = { + "id": uuid4(), + "global_id": "2XPyKWY018sA1ygZKgQPtU", + "ifc_type": "IfcWall", + "name": "Wall-1", + "description": "", + "storey": "Ground Floor", + } + element = ElementOut(**data) + assert element.ifc_type == "IfcWall" + + +def test_property_schema_validates(): + """PropertyOut schema accepts valid data.""" + data = { + "id": uuid4(), + "pset_name": "Pset_WallCommon", + "name": "ThermalTransmittance", + "value": "1.5", + } + prop = PropertyOut(**data) + assert prop.pset_name == "Pset_WallCommon" + diff --git a/backend/tests/test_upload.py b/backend/tests/test_upload.py new file mode 100644 index 0000000..49dc482 --- /dev/null +++ b/backend/tests/test_upload.py @@ -0,0 +1,34 @@ +"""Test the IFC upload endpoint.""" + +import pytest +from httpx import ASGITransport, AsyncClient + +from app.main import app + + +@pytest.mark.asyncio +async def test_upload_rejects_non_ifc(): + """Upload endpoint rejects files without .ifc extension.""" + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + response = await client.post( + "/api/upload", + files={"file": ("model.obj", b"dummy content", "application/octet-stream")}, + ) + + assert response.status_code == 400 + assert "Only .ifc files" in response.json()["detail"] + + +@pytest.mark.asyncio +async def test_upload_rejects_empty_filename(): + """Upload endpoint rejects files with wrong extension.""" + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://test") as client: + response = await client.post( + "/api/upload", + files={"file": ("readme.txt", b"not an ifc file", "text/plain")}, + ) + + assert response.status_code == 400 +