test_print_log.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. """Unit tests for print log service and schema."""
  2. from datetime import datetime, timedelta
  3. import pytest
  4. from backend.app.schemas.print_log import PrintLogEntrySchema, PrintLogResponse
  5. class TestPrintLogEntrySchema:
  6. """Test PrintLogEntrySchema validation."""
  7. def test_minimal_entry(self):
  8. """Schema accepts minimal required fields."""
  9. entry = PrintLogEntrySchema(
  10. id=1,
  11. status="completed",
  12. created_at=datetime(2024, 1, 15, 10, 30, 0),
  13. )
  14. assert entry.id == 1
  15. assert entry.status == "completed"
  16. assert entry.print_name is None
  17. assert entry.printer_name is None
  18. assert entry.duration_seconds is None
  19. def test_full_entry(self):
  20. """Schema accepts all fields."""
  21. started = datetime(2024, 1, 15, 10, 0, 0)
  22. completed = datetime(2024, 1, 15, 12, 30, 0)
  23. entry = PrintLogEntrySchema(
  24. id=42,
  25. print_name="Benchy",
  26. printer_name="X1C-01",
  27. printer_id=3,
  28. status="completed",
  29. started_at=started,
  30. completed_at=completed,
  31. duration_seconds=9000,
  32. filament_type="PLA",
  33. filament_color="#FF5500",
  34. filament_used_grams=15.2,
  35. thumbnail_path="archives/3/20240115_benchy/thumbnail.png",
  36. created_by_username="admin",
  37. created_at=datetime(2024, 1, 15, 12, 30, 0),
  38. )
  39. assert entry.print_name == "Benchy"
  40. assert entry.printer_name == "X1C-01"
  41. assert entry.filament_used_grams == 15.2
  42. assert entry.created_by_username == "admin"
  43. def test_failed_status(self):
  44. """Schema accepts various status values."""
  45. for status in ("completed", "failed", "stopped", "cancelled", "skipped"):
  46. entry = PrintLogEntrySchema(id=1, status=status, created_at=datetime.now())
  47. assert entry.status == status
  48. class TestPrintLogResponse:
  49. """Test PrintLogResponse pagination wrapper."""
  50. def test_empty_response(self):
  51. """Empty response with zero total."""
  52. resp = PrintLogResponse(items=[], total=0)
  53. assert len(resp.items) == 0
  54. assert resp.total == 0
  55. def test_paginated_response(self):
  56. """Response with items and total count > items count."""
  57. items = [PrintLogEntrySchema(id=i, status="completed", created_at=datetime.now()) for i in range(3)]
  58. resp = PrintLogResponse(items=items, total=100)
  59. assert len(resp.items) == 3
  60. assert resp.total == 100
  61. class TestWriteLogEntry:
  62. """Test the write_log_entry service function (logic only, no DB)."""
  63. def test_duration_calculation(self):
  64. """Duration is computed from started_at and completed_at."""
  65. started = datetime(2024, 1, 15, 10, 0, 0)
  66. completed = started + timedelta(hours=2, minutes=30)
  67. # Simulating the duration calculation from write_log_entry
  68. duration = int((completed - started).total_seconds())
  69. assert duration == 9000 # 2.5 hours = 9000 seconds
  70. def test_duration_none_when_missing_times(self):
  71. """Duration is None when started_at or completed_at is missing."""
  72. started = datetime(2024, 1, 15, 10, 0, 0)
  73. completed_at = None
  74. started_at = None
  75. completed = datetime.now()
  76. # No completed_at
  77. duration = None
  78. if started and completed_at:
  79. duration = int((completed_at - started).total_seconds())
  80. assert duration is None
  81. # No started_at
  82. duration = None
  83. if started_at and completed:
  84. duration = int((completed - started_at).total_seconds())
  85. assert duration is None