import pytest
from unittest.mock import MagicMock, patch
from uuid import uuid4
from datetime import datetime
from sqlalchemy.orm import Session
from preloop.models.crud.issue import CRUDIssue
from preloop.models.models.issue import Issue
@pytest.fixture
def mock_db_session():
"""Fixture for a mock database session."""
session = MagicMock(spec=Session)
return session
@pytest.fixture
def crud_issue():
"""Fixture for a CRUDIssue instance."""
return CRUDIssue(Issue)
def test_create_with_external(crud_issue, mock_db_session):
"""Test creating an issue with external sync."""
# Arrange
issue_in = {"title": "Test Issue", "project_id": str(uuid4())}
mock_issue = Issue(**issue_in)
with patch.object(crud_issue, "create", return_value=mock_issue) as mock_create:
# Act
result = crud_issue.create_with_external(mock_db_session, obj_in=issue_in)
# Assert
mock_create.assert_called_once_with(mock_db_session, obj_in=issue_in)
assert result.title == issue_in["title"]
def test_get_by_title(crud_issue, mock_db_session):
"""Test retrieving an issue by title."""
# Arrange
title = "Test Issue"
project_id = str(uuid4())
mock_issue = Issue(id=str(uuid4()), title=title)
mock_query = MagicMock()
mock_db_session.query.return_value = mock_query
mock_query.filter.return_value = mock_query
mock_query.first.return_value = mock_issue
# Act
result = crud_issue.get_by_title(
mock_db_session, title=title, project_id=project_id
)
# Assert
assert result.title == title
def test_get_by_key(crud_issue, mock_db_session):
"""Test retrieving an issue by key."""
# Arrange
issue_key = "TEST-123"
project_id = str(uuid4())
account_id = str(uuid4())
mock_issue = Issue(id=str(uuid4()), key=issue_key)
mock_query = MagicMock()
mock_db_session.query.return_value = mock_query
mock_query.filter.return_value = mock_query
mock_query.join.return_value = mock_query
mock_query.first.return_value = mock_issue
# Act
result = crud_issue.get_by_key(
mock_db_session, key=issue_key, project_id=project_id, account_id=account_id
)
# Assert
assert result == mock_issue
assert result.key == issue_key
mock_db_session.query.assert_called_once_with(Issue)
def test_get_by_external_id(crud_issue, mock_db_session):
"""Test retrieving an issue by external ID."""
# Arrange
external_id = "JIRA-456"
project_id = str(uuid4())
account_id = str(uuid4())
mock_issue = Issue(id=str(uuid4()), external_id=external_id)
mock_query = MagicMock()
mock_db_session.query.return_value = mock_query
mock_query.filter.return_value = mock_query
mock_query.join.return_value = mock_query
mock_query.first.return_value = mock_issue
# Act
result = crud_issue.get_by_external_id(
mock_db_session,
project_id=project_id,
external_id=external_id,
account_id=account_id,
)
# Assert
assert result == mock_issue
assert result.external_id == external_id
mock_db_session.query.assert_called_once_with(Issue)
def test_get_for_project(crud_issue, mock_db_session):
"""Test retrieving issues for a project."""
# Arrange
project_id = str(uuid4())
mock_issues = [Issue(id=str(uuid4())) for _ in range(3)]
mock_query = MagicMock()
mock_db_session.query.return_value = mock_query
mock_query.filter.return_value = mock_query
mock_query.order_by.return_value = mock_query
mock_query.offset.return_value = mock_query
mock_query.limit.return_value = mock_query
mock_query.all.return_value = mock_issues
# Act
result = crud_issue.get_for_project(mock_db_session, project_id=project_id)
# Assert
assert len(result) == 3
def test_get_issue_counts_per_project(crud_issue, mock_db_session):
"""Test getting issue counts per project."""
# Arrange
project_id = str(uuid4())
mock_db_session.query.return_value.filter.return_value.group_by.return_value.all.return_value = [
(project_id, 10)
]
# Act
result = crud_issue.get_issue_counts_per_project(
mock_db_session, project_ids=[project_id]
)
# Assert
assert result[project_id]["total"] == 10
def test_get_issue_count(crud_issue, mock_db_session):
"""Test getting the total number of issues for an account."""
# Arrange
account_id = str(uuid4())
mock_query = MagicMock()
mock_db_session.query.return_value = mock_query
mock_query.join.return_value = mock_query
mock_query.filter.return_value = mock_query
mock_query.scalar.return_value = 5
# Act
result = crud_issue.get_issue_count(mock_db_session, account_id=account_id)
# Assert
assert result == 5
def test_update_status(crud_issue, mock_db_session):
"""Test updating an issue's status."""
# Arrange
issue_id = str(uuid4())
new_status = "In Progress"
mock_issue = Issue(id=issue_id, status="Open")
crud_issue.get = MagicMock(return_value=mock_issue)
# Act
result = crud_issue.update_status(mock_db_session, id=issue_id, status=new_status)
# Assert
assert result.status == new_status
mock_db_session.add.assert_called_once_with(mock_issue)
mock_db_session.commit.assert_called_once()
mock_db_session.refresh.assert_called_once_with(mock_issue)
def test_update_last_synced(crud_issue, mock_db_session):
"""Test updating an issue's last_synced timestamp."""
# Arrange
issue_id = str(uuid4())
mock_issue = Issue(id=issue_id, last_synced=None)
crud_issue.get = MagicMock(return_value=mock_issue)
# Act
result = crud_issue.update_last_synced(mock_db_session, id=issue_id)
# Assert
assert result.last_synced is not None
assert isinstance(result.last_synced, datetime)
mock_db_session.add.assert_called_once_with(mock_issue)
mock_db_session.commit.assert_called_once()
mock_db_session.refresh.assert_called_once_with(mock_issue)