Add 134 tests as independent test project: - test_auth.py (5): Login, JWT, protected endpoints - test_users.py (8): User CRUD, permissions - test_projects.py (8): Project CRUD, ownership - test_milestones.py (7): Milestone CRUD, filtering - test_tasks.py (8): Task CRUD, filtering - test_comments.py (5): Comment CRUD, permissions - test_roles.py (9): Role/permission management - test_milestone_actions.py (17): Milestone state machine - test_task_transitions.py (34): Task state machine - test_propose.py (19): Propose CRUD, lifecycle - test_misc.py (14): Notifications, activity, API keys, dashboard Setup: - conftest.py: SQLite in-memory DB, fixtures - requirements.txt: Dependencies - pyproject.toml: Pytest config - README.md: Documentation
181 lines
6.8 KiB
Python
181 lines
6.8 KiB
Python
"""P14.1 — Comments API tests.
|
|
|
|
Covers:
|
|
- List comments for task
|
|
- Create comment
|
|
- Update comment
|
|
- Delete comment
|
|
- Comment permissions
|
|
"""
|
|
import pytest
|
|
|
|
|
|
class TestComments:
|
|
"""Comment management endpoints."""
|
|
|
|
def test_list_comments(self, client, db, make_user, make_project, auth_header, seed_roles_and_permissions, make_member):
|
|
"""List comments for a task."""
|
|
admin_role, mgr_role, dev_role = seed_roles_and_permissions
|
|
user = make_user()
|
|
project = make_project()
|
|
make_member(project.id, user.id, dev_role.id)
|
|
|
|
from app.models.milestone import Milestone, MilestoneStatus
|
|
from app.models.task import Task, TaskStatus, TaskPriority
|
|
from app.models.models import Comment
|
|
|
|
milestone = Milestone(title="M1", project_id=project.id, status=MilestoneStatus.OPEN)
|
|
db.add(milestone)
|
|
db.commit()
|
|
|
|
task = Task(
|
|
title="Test Task", project_id=project.id, milestone_id=milestone.id,
|
|
reporter_id=user.id, status=TaskStatus.OPEN, priority=TaskPriority.MEDIUM
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
|
|
# Add comments
|
|
comment1 = Comment(content="Comment 1", task_id=task.id, author_id=user.id)
|
|
comment2 = Comment(content="Comment 2", task_id=task.id, author_id=user.id)
|
|
db.add_all([comment1, comment2])
|
|
db.commit()
|
|
|
|
resp = client.get(f"/projects/{project.id}/tasks/{task.id}/comments", headers=auth_header(user))
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert len(data) == 2
|
|
|
|
def test_create_comment(self, client, db, make_user, make_project, auth_header, seed_roles_and_permissions, make_member):
|
|
"""Create comment on task."""
|
|
admin_role, mgr_role, dev_role = seed_roles_and_permissions
|
|
user = make_user()
|
|
project = make_project()
|
|
make_member(project.id, user.id, dev_role.id)
|
|
|
|
from app.models.milestone import Milestone, MilestoneStatus
|
|
from app.models.task import Task, TaskStatus, TaskPriority
|
|
|
|
milestone = Milestone(title="M1", project_id=project.id, status=MilestoneStatus.OPEN)
|
|
db.add(milestone)
|
|
db.commit()
|
|
|
|
task = Task(
|
|
title="Test Task", project_id=project.id, milestone_id=milestone.id,
|
|
reporter_id=user.id, status=TaskStatus.OPEN, priority=TaskPriority.MEDIUM
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
|
|
resp = client.post(
|
|
f"/projects/{project.id}/tasks/{task.id}/comments",
|
|
json={"content": "This is a test comment"},
|
|
headers=auth_header(user)
|
|
)
|
|
assert resp.status_code == 201
|
|
data = resp.json()
|
|
assert data["content"] == "This is a test comment"
|
|
assert data["author_id"] == user.id
|
|
|
|
def test_update_comment(self, client, db, make_user, make_project, auth_header, seed_roles_and_permissions, make_member):
|
|
"""Update own comment."""
|
|
admin_role, mgr_role, dev_role = seed_roles_and_permissions
|
|
user = make_user()
|
|
project = make_project()
|
|
make_member(project.id, user.id, dev_role.id)
|
|
|
|
from app.models.milestone import Milestone, MilestoneStatus
|
|
from app.models.task import Task, TaskStatus, TaskPriority
|
|
from app.models.models import Comment
|
|
|
|
milestone = Milestone(title="M1", project_id=project.id, status=MilestoneStatus.OPEN)
|
|
db.add(milestone)
|
|
db.commit()
|
|
|
|
task = Task(
|
|
title="Test Task", project_id=project.id, milestone_id=milestone.id,
|
|
reporter_id=user.id, status=TaskStatus.OPEN, priority=TaskPriority.MEDIUM
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
|
|
comment = Comment(content="Original", task_id=task.id, author_id=user.id)
|
|
db.add(comment)
|
|
db.commit()
|
|
|
|
resp = client.patch(
|
|
f"/projects/{project.id}/tasks/{task.id}/comments/{comment.id}",
|
|
json={"content": "Updated content"},
|
|
headers=auth_header(user)
|
|
)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert data["content"] == "Updated content"
|
|
|
|
def test_delete_comment(self, client, db, make_user, make_project, auth_header, seed_roles_and_permissions, make_member):
|
|
"""Delete comment."""
|
|
admin_role, mgr_role, dev_role = seed_roles_and_permissions
|
|
user = make_user()
|
|
project = make_project()
|
|
make_member(project.id, user.id, dev_role.id)
|
|
|
|
from app.models.milestone import Milestone, MilestoneStatus
|
|
from app.models.task import Task, TaskStatus, TaskPriority
|
|
from app.models.models import Comment
|
|
|
|
milestone = Milestone(title="M1", project_id=project.id, status=MilestoneStatus.OPEN)
|
|
db.add(milestone)
|
|
db.commit()
|
|
|
|
task = Task(
|
|
title="Test Task", project_id=project.id, milestone_id=milestone.id,
|
|
reporter_id=user.id, status=TaskStatus.OPEN, priority=TaskPriority.MEDIUM
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
|
|
comment = Comment(content="To delete", task_id=task.id, author_id=user.id)
|
|
db.add(comment)
|
|
db.commit()
|
|
|
|
resp = client.delete(
|
|
f"/projects/{project.id}/tasks/{task.id}/comments/{comment.id}",
|
|
headers=auth_header(user)
|
|
)
|
|
assert resp.status_code == 204
|
|
|
|
def test_cannot_edit_others_comment(self, client, db, make_user, make_project, auth_header, seed_roles_and_permissions, make_member):
|
|
"""Cannot edit another user's comment."""
|
|
admin_role, mgr_role, dev_role = seed_roles_and_permissions
|
|
user1 = make_user(username="user1")
|
|
user2 = make_user(username="user2")
|
|
project = make_project()
|
|
make_member(project.id, user1.id, dev_role.id)
|
|
make_member(project.id, user2.id, dev_role.id)
|
|
|
|
from app.models.milestone import Milestone, MilestoneStatus
|
|
from app.models.task import Task, TaskStatus, TaskPriority
|
|
from app.models.models import Comment
|
|
|
|
milestone = Milestone(title="M1", project_id=project.id, status=MilestoneStatus.OPEN)
|
|
db.add(milestone)
|
|
db.commit()
|
|
|
|
task = Task(
|
|
title="Test Task", project_id=project.id, milestone_id=milestone.id,
|
|
reporter_id=user1.id, status=TaskStatus.OPEN, priority=TaskPriority.MEDIUM
|
|
)
|
|
db.add(task)
|
|
db.commit()
|
|
|
|
comment = Comment(content="User1's comment", task_id=task.id, author_id=user1.id)
|
|
db.add(comment)
|
|
db.commit()
|
|
|
|
resp = client.patch(
|
|
f"/projects/{project.id}/tasks/{task.id}/comments/{comment.id}",
|
|
json={"content": "Hacked!"},
|
|
headers=auth_header(user2)
|
|
)
|
|
assert resp.status_code == 403
|