mirror of
https://github.com/dat515-2025/Group-8.git
synced 2026-03-22 15:12:08 +01:00
feat(test): added more tests
This commit is contained in:
@@ -64,3 +64,128 @@ async def test_create_transaction_missing_amount_fails(fastapi_app, test_user):
|
||||
|
||||
# 4. Assert the expected validation error
|
||||
assert resp.status_code == status.HTTP_422_UNPROCESSABLE_ENTITY
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_login_invalid_credentials(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
bad = await ac.post("/auth/jwt/login", data={"username": test_user["username"], "password": "nope"})
|
||||
assert bad.status_code in (status.HTTP_401_UNAUTHORIZED, status.HTTP_400_BAD_REQUEST)
|
||||
unknown = await ac.post("/auth/jwt/login", data={"username": "nouser@example.com", "password": "x"})
|
||||
assert unknown.status_code in (status.HTTP_401_UNAUTHORIZED, status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_category_duplicate_name_conflict(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
p = {"name": "Food"}
|
||||
r1 = await ac.post("/categories/create", json=p, headers=h)
|
||||
assert r1.status_code == status.HTTP_201_CREATED
|
||||
r2 = await ac.post("/categories/create", json=p, headers=h)
|
||||
assert r2.status_code == status.HTTP_409_CONFLICT
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_create_transaction_invalid_date_format(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
bad = await ac.post("/transactions/create", json={"amount": 10, "description": "x", "date": "31-12-2024"}, headers=h)
|
||||
assert bad.status_code == status.HTTP_400_BAD_REQUEST
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_update_transaction_rejects_duplicate_category_ids(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
tx = (await ac.post("/transactions/create", json={"amount": 5, "description": "x"}, headers=h)).json()
|
||||
dup = await ac.patch(f"/transactions/{tx['id']}/edit", json={"category_ids": [1, 1]}, headers=h)
|
||||
assert dup.status_code == status.HTTP_400_BAD_REQUEST
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_assign_unassign_category_not_found_cases(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
# Create tx and category
|
||||
tx = (await ac.post("/transactions/create", json={"amount": 1, "description": "a"}, headers=h)).json()
|
||||
cat = (await ac.post("/categories/create", json={"name": "X"}, headers=h)).json()
|
||||
|
||||
# Missing transaction
|
||||
r1 = await ac.post(f"/transactions/999999/categories/{cat['id']}", headers=h)
|
||||
assert r1.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
# Missing category
|
||||
r2 = await ac.post(f"/transactions/{tx['id']}/categories/999999", headers=h)
|
||||
assert r2.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_transactions_date_filter_and_balance_series(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
# Seed transactions spanning days
|
||||
data = [
|
||||
{"amount": 100, "description": "day1", "date": "2024-01-01"},
|
||||
{"amount": -25, "description": "day2", "date": "2024-01-02"},
|
||||
{"amount": 50, "description": "day3", "date": "2024-01-03"},
|
||||
]
|
||||
for p in data:
|
||||
r = await ac.post("/transactions/create", json=p, headers=h)
|
||||
assert r.status_code == status.HTTP_201_CREATED
|
||||
|
||||
# Filtered list (2nd and 3rd only)
|
||||
lst = await ac.get("/transactions/", params={"start_date": "2024-01-02", "end_date": "2024-01-03"}, headers=h)
|
||||
assert lst.status_code == status.HTTP_200_OK
|
||||
assert len(lst.json()) == 2
|
||||
|
||||
# Balance series should be cumulative per date
|
||||
series = await ac.get("/transactions/balance_series", headers=h)
|
||||
assert series.status_code == status.HTTP_200_OK
|
||||
s = series.json()
|
||||
assert s == [
|
||||
{"date": "2024-01-01", "balance": 100.0},
|
||||
{"date": "2024-01-02", "balance": 75.0},
|
||||
{"date": "2024-01-03", "balance": 125.0},
|
||||
]
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_transaction_not_found(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
r = await ac.delete("/transactions/999999/delete", headers=h)
|
||||
assert r.status_code == status.HTTP_404_NOT_FOUND
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_debug_csas_endpoints_require_auth_and_queue(fastapi_app, test_user):
|
||||
transport = ASGITransport(app=fastapi_app)
|
||||
async with AsyncClient(transport=transport, base_url="http://testserver") as ac:
|
||||
# unauthenticated should be blocked
|
||||
unauth = await ac.get("/debug/scrape/csas/all")
|
||||
assert unauth.status_code in (status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN)
|
||||
|
||||
token = (await ac.post("/auth/jwt/login", data=test_user)).json()["access_token"]
|
||||
h = {"Authorization": f"Bearer {token}"}
|
||||
|
||||
all_resp = await ac.get("/debug/scrape/csas/all", headers=h)
|
||||
assert all_resp.status_code == status.HTTP_200_OK
|
||||
assert all_resp.json()["status"] == "queued"
|
||||
|
||||
# Single-user CSAS requires auth and user dep; using current user id via /users/me
|
||||
me = await ac.get("/users/me", headers=h)
|
||||
uid = me.json()["id"]
|
||||
one = await ac.post(f"/debug/scrape/csas/{uid}", headers=h)
|
||||
assert one.status_code == status.HTTP_200_OK
|
||||
assert one.json()["status"] == "queued"
|
||||
|
||||
Reference in New Issue
Block a user