| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- """Statistics keeps naming a printer that was deleted with its history (#2873).
- Deleting a printer while keeping its prints leaves the log rows pointing at an
- id nothing resolves any more, so every per-printer breakdown fell back to
- "Printer 1" for machines the reporter knew as "Ultron". Each run recorded the
- name it printed on, so that is what the aggregates report now.
- """
- from __future__ import annotations
- from datetime import datetime, timedelta
- import pytest
- from httpx import AsyncClient
- from backend.app.models.print_log import PrintLogEntry
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_stats_name_history_of_a_deleted_printer(async_client: AsyncClient, db_session):
- base = datetime(2026, 7, 15, 10, 0, 0)
- db_session.add_all(
- [
- PrintLogEntry(
- printer_id=71,
- printer_name="Ultron",
- status="completed",
- started_at=base,
- completed_at=base + timedelta(hours=1),
- duration_seconds=3600,
- ),
- PrintLogEntry(
- printer_id=71,
- printer_name="Ultron",
- status="failed",
- started_at=base + timedelta(hours=2),
- completed_at=base + timedelta(hours=3),
- duration_seconds=3600,
- ),
- ]
- )
- await db_session.commit()
- stats = (await async_client.get("/api/v1/archives/stats")).json()
- assert stats["prints_by_printer"]["71"] == 2
- assert stats["printer_names"]["71"] == "Ultron"
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_stats_reports_the_last_name_the_printer_ran_under(async_client: AsyncClient, db_session):
- """A printer renamed before it was deleted is remembered by its last name."""
- base = datetime(2026, 7, 15, 10, 0, 0)
- db_session.add_all(
- [
- PrintLogEntry(printer_id=71, printer_name="Ultron", status="completed", started_at=base),
- PrintLogEntry(
- printer_id=71,
- printer_name="Ultron Mk II",
- status="completed",
- started_at=base + timedelta(days=1),
- ),
- # A run logged before names were recorded must not blank the label.
- PrintLogEntry(printer_id=71, printer_name=None, status="completed", started_at=base + timedelta(days=2)),
- ]
- )
- await db_session.commit()
- stats = (await async_client.get("/api/v1/archives/stats")).json()
- assert stats["printer_names"]["71"] == "Ultron Mk II"
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_stats_names_do_not_override_a_live_printer(async_client: AsyncClient, db_session, printer_factory):
- """Renaming a printer that still exists shows up straight away.
- The client prefers the live record, so the historical name only has to be
- present, not authoritative.
- """
- printer = await printer_factory(name="Renamed Later")
- db_session.add(PrintLogEntry(printer_id=printer.id, printer_name="Original Name", status="completed"))
- await db_session.commit()
- stats = (await async_client.get("/api/v1/archives/stats")).json()
- printers = (await async_client.get("/api/v1/printers/")).json()
- assert stats["printer_names"][str(printer.id)] == "Original Name"
- assert [p["name"] for p in printers if p["id"] == printer.id] == ["Renamed Later"]
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_failure_analysis_names_a_deleted_printer(async_client: AsyncClient, db_session, printer_factory):
- """Failures by printer reads the recorded name once the printer is gone."""
- live = await printer_factory(name="Still Here")
- db_session.add_all(
- [
- PrintLogEntry(printer_id=71, printer_name="Ultron", status="failed"),
- PrintLogEntry(printer_id=live.id, printer_name="Older Name", status="failed"),
- ]
- )
- await db_session.commit()
- analysis = (await async_client.get("/api/v1/archives/analysis/failures")).json()
- assert analysis["failures_by_printer"]["Ultron"] == 1
- assert analysis["failures_by_printer"]["Still Here"] == 1
- assert "Printer 71" not in analysis["failures_by_printer"]
|