2026-07-26 16:09:04 +02:00
|
|
|
# retoor <retoor@molodetz.nl>
|
|
|
|
|
|
|
|
|
|
import unittest
|
|
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
from fastapi.testclient import TestClient
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
from typosaurus_sandbox.app import App
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
client = TestClient(App)
|
2026-07-26 16:09:04 +02:00
|
|
|
|
|
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
class TestHealthEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_health_returns_ok(self) -> None:
|
|
|
|
|
response = client.get("/health")
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"status": "ok"})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestCalculatorAddEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_add_positive_integers(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/add", json={"left": 3, "right": 5})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 8})
|
|
|
|
|
|
|
|
|
|
def test_add_negative_integers(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/add", json={"left": -3, "right": -5})
|
2026-07-26 16:09:04 +02:00
|
|
|
self.assertEqual(response.status_code, 200)
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
self.assertEqual(response.json(), {"result": -8})
|
|
|
|
|
|
|
|
|
|
def test_add_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/add", json={"left": "abc", "right": 5})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_add_missing_field_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/add", json={"left": 3})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
2026-07-26 16:09:04 +02:00
|
|
|
|
|
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
class TestCalculatorSubtractEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_subtract_positive(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/subtract", json={"left": 10, "right": 3})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 7})
|
|
|
|
|
|
|
|
|
|
def test_subtract_negative_result(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/subtract", json={"left": 3, "right": 10})
|
2026-07-26 16:09:04 +02:00
|
|
|
self.assertEqual(response.status_code, 200)
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
self.assertEqual(response.json(), {"result": -7})
|
|
|
|
|
|
|
|
|
|
def test_subtract_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/subtract", json={"left": 10, "right": None})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
2026-07-26 16:09:04 +02:00
|
|
|
|
test(sveta): Write API integration tests for calculator endpoints
Outcome: done
Changed: tests/test_api.py:53-68,75-85,90-98 — added clamp low>high, missing-field, and subtract missing-field tests; src/typosaurus_sandbox/presentation/api/v1/calculator.py:2,51-55 — added HTTPException import and ValueError catch in calculate_clamp
Verified by: `make verify` — exit 0, 47 tests OK, zero warnings, zero compile errors
Findings:
- tests/test_api.py now contains 22 integration tests covering all five endpoints with success, validation errors (missing fields, wrong types), and the clamp low>high ValueError boundary.
- clamp low>high error is returned as 422 via HTTPException in the route handler, matching the acceptance criterion.
- All 47 tests (25 unit + 22 integration) pass with zero warnings.
Open: none
Confidence: high — all acceptance criteria addressed, all tests pass, verification gate passed
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: 9fe1a5bb3c164f6eb359366ca55b1067
Typosaurus-Agent: @sveta
Refs: #15
2026-07-26 18:40:14 +02:00
|
|
|
def test_subtract_missing_left_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/subtract", json={"right": 3})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_subtract_missing_right_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/subtract", json={"left": 10})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
class TestCalculatorClampEndpoint(unittest.TestCase):
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_clamp_value_below_low(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": -5, "low": 0, "high": 10})
|
2026-07-26 16:09:04 +02:00
|
|
|
self.assertEqual(response.status_code, 200)
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
self.assertEqual(response.json(), {"result": 0})
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_clamp_value_above_high(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": 15, "low": 0, "high": 10})
|
2026-07-26 16:09:04 +02:00
|
|
|
self.assertEqual(response.status_code, 200)
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
self.assertEqual(response.json(), {"result": 10})
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_clamp_value_in_range(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": 5, "low": 0, "high": 10})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 5.0})
|
|
|
|
|
|
|
|
|
|
def test_clamp_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": "x", "low": 0, "high": 10})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
2026-07-26 16:09:04 +02:00
|
|
|
|
test(sveta): Write API integration tests for calculator endpoints
Outcome: done
Changed: tests/test_api.py:53-68,75-85,90-98 — added clamp low>high, missing-field, and subtract missing-field tests; src/typosaurus_sandbox/presentation/api/v1/calculator.py:2,51-55 — added HTTPException import and ValueError catch in calculate_clamp
Verified by: `make verify` — exit 0, 47 tests OK, zero warnings, zero compile errors
Findings:
- tests/test_api.py now contains 22 integration tests covering all five endpoints with success, validation errors (missing fields, wrong types), and the clamp low>high ValueError boundary.
- clamp low>high error is returned as 422 via HTTPException in the route handler, matching the acceptance criterion.
- All 47 tests (25 unit + 22 integration) pass with zero warnings.
Open: none
Confidence: high — all acceptance criteria addressed, all tests pass, verification gate passed
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: 9fe1a5bb3c164f6eb359366ca55b1067
Typosaurus-Agent: @sveta
Refs: #15
2026-07-26 18:40:14 +02:00
|
|
|
def test_clamp_low_greater_than_high_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": 5, "low": 10, "high": 0})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_clamp_missing_low_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": 5, "high": 10})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_clamp_missing_high_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp", json={"value": 5, "low": 0})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
class TestCalculatorClampToByteEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_clamp_to_byte_within_range(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp-to-byte", json={"value": 128})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 128})
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_clamp_to_byte_below_zero(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp-to-byte", json={"value": -10})
|
2026-07-26 16:09:04 +02:00
|
|
|
self.assertEqual(response.status_code, 200)
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
self.assertEqual(response.json(), {"result": 0})
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_clamp_to_byte_above_255(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp-to-byte", json={"value": 300})
|
2026-07-26 16:09:04 +02:00
|
|
|
self.assertEqual(response.status_code, 200)
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
self.assertEqual(response.json(), {"result": 255})
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Implement FastAPI application with calculator endpoints
```yaml
Outcome: done
Changed:
- pyproject.toml:1-18
- src/typosaurus_sandbox/__init__.py:1-4
- src/typosaurus_sandbox/__main__.py:1-8
- src/typosaurus_sandbox/app.py:1-18
- src/typosaurus_sandbox/domain/__init__.py:1-1
- src/typosaurus_sandbox/domain/calculator/__init__.py:1-6
- src/typosaurus_sandbox/domain/calculator/operations.py:1-23
- src/typosaurus_sandbox/presentation/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/__init__.py:1-1
- src/typosaurus_sandbox/presentation/api/v1/calculator.py:1-63
- tests/__init__.py (unchanged)
- tests/test_calculator.py:1-95
- tests/test_api.py:1-120
- Makefile:2
- CLAUDE.md:4-23
Verified by: `make verify` — exit 0, 42 tests OK, zero warnings
Findings:
- FastAPI application created at src/typosaurus_sandbox/app.py with App importable as `from typosaurus_sandbox import App`.
- Calculator HTTP API router at src/typosaurus_sandbox/presentation/api/v1/calculator.py with endpoints: POST /api/v1/calculator/add, POST /api/v1/calculator/subtract, POST /api/v1/calculator/clamp, POST /api/v1/calculator/clamp-to-byte.
- Health endpoint at GET /health implemented directly on App in src/typosaurus_sandbox/app.py.
- All endpoints use Pydantic models for request validation and response serialization (AddRequest, SubtractRequest, ClampRequest, ClampToByteRequest, IntResult, FloatResult).
- 42 tests pass (16 unit tests for calculator function
Typosaurus-Run: d4f7c095ea9d49c69663ae6d01a21513
Typosaurus-Node: d0f507214bf6453cab8f8d19b8fd2040
Typosaurus-Agent: @nadia
Refs: #15
2026-07-26 18:38:43 +02:00
|
|
|
def test_clamp_to_byte_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/clamp-to-byte", json={"value": "abc"})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
2026-07-26 16:09:04 +02:00
|
|
|
|
feat(nadia): Expose missing calculator operations as API endpoints
Outcome: done
Changed:
src/typosaurus_sandbox/presentation/api/v1/calculator.py — added imports (average, median, variance, percentage, logging), ValuesRequest model, PercentageRequest model, and four new endpoint handlers with logging and ValueError → 422 conversion
tests/test_api.py — added 26 test cases across four new test classes
Verified by: `make verify` — 93 tests, 0 failures, 0 new warnings
Findings:
- `ValuesRequest` model accepts `values: list[float]` and serves /average, /median, /variance
- `PercentageRequest` model accepts `value: float, total: float` for /percentage
- All four endpoints log at DEBUG level on invocation
- Empty list (average, median, variance) and zero total (percentage) produce HTTP 422 with descriptive detail
Open: none
Confidence: high — 26 new tests pass, zero regressions, pattern matches existing endpoint conventions
Typosaurus-Run: 34b5946ec981488091bee588eb919ff2
Typosaurus-Node: 644d226aefca431c81cf8be8a46d2070
Typosaurus-Agent: @nadia
Refs: #28
2026-07-27 00:30:18 +02:00
|
|
|
|
|
|
|
|
class TestCalculatorAverageEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_average_positive_values(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/average", json={"values": [1, 2, 3, 4, 5]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 3.0})
|
|
|
|
|
|
|
|
|
|
def test_average_single_value(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/average", json={"values": [5]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 5.0})
|
|
|
|
|
|
|
|
|
|
def test_average_negative_values(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/average", json={"values": [-10, -20, -30]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": -20.0})
|
|
|
|
|
|
|
|
|
|
def test_average_empty_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/average", json={"values": []})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_average_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/average", json={"values": ["a", "b"]})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_average_missing_field_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/average", json={})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestCalculatorMedianEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_median_odd_length(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={"values": [1, 3, 5]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 3.0})
|
|
|
|
|
|
|
|
|
|
def test_median_even_length(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={"values": [1, 2, 3, 4]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 2.5})
|
|
|
|
|
|
|
|
|
|
def test_median_single_element(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={"values": [7]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 7.0})
|
|
|
|
|
|
|
|
|
|
def test_median_unsorted_input(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={"values": [3, 1, 2]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 2.0})
|
|
|
|
|
|
|
|
|
|
def test_median_empty_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={"values": []})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_median_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={"values": ["a"]})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_median_missing_field_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/median", json={})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestCalculatorVarianceEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_variance_known_set(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/variance", json={"values": [1, 2, 3, 4, 5]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 2.0})
|
|
|
|
|
|
|
|
|
|
def test_variance_constant_values(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/variance", json={"values": [1.0, 1.0, 1.0]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 0.0})
|
|
|
|
|
|
|
|
|
|
def test_variance_single_element(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/variance", json={"values": [42.0]})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 0.0})
|
|
|
|
|
|
|
|
|
|
def test_variance_empty_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/variance", json={"values": []})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_variance_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/variance", json={"values": ["a", "b", "c"]})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_variance_missing_field_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/variance", json={})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TestCalculatorPercentageEndpoint(unittest.TestCase):
|
|
|
|
|
|
|
|
|
|
def test_percentage_half(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"value": 50, "total": 100})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 50.0})
|
|
|
|
|
|
|
|
|
|
def test_percentage_quarter(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"value": 25, "total": 100})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 25.0})
|
|
|
|
|
|
|
|
|
|
def test_percentage_zero_value(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"value": 0, "total": 100})
|
|
|
|
|
self.assertEqual(response.status_code, 200)
|
|
|
|
|
self.assertEqual(response.json(), {"result": 0.0})
|
|
|
|
|
|
|
|
|
|
def test_percentage_total_zero_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"value": 50, "total": 0})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_percentage_invalid_input_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"value": "abc", "total": 100})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_percentage_missing_value_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"total": 100})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
def test_percentage_missing_total_returns_422(self) -> None:
|
|
|
|
|
response = client.post("/api/v1/calculator/percentage", json={"value": 50})
|
|
|
|
|
self.assertEqual(response.status_code, 422)
|
|
|
|
|
|
|
|
|
|
|