test_deleted_printer_keeps_name_2873.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """Statistics keeps naming a printer that was deleted with its history (#2873).
  2. Deleting a printer while keeping its prints leaves the log rows pointing at an
  3. id nothing resolves any more, so every per-printer breakdown fell back to
  4. "Printer 1" for machines the reporter knew as "Ultron". Each run recorded the
  5. name it printed on, so that is what the aggregates report now.
  6. """
  7. from __future__ import annotations
  8. from datetime import datetime, timedelta
  9. import pytest
  10. from httpx import AsyncClient
  11. from backend.app.models.print_log import PrintLogEntry
  12. @pytest.mark.asyncio
  13. @pytest.mark.integration
  14. async def test_stats_name_history_of_a_deleted_printer(async_client: AsyncClient, db_session):
  15. base = datetime(2026, 7, 15, 10, 0, 0)
  16. db_session.add_all(
  17. [
  18. PrintLogEntry(
  19. printer_id=71,
  20. printer_name="Ultron",
  21. status="completed",
  22. started_at=base,
  23. completed_at=base + timedelta(hours=1),
  24. duration_seconds=3600,
  25. ),
  26. PrintLogEntry(
  27. printer_id=71,
  28. printer_name="Ultron",
  29. status="failed",
  30. started_at=base + timedelta(hours=2),
  31. completed_at=base + timedelta(hours=3),
  32. duration_seconds=3600,
  33. ),
  34. ]
  35. )
  36. await db_session.commit()
  37. stats = (await async_client.get("/api/v1/archives/stats")).json()
  38. assert stats["prints_by_printer"]["71"] == 2
  39. assert stats["printer_names"]["71"] == "Ultron"
  40. @pytest.mark.asyncio
  41. @pytest.mark.integration
  42. async def test_stats_reports_the_last_name_the_printer_ran_under(async_client: AsyncClient, db_session):
  43. """A printer renamed before it was deleted is remembered by its last name."""
  44. base = datetime(2026, 7, 15, 10, 0, 0)
  45. db_session.add_all(
  46. [
  47. PrintLogEntry(printer_id=71, printer_name="Ultron", status="completed", started_at=base),
  48. PrintLogEntry(
  49. printer_id=71,
  50. printer_name="Ultron Mk II",
  51. status="completed",
  52. started_at=base + timedelta(days=1),
  53. ),
  54. # A run logged before names were recorded must not blank the label.
  55. PrintLogEntry(printer_id=71, printer_name=None, status="completed", started_at=base + timedelta(days=2)),
  56. ]
  57. )
  58. await db_session.commit()
  59. stats = (await async_client.get("/api/v1/archives/stats")).json()
  60. assert stats["printer_names"]["71"] == "Ultron Mk II"
  61. @pytest.mark.asyncio
  62. @pytest.mark.integration
  63. async def test_stats_names_do_not_override_a_live_printer(async_client: AsyncClient, db_session, printer_factory):
  64. """Renaming a printer that still exists shows up straight away.
  65. The client prefers the live record, so the historical name only has to be
  66. present, not authoritative.
  67. """
  68. printer = await printer_factory(name="Renamed Later")
  69. db_session.add(PrintLogEntry(printer_id=printer.id, printer_name="Original Name", status="completed"))
  70. await db_session.commit()
  71. stats = (await async_client.get("/api/v1/archives/stats")).json()
  72. printers = (await async_client.get("/api/v1/printers/")).json()
  73. assert stats["printer_names"][str(printer.id)] == "Original Name"
  74. assert [p["name"] for p in printers if p["id"] == printer.id] == ["Renamed Later"]
  75. @pytest.mark.asyncio
  76. @pytest.mark.integration
  77. async def test_failure_analysis_names_a_deleted_printer(async_client: AsyncClient, db_session, printer_factory):
  78. """Failures by printer reads the recorded name once the printer is gone."""
  79. live = await printer_factory(name="Still Here")
  80. db_session.add_all(
  81. [
  82. PrintLogEntry(printer_id=71, printer_name="Ultron", status="failed"),
  83. PrintLogEntry(printer_id=live.id, printer_name="Older Name", status="failed"),
  84. ]
  85. )
  86. await db_session.commit()
  87. analysis = (await async_client.get("/api/v1/archives/analysis/failures")).json()
  88. assert analysis["failures_by_printer"]["Ultron"] == 1
  89. assert analysis["failures_by_printer"]["Still Here"] == 1
  90. assert "Printer 71" not in analysis["failures_by_printer"]