116 lines
3.8 KiB
Python
116 lines
3.8 KiB
Python
from fastapi.testclient import TestClient
|
|
from sqlalchemy import create_engine, Column, Integer, String, Date, Enum
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from sqlalchemy.orm import sessionmaker
|
|
|
|
DATABASE_URL = "sqlite:///./test_todo.db"
|
|
engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
|
|
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
|
|
Base = declarative_base()
|
|
|
|
class Todo(Base):
|
|
__tablename__ = "todos"
|
|
id = Column(Integer, primary_key=True, index=True)
|
|
title = Column(String(100), nullable=False)
|
|
description = Column(String(500))
|
|
due_date = Column(Date, nullable=False)
|
|
status = Column(Enum('pending', 'completed'), default='pending')
|
|
|
|
Base.metadata.create_all(bind=engine)
|
|
|
|
def get_db():
|
|
db = SessionLocal()
|
|
try:
|
|
yield db
|
|
finally:
|
|
db.close()
|
|
|
|
app = FastAPI()
|
|
|
|
@app.post("/todos/", response_model=Todo, status_code=201)
|
|
def create_todo(todo: TodoCreate, db: Session = Depends(get_db)):
|
|
db_todo = Todo(**todo.model_dump())
|
|
db.add(db_todo)
|
|
db.commit()
|
|
db.refresh(db_todo)
|
|
return db_todo
|
|
|
|
@app.get("/todos/", response_model=list[Todo])
|
|
def list_todos(status: str | None = None, db: Session = Depends(get_db)):
|
|
if status:
|
|
query = db.query(Todo).filter_by(status=status)
|
|
else:
|
|
query = db.query(Todo)
|
|
return query.all()
|
|
|
|
@app.get("/todos/{todo_id}", response_model=Todo)
|
|
def get_todo(todo_id: int, db: Session = Depends(get_db)):
|
|
todo = db.query(Todo).filter(Todo.id == todo_id).first()
|
|
if not todo:
|
|
raise HTTPException(status_code=404, detail="Not found")
|
|
return todo
|
|
|
|
@app.put("/todos/{todo_id}", response_model=Todo)
|
|
def update_todo(todo_id: int, todo: TodoCreate, db: Session = Depends(get_db)):
|
|
db_todo = db.query(Todo).filter(Todo.id == todo_id).first()
|
|
if not db_todo:
|
|
raise HTTPException(status_code=404, detail="Not found")
|
|
for key, value in todo.model_dump().items():
|
|
setattr(db_todo, key, value)
|
|
db.commit()
|
|
db.refresh(db_todo)
|
|
return db_todo
|
|
|
|
@app.delete("/todos/{todo_id}", status_code=204)
|
|
def delete_todo(todo_id: int, db: Session = Depends(get_db)):
|
|
db_todo = db.query(Todo).filter(Todo.id == todo_id).first()
|
|
if not db_todo:
|
|
raise HTTPException(status_code=404, detail="Not found")
|
|
db.delete(db_todo)
|
|
db.commit()
|
|
|
|
client = TestClient(app)
|
|
|
|
def test_create_todo():
|
|
response = client.post("/todos/", json={"title": "Test Todo", "description": "This is a test todo.", "due_date": "2023-12-31"})
|
|
assert response.status_code == 201
|
|
data = response.json()
|
|
assert "id" in data
|
|
assert data["title"] == "Test Todo"
|
|
assert data["description"] == "This is a test todo."
|
|
assert data["due_date"] == "2023-12-31"
|
|
assert data["status"] == "pending"
|
|
|
|
def test_list_todos():
|
|
response = client.get("/todos/")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert len(data) > 0
|
|
|
|
def test_get_todo_by_id():
|
|
todo_id = create_test_todo().json()["id"]
|
|
response = client.get(f"/todos/{todo_id}")
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "id" in data
|
|
assert data["title"] == "Test Todo"
|
|
|
|
def test_get_nonexistent_todo():
|
|
response = client.get("/todos/999")
|
|
assert response.status_code == 404
|
|
|
|
def test_update_todo():
|
|
todo_id = create_test_todo().json()["id"]
|
|
response = client.put(f"/todos/{todo_id}", json={"title": "Updated Todo"})
|
|
assert response.status_code == 200
|
|
data = response.json()
|
|
assert "id" in data
|
|
assert data["title"] == "Updated Todo"
|
|
|
|
def test_delete_todo():
|
|
todo_id = create_test_todo().json()["id"]
|
|
response = client.delete(f"/todos/{todo_id}")
|
|
assert response.status_code == 204
|
|
|
|
def create_test_todo():
|
|
return client.post("/todos/", json={"title": "Test Todo", "description": "This is a test todo.", "due_date": "2023 |