Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
367 lines
12 KiB
Python
367 lines
12 KiB
Python
"""
|
|
Tests pour le service Scheduler.
|
|
|
|
Couvre:
|
|
- Validation des expressions cron
|
|
- Création/mise à jour/suppression de schedules
|
|
- Pause/Resume
|
|
- Statistiques
|
|
- Exécution planifiée (mocked)
|
|
"""
|
|
|
|
import pytest
|
|
from datetime import datetime, timezone, timedelta
|
|
from unittest.mock import patch, AsyncMock, MagicMock
|
|
from freezegun import freeze_time
|
|
|
|
pytestmark = pytest.mark.unit
|
|
|
|
|
|
class TestSchedulerCronValidation:
|
|
"""Tests pour la validation des expressions cron."""
|
|
|
|
def test_validate_cron_valid_expression(self):
|
|
"""Expression cron valide retourne valid=True."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
result = service.validate_cron_expression("0 2 * * *")
|
|
|
|
assert result["valid"] is True
|
|
assert result["expression"] == "0 2 * * *"
|
|
assert result["error"] is None
|
|
assert len(result["next_runs"]) == 5
|
|
|
|
def test_validate_cron_invalid_expression(self):
|
|
"""Expression cron invalide retourne valid=False."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
result = service.validate_cron_expression("invalid cron")
|
|
|
|
assert result["valid"] is False
|
|
assert result["error"] is not None
|
|
|
|
def test_validate_cron_edge_cases(self):
|
|
"""Expressions cron valides complexes."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
|
|
# Every hour
|
|
result = service.validate_cron_expression("0 * * * *")
|
|
assert result["valid"] is True
|
|
|
|
# Every Monday at 9am
|
|
result = service.validate_cron_expression("0 9 * * 1")
|
|
assert result["valid"] is True
|
|
|
|
# First of every month
|
|
result = service.validate_cron_expression("0 0 1 * *")
|
|
assert result["valid"] is True
|
|
|
|
|
|
class TestSchedulerServiceCache:
|
|
"""Tests pour la gestion du cache des schedules."""
|
|
|
|
def test_get_all_schedules_empty(self):
|
|
"""Cache vide retourne liste vide."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
schedules = service.get_all_schedules()
|
|
|
|
assert schedules == []
|
|
|
|
def test_get_schedule_not_found(self):
|
|
"""Schedule inexistant retourne None."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
schedule = service.get_schedule("nonexistent")
|
|
|
|
assert schedule is None
|
|
|
|
def test_add_schedule_to_cache(self):
|
|
"""Ajoute un schedule au cache."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
schedule = Schedule(
|
|
id="test-schedule",
|
|
name="Test Schedule",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=False,
|
|
)
|
|
|
|
service.add_schedule_to_cache(schedule)
|
|
|
|
assert service.get_schedule("test-schedule") is not None
|
|
|
|
def test_remove_schedule_from_cache(self):
|
|
"""Supprime un schedule du cache."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
schedule = Schedule(
|
|
id="to-remove",
|
|
name="Remove Me",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=False,
|
|
)
|
|
|
|
service.add_schedule_to_cache(schedule)
|
|
assert service.get_schedule("to-remove") is not None
|
|
|
|
service.remove_schedule_from_cache("to-remove")
|
|
assert service.get_schedule("to-remove") is None
|
|
|
|
|
|
class TestSchedulerServiceFiltering:
|
|
"""Tests pour le filtrage des schedules."""
|
|
|
|
def test_filter_by_enabled(self):
|
|
"""Filtre par état enabled."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
service.add_schedule_to_cache(Schedule(
|
|
id="enabled-1", name="Enabled", playbook="test.yml",
|
|
target="all", schedule_type="once", enabled=True
|
|
))
|
|
service.add_schedule_to_cache(Schedule(
|
|
id="disabled-1", name="Disabled", playbook="test.yml",
|
|
target="all", schedule_type="once", enabled=False
|
|
))
|
|
|
|
enabled = service.get_all_schedules(enabled=True)
|
|
disabled = service.get_all_schedules(enabled=False)
|
|
|
|
assert len(enabled) == 1
|
|
assert enabled[0].id == "enabled-1"
|
|
assert len(disabled) == 1
|
|
assert disabled[0].id == "disabled-1"
|
|
|
|
def test_filter_by_playbook(self):
|
|
"""Filtre par nom de playbook."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
service.add_schedule_to_cache(Schedule(
|
|
id="backup-1", name="Backup", playbook="backup.yml",
|
|
target="all", schedule_type="once", enabled=True
|
|
))
|
|
service.add_schedule_to_cache(Schedule(
|
|
id="health-1", name="Health", playbook="health-check.yml",
|
|
target="all", schedule_type="once", enabled=True
|
|
))
|
|
|
|
backup_schedules = service.get_all_schedules(playbook="backup")
|
|
|
|
assert len(backup_schedules) == 1
|
|
assert backup_schedules[0].id == "backup-1"
|
|
|
|
|
|
class TestSchedulerServicePauseResume:
|
|
"""Tests pour pause/resume des schedules."""
|
|
|
|
def test_pause_schedule(self):
|
|
"""Pause un schedule."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
schedule = Schedule(
|
|
id="pausable",
|
|
name="Pausable",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=True
|
|
)
|
|
service.add_schedule_to_cache(schedule)
|
|
|
|
result = service.pause_schedule("pausable")
|
|
|
|
assert result is True
|
|
assert service.get_schedule("pausable").enabled is False
|
|
|
|
def test_pause_nonexistent_schedule(self):
|
|
"""Pause d'un schedule inexistant retourne False."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
result = service.pause_schedule("nonexistent")
|
|
|
|
assert result is False
|
|
|
|
def test_resume_schedule(self):
|
|
"""Resume un schedule en pause."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
schedule = Schedule(
|
|
id="resumable",
|
|
name="Resumable",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=False
|
|
)
|
|
service.add_schedule_to_cache(schedule)
|
|
|
|
result = service.resume_schedule("resumable")
|
|
|
|
assert result is True
|
|
assert service.get_schedule("resumable").enabled is True
|
|
|
|
|
|
class TestSchedulerServiceStats:
|
|
"""Tests pour les statistiques des schedules."""
|
|
|
|
def test_get_stats_empty(self):
|
|
"""Stats avec cache vide."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
|
|
service = SchedulerService()
|
|
stats = service.get_stats()
|
|
|
|
assert stats.total == 0
|
|
assert stats.active == 0
|
|
assert stats.paused == 0
|
|
|
|
def test_get_stats_with_schedules(self):
|
|
"""Stats avec des schedules."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
# Add mix of enabled/disabled
|
|
for i in range(3):
|
|
service.add_schedule_to_cache(Schedule(
|
|
id=f"active-{i}",
|
|
name=f"Active {i}",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=True
|
|
))
|
|
|
|
for i in range(2):
|
|
service.add_schedule_to_cache(Schedule(
|
|
id=f"paused-{i}",
|
|
name=f"Paused {i}",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=False
|
|
))
|
|
|
|
stats = service.get_stats()
|
|
|
|
assert stats.total == 5
|
|
assert stats.active == 3
|
|
assert stats.paused == 2
|
|
|
|
@freeze_time("2024-01-15 10:00:00")
|
|
def test_get_upcoming_executions(self):
|
|
"""Récupère les prochaines exécutions."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
future_time = datetime.now(timezone.utc) + timedelta(hours=2)
|
|
|
|
service.add_schedule_to_cache(Schedule(
|
|
id="upcoming-1",
|
|
name="Upcoming",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=True,
|
|
next_run_at=future_time
|
|
))
|
|
|
|
upcoming = service.get_upcoming_executions(limit=5)
|
|
|
|
assert len(upcoming) == 1
|
|
assert upcoming[0]["schedule_id"] == "upcoming-1"
|
|
|
|
|
|
class TestSchedulerServiceUpdate:
|
|
"""Tests pour la mise à jour des schedules."""
|
|
|
|
def test_update_schedule_name(self):
|
|
"""Met à jour le nom d'un schedule."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule, ScheduleUpdateRequest
|
|
|
|
service = SchedulerService()
|
|
|
|
schedule = Schedule(
|
|
id="update-me",
|
|
name="Old Name",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=True
|
|
)
|
|
service.add_schedule_to_cache(schedule)
|
|
|
|
update = ScheduleUpdateRequest(name="New Name")
|
|
updated = service.update_schedule("update-me", update)
|
|
|
|
assert updated is not None
|
|
assert updated.name == "New Name"
|
|
|
|
def test_update_schedule_not_found(self):
|
|
"""Mise à jour d'un schedule inexistant retourne None."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import ScheduleUpdateRequest
|
|
|
|
service = SchedulerService()
|
|
|
|
update = ScheduleUpdateRequest(name="New Name")
|
|
result = service.update_schedule("nonexistent", update)
|
|
|
|
assert result is None
|
|
|
|
def test_delete_schedule(self):
|
|
"""Supprime un schedule."""
|
|
from app.services.scheduler_service import SchedulerService
|
|
from app.schemas.schedule_api import Schedule
|
|
|
|
service = SchedulerService()
|
|
|
|
schedule = Schedule(
|
|
id="delete-me",
|
|
name="Delete Me",
|
|
playbook="test.yml",
|
|
target="all",
|
|
schedule_type="once",
|
|
enabled=True
|
|
)
|
|
service.add_schedule_to_cache(schedule)
|
|
|
|
result = service.delete_schedule("delete-me")
|
|
|
|
assert result is True
|
|
assert service.get_schedule("delete-me") is None
|