Files
MAIA/backend/tests/test_todo.py

211 lines
8.2 KiB
Python

import pytest
from fastapi import status
from fastapi.testclient import TestClient
from sqlalchemy.orm import Session
from datetime import date
from tests.helpers import generators
from modules.todo import schemas # Import schemas
# Helper Function
def _login_user(db: Session, client: TestClient):
user, password = generators.create_user(db)
login_rsp = generators.login(db, user.username, password)
return user, login_rsp["access_token"], login_rsp["refresh_token"]
# --- Test CRUD Operations ---
def test_create_todo(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
today_date = date.today()
# Format the date string to match the expected response format "YYYY-MM-DDTHH:MM:SS"
todo_data = {
"task": "Test TODO",
"date": f"{today_date.isoformat()}T00:00:00",
"remind": True
}
response = client.post(
"/api/todos/",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token},
json=todo_data
)
assert response.status_code == status.HTTP_201_CREATED
data = response.json()
assert data["task"] == todo_data["task"]
assert data["date"] == todo_data["date"]
assert data["remind"] == todo_data["remind"]
assert data["complete"] is False # Default
assert "id" in data
assert data["owner_id"] == user.id
def test_read_todos(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
# Create some todos for the user
client.post("/api/todos/", headers={"Authorization": f"Bearer {access_token}"}, cookies={"refresh_token": refresh_token}, json={"task": "Todo 1"})
client.post("/api/todos/", headers={"Authorization": f"Bearer {access_token}"}, cookies={"refresh_token": refresh_token}, json={"task": "Todo 2"})
# Create a todo for another user
other_user, other_password = generators.create_user(db)
other_login_rsp = generators.login(db, other_user.username, other_password)
other_access_token = other_login_rsp["access_token"]
other_refresh_token = other_login_rsp["refresh_token"]
client.post("/api/todos/", headers={"Authorization": f"Bearer {other_access_token}"}, cookies={"refresh_token": other_refresh_token}, json={"task": "Other User Todo"})
response = client.get(
"/api/todos/",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert len(data) == 2 # Should only get todos for the logged-in user
assert data[0]["task"] == "Todo 1"
assert data[1]["task"] == "Todo 2"
def test_read_single_todo(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
create_response = client.post(
"/api/todos/",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token},
json={"task": "Specific Todo"}
)
todo_id = create_response.json()["id"]
response = client.get(
f"/api/todos/{todo_id}",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["id"] == todo_id
assert data["task"] == "Specific Todo"
assert data["owner_id"] == user.id
def test_read_single_todo_not_found(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
response = client.get(
"/api/todos/9999", # Non-existent ID
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert response.status_code == status.HTTP_404_NOT_FOUND
def test_read_single_todo_forbidden(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
# Create a todo for another user
other_user, other_password = generators.create_user(db)
other_login_rsp = generators.login(db, other_user.username, other_password)
other_access_token = other_login_rsp["access_token"]
other_refresh_token = other_login_rsp["refresh_token"]
other_create_response = client.post("/api/todos/", headers={"Authorization": f"Bearer {other_access_token}"}, cookies={"refresh_token": other_refresh_token}, json={"task": "Other User Todo"})
other_todo_id = other_create_response.json()["id"]
# Try to access the other user's todo
response = client.get(
f"/api/todos/{other_todo_id}",
headers={"Authorization": f"Bearer {access_token}"}, # Using the first user's token
cookies={"refresh_token": refresh_token}
)
assert response.status_code == status.HTTP_404_NOT_FOUND # Service raises 404 if not found for *this* user
def test_update_todo(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
create_response = client.post(
"/api/todos/",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token},
json={"task": "Update Me"}
)
todo_id = create_response.json()["id"]
update_data = {"task": "Updated Task", "complete": True}
response = client.put(
f"/api/todos/{todo_id}",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token},
json=update_data
)
assert response.status_code == status.HTTP_200_OK
data = response.json()
assert data["id"] == todo_id
assert data["task"] == update_data["task"]
assert data["complete"] == update_data["complete"]
assert data["owner_id"] == user.id
# Verify update by reading again
get_response = client.get(
f"/api/todos/{todo_id}",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert get_response.json()["task"] == update_data["task"]
assert get_response.json()["complete"] == update_data["complete"]
def test_update_todo_not_found(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
update_data = {"task": "Updated Task", "complete": True}
response = client.put(
"/api/todos/9999", # Non-existent ID
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token},
json=update_data
)
assert response.status_code == status.HTTP_404_NOT_FOUND
def test_delete_todo(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
create_response = client.post(
"/api/todos/",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token},
json={"task": "Delete Me"}
)
todo_id = create_response.json()["id"]
response = client.delete(
f"/api/todos/{todo_id}",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert response.status_code == status.HTTP_200_OK # Delete returns the deleted item
assert response.json()["id"] == todo_id
# Verify deletion by trying to read
get_response = client.get(
f"/api/todos/{todo_id}",
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert get_response.status_code == status.HTTP_404_NOT_FOUND
def test_delete_todo_not_found(client: TestClient, db: Session):
user, access_token, refresh_token = _login_user(db, client)
response = client.delete(
"/api/todos/9999", # Non-existent ID
headers={"Authorization": f"Bearer {access_token}"},
cookies={"refresh_token": refresh_token}
)
assert response.status_code == status.HTTP_404_NOT_FOUND
# --- Test Authentication/Authorization ---
def test_create_todo_unauthorized(client: TestClient):
response = client.post("/api/todos/", json={"task": "No Auth"})
assert response.status_code == status.HTTP_401_UNAUTHORIZED
def test_read_todos_unauthorized(client: TestClient):
response = client.get("/api/todos/")
assert response.status_code == status.HTTP_401_UNAUTHORIZED