Files
noteflow/tests/cli/test_retention.py
Travis Vasceannie d8090a98e8
Some checks failed
CI / test-typescript (push) Has been cancelled
CI / test-rust (push) Has been cancelled
CI / test-python (push) Has been cancelled
ci/cd fixes
2026-01-26 00:28:15 +00:00

189 lines
8.6 KiB
Python

"""Tests for CLI retention command."""
from __future__ import annotations
from datetime import UTC, datetime
from unittest.mock import AsyncMock, MagicMock
import pytest
from noteflow.cli.retention import main, run_cleanup, show_status
class TestRunCleanup:
@pytest.mark.asyncio
async def test_run_cleanup_disabled_without_dry_run_returns_1(
self,
mock_retention_settings_disabled: MagicMock,
mock_retention_uow_factory: MagicMock,
) -> None:
assert mock_retention_settings_disabled is not None, (
"Retention settings fixture should be provided"
)
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
result = await run_cleanup(dry_run=False)
assert result == 1, "Should return 1 when retention disabled and not dry-run"
@pytest.mark.asyncio
async def test_run_cleanup_dry_run_proceeds_when_disabled(
self,
mock_retention_settings_disabled: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert mock_retention_settings_disabled is not None, (
"Retention settings fixture should be provided"
)
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.run_cleanup = AsyncMock(
return_value=MagicMock(meetings_checked=5, meetings_deleted=0, errors=[])
)
result = await run_cleanup(dry_run=True)
assert result == 0, "Dry-run should succeed even when retention disabled"
@pytest.mark.asyncio
async def test_run_cleanup_success_returns_0(
self,
mock_retention_settings: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert mock_retention_settings is not None, "Retention settings fixture should be provided"
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.run_cleanup = AsyncMock(
return_value=MagicMock(meetings_checked=10, meetings_deleted=3, errors=[])
)
result = await run_cleanup(dry_run=False)
assert result == 0, "Should return 0 on successful cleanup"
@pytest.mark.asyncio
async def test_run_cleanup_with_errors_returns_1(
self,
mock_retention_settings: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert mock_retention_settings is not None, "Retention settings fixture should be provided"
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.run_cleanup = AsyncMock(
return_value=MagicMock(
meetings_checked=10, meetings_deleted=2, errors=["Error 1", "Error 2"]
)
)
result = await run_cleanup(dry_run=False)
assert result == 1, "Should return 1 when errors occurred"
class TestShowStatus:
@pytest.mark.asyncio
async def test_show_status_returns_0(
self,
mock_retention_settings: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert mock_retention_settings is not None, "Retention settings fixture should be provided"
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.find_expired_meetings = AsyncMock(return_value=[])
result = await show_status()
assert result == 0, "Status should always return 0"
@pytest.mark.asyncio
async def test_show_status_with_expired_meetings(
self,
mock_retention_settings: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert mock_retention_settings is not None, "Retention settings fixture should be provided"
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
meeting = MagicMock()
meeting.id = "test-id"
meeting.title = "Test Meeting"
meeting.ended_at = datetime(2024, 1, 1, tzinfo=UTC)
mock_retention_service.find_expired_meetings = AsyncMock(return_value=[meeting])
result = await show_status()
assert result == 0, "Status should return 0 even with pending deletions"
class TestMain:
def test_main_no_command_exits_with_1(self, argv_retention_no_command: None) -> None:
assert argv_retention_no_command is None, (
"argv_retention_no_command fixture should provide None"
)
with pytest.raises(SystemExit, match="1") as exc_info:
main()
assert exc_info.value.code == 1, "Should exit with 1 when no command"
def test_main_cleanup_command_calls_run_cleanup(
self,
argv_retention_cleanup: None,
mock_retention_settings: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert argv_retention_cleanup is None, "argv_retention_cleanup fixture should provide None"
assert mock_retention_settings is not None, "Retention settings fixture should be provided"
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.run_cleanup = AsyncMock(
return_value=MagicMock(meetings_checked=0, meetings_deleted=0, errors=[])
)
with pytest.raises(SystemExit, match="0") as exc_info:
main()
assert exc_info.value.code == 0, "Cleanup should exit with 0 on success"
def test_main_cleanup_dry_run_passes_flag(
self,
argv_retention_cleanup_dry_run: None,
mock_retention_settings_disabled: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert argv_retention_cleanup_dry_run is None, (
"argv_retention_cleanup_dry_run fixture should provide None"
)
assert mock_retention_settings_disabled is not None, (
"Retention settings fixture should be provided"
)
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.run_cleanup = AsyncMock(
return_value=MagicMock(meetings_checked=0, meetings_deleted=0, errors=[])
)
with pytest.raises(SystemExit, match="0") as exc_info:
main()
assert exc_info.value.code == 0, "Dry-run should succeed"
mock_retention_service.run_cleanup.assert_called_once_with(dry_run=True)
def test_main_status_command_calls_show_status(
self,
argv_retention_status_cmd: None,
mock_retention_settings: MagicMock,
mock_retention_uow_factory: MagicMock,
mock_retention_service: MagicMock,
mock_retention_console: MagicMock,
) -> None:
assert argv_retention_status_cmd is None, (
"argv_retention_status_cmd fixture should provide None"
)
assert mock_retention_settings is not None, "Retention settings fixture should be provided"
assert mock_retention_uow_factory is not None, "Retention UOW fixture should be provided"
assert mock_retention_console is not None, "Retention console fixture should be provided"
mock_retention_service.find_expired_meetings = AsyncMock(return_value=[])
with pytest.raises(SystemExit, match="0") as exc_info:
main()
assert exc_info.value.code == 0, "Status should exit with 0"