Spaces:
Sleeping
Sleeping
Download backend/tests/api/test_logs_write.py from Aynkhn/Face-Expression-Analyzer: direct link, hf CLI and curl.
- Browser
- Download file 4.47 kB
-
https://huggingface.co/spaces/Aynkhn/Face-Expression-Analyzer/resolve/main/backend/tests/api/test_logs_write.py
- Command line
-
hf download hf://spaces/Aynkhn/Face-Expression-Analyzer/backend/tests/api/test_logs_write.py
-
curl -L -o test_logs_write.py https://huggingface.co/spaces/Aynkhn/Face-Expression-Analyzer/resolve/main/backend/tests/api/test_logs_write.py
4.47 kB
| """Write-path route tests.""" | |
| from __future__ import annotations | |
| import pytest | |
| from app.schemas.emotion_log import EMOTION_NAMES | |
| class TestCreate: | |
| def test_accepts_every_valid_emotion(self, client, ingest_headers, emotion): | |
| response = client.post( | |
| "/api/logs", | |
| json={"dominant_emotion": emotion, "duration_seconds": 10}, | |
| headers=ingest_headers, | |
| ) | |
| assert response.status_code == 201 | |
| assert response.json()["dominant_emotion"] == emotion | |
| def test_rejects_unknown_emotion_with_422(self, client, ingest_headers): | |
| """Previously a hand-rolled validator; now a Literal, so the error is typed.""" | |
| response = client.post( | |
| "/api/logs", | |
| json={"dominant_emotion": "Ecstatic", "duration_seconds": 10}, | |
| headers=ingest_headers, | |
| ) | |
| assert response.status_code == 422 | |
| def test_rejects_out_of_range_duration(self, client, ingest_headers, duration): | |
| response = client.post( | |
| "/api/logs", | |
| json={"dominant_emotion": "Happy", "duration_seconds": duration}, | |
| headers=ingest_headers, | |
| ) | |
| assert response.status_code == 422 | |
| def test_response_includes_server_assigned_fields(self, client, ingest_headers): | |
| body = client.post( | |
| "/api/logs", | |
| json={"dominant_emotion": "Happy", "duration_seconds": 10}, | |
| headers=ingest_headers, | |
| ).json() | |
| assert isinstance(body["id"], int) | |
| assert body["timestamp"] | |
| def test_timestamp_carries_an_explicit_utc_offset(self, client, ingest_headers): | |
| """Without an offset, browsers parse the value as local time. | |
| SQLite returns a naive datetime even for a column declared timezone-aware, | |
| so the serialiser has to reattach UTC. A bare "2026-08-13T22:01:45" would | |
| shift every displayed record by the viewer's offset. | |
| """ | |
| body = client.post( | |
| "/api/logs", | |
| json={"dominant_emotion": "Happy", "duration_seconds": 10}, | |
| headers=ingest_headers, | |
| ).json() | |
| assert body["timestamp"].endswith(("Z", "+00:00")) | |
| def test_listed_timestamps_carry_an_offset(self, client, ingest_headers, session_headers): | |
| client.post( | |
| "/api/logs", | |
| json={"dominant_emotion": "Sad", "duration_seconds": 10}, | |
| headers=ingest_headers, | |
| ) | |
| items = client.get("/api/logs", headers=session_headers).json()["items"] | |
| assert items | |
| assert all(item["timestamp"].endswith(("Z", "+00:00")) for item in items) | |
| class TestBulkCreate: | |
| def test_creates_all_items(self, client, ingest_headers): | |
| items = [{"dominant_emotion": "Happy", "duration_seconds": 10} for _ in range(5)] | |
| response = client.post("/api/logs/bulk", json={"items": items}, headers=ingest_headers) | |
| assert response.status_code == 201 | |
| body = response.json() | |
| assert body["created"] == 5 | |
| assert body["rejected"] == 0 | |
| def test_reports_per_item_indexes(self, client, ingest_headers): | |
| items = [{"dominant_emotion": "Sad", "duration_seconds": 10} for _ in range(3)] | |
| body = client.post("/api/logs/bulk", json={"items": items}, headers=ingest_headers).json() | |
| assert [entry["index"] for entry in body["results"]] == [0, 1, 2] | |
| def test_rejects_empty_batch(self, client, ingest_headers): | |
| response = client.post("/api/logs/bulk", json={"items": []}, headers=ingest_headers) | |
| assert response.status_code == 422 | |
| def test_rejects_oversized_batch(self, client, ingest_headers): | |
| items = [{"dominant_emotion": "Happy", "duration_seconds": 10}] * 501 | |
| response = client.post("/api/logs/bulk", json={"items": items}, headers=ingest_headers) | |
| assert response.status_code == 422 | |
| def test_invalid_item_fails_the_batch_validation(self, client, ingest_headers): | |
| items = [ | |
| {"dominant_emotion": "Happy", "duration_seconds": 10}, | |
| {"dominant_emotion": "Nonsense", "duration_seconds": 10}, | |
| ] | |
| response = client.post("/api/logs/bulk", json={"items": items}, headers=ingest_headers) | |
| assert response.status_code == 422 | |