""" Integration tests for the /api/v2/packs endpoints. Uses FastAPI's TestClient (starlette) with an isolated SQLite test database. The db_transaction fixture in conftest.py rolls back all changes after each test. """ import pytest from starlette.testclient import TestClient from app.main import app TEST_TOKEN = "test_token_12345" AUTH_HEADERS = {"Authorization": f"Bearer {TEST_TOKEN}"} @pytest.fixture def client(): """Return a TestClient for the FastAPI app.""" return TestClient(app, raise_server_exceptions=True) class TestGetPacks: """Tests for GET /api/v2/packs.""" def test_empty_database_returns_404(self, client): """With no packs in the DB, the endpoint should return 404.""" resp = client.get("/api/v2/packs") assert resp.status_code == 404 def test_returns_pack_list(self, client, sample_pack): """With at least one pack, GET /packs returns count and list.""" resp = client.get("/api/v2/packs") assert resp.status_code == 200 data = resp.json() assert "count" in data assert data["count"] >= 1 assert "packs" in data assert len(data["packs"]) >= 1 def test_filter_by_team_id(self, client, sample_pack, sample_team): """team_id filter should return only packs for that team.""" resp = client.get(f"/api/v2/packs?team_id={sample_team.id}") assert resp.status_code == 200 data = resp.json() for pack in data["packs"]: assert pack["team"]["id"] == sample_team.id def test_filter_by_invalid_team_returns_404(self, client, sample_pack): """Filtering by a non-existent team_id should return 404.""" resp = client.get("/api/v2/packs?team_id=999999") assert resp.status_code == 404 def test_filter_opened_false(self, client, sample_pack): """opened=false should return only packs with no open_time.""" resp = client.get("/api/v2/packs?opened=false") assert resp.status_code == 200 data = resp.json() for pack in data["packs"]: assert pack["open_time"] is None class TestGetOnePack: """Tests for GET /api/v2/packs/{pack_id}.""" def test_get_existing_pack(self, client, sample_pack): """GET with a valid pack_id should return that pack's data.""" resp = client.get(f"/api/v2/packs/{sample_pack.id}") assert resp.status_code == 200 data = resp.json() assert data["id"] == sample_pack.id def test_get_nonexistent_pack_returns_404(self, client): """GET with an unknown pack_id should return 404.""" resp = client.get("/api/v2/packs/999999") assert resp.status_code == 404 class TestPostPack: """Tests for POST /api/v2/packs — requires auth token.""" def test_post_without_token_returns_401( self, client, sample_team, sample_pack_type ): """POST without Authorization header should return 422 (missing field).""" payload = { "packs": [{"team_id": sample_team.id, "pack_type_id": sample_pack_type.id}] } resp = client.post("/api/v2/packs", json=payload) # FastAPI returns 422 when required OAuth2 token is missing assert resp.status_code == 422 def test_post_with_invalid_token_returns_401( self, client, sample_team, sample_pack_type ): """POST with a wrong token should return 401.""" payload = { "packs": [{"team_id": sample_team.id, "pack_type_id": sample_pack_type.id}] } resp = client.post( "/api/v2/packs", json=payload, headers={"Authorization": "Bearer wrong_token"}, ) assert resp.status_code == 401 def test_post_with_valid_token_creates_packs( self, client, sample_team, sample_pack_type ): """POST with valid token and payload should create the packs (returns 200).""" payload = { "packs": [{"team_id": sample_team.id, "pack_type_id": sample_pack_type.id}] } resp = client.post("/api/v2/packs", json=payload, headers=AUTH_HEADERS) # The router raises HTTPException(200) on success assert resp.status_code == 200 class TestDeletePack: """Tests for DELETE /api/v2/packs/{pack_id} — requires auth token.""" def test_delete_nonexistent_pack_returns_404(self, client): """Deleting a pack that doesn't exist should return 404.""" resp = client.delete("/api/v2/packs/999999", headers=AUTH_HEADERS) assert resp.status_code == 404 def test_delete_without_token_returns_401_or_422(self, client, sample_pack): """DELETE without a token should fail auth.""" resp = client.delete(f"/api/v2/packs/{sample_pack.id}") assert resp.status_code in (401, 422)