test_run_filament_helper.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. """Unit tests for the per-run filament helper (#1378, #1390).
  2. The helper computes what value to write into PrintLogEntry.filament_used_grams
  3. for a given print event — partial-aware so failed / cancelled / stopped prints
  4. don't inflate stats with the full slicer estimate, and tracker-aware so
  5. completed prints agree with the per-spool counter on the Inventory page.
  6. """
  7. from backend.app.main import _compute_run_filament_grams
  8. class TestComputeRunFilamentGrams:
  9. def test_completed_no_tracker_returns_archive_estimate(self):
  10. # Completed print without inventory tracking: the slicer estimate is
  11. # the canonical "this print used X" value.
  12. assert _compute_run_filament_grams("completed", 100.0, 100, []) == 100.0
  13. def test_completed_prefers_tracked_over_estimate(self):
  14. # #1390: when inventory tracked the AMS weight delta, Stats should
  15. # reflect that — same source that drives "Total Consumed" on the
  16. # Inventory page. Two halves of the app must show the same number.
  17. assert _compute_run_filament_grams("completed", 100.0, 100, [{"weight_used": 96.5}]) == 96.5
  18. def test_failed_uses_tracked_spool_delta(self):
  19. # Failed reprint at 10g actual: inventory tracked the spool delta.
  20. # The estimate was 100g; we want 10g recorded for stats.
  21. assert _compute_run_filament_grams("failed", 100.0, 10, [{"weight_used": 10.0}]) == 10.0
  22. def test_cancelled_uses_tracked_spool_delta(self):
  23. # Same logic for cancelled.
  24. assert _compute_run_filament_grams("cancelled", 100.0, 12, [{"weight_used": 8.5}]) == 8.5
  25. def test_stopped_uses_tracked_spool_delta(self):
  26. assert _compute_run_filament_grams("stopped", 100.0, 15, [{"weight_used": 12.0}]) == 12.0
  27. def test_failed_with_no_tracked_falls_back_to_progress_scale(self):
  28. # No inventory tracking: scale estimate by progress% (10% of 100g = 10g).
  29. assert _compute_run_filament_grams("failed", 100.0, 10, []) == 10.0
  30. def test_failed_with_no_tracked_and_no_progress_returns_none(self):
  31. # Nothing to infer from — return None rather than guess the estimate.
  32. assert _compute_run_filament_grams("failed", 100.0, 0, []) is None
  33. def test_failed_with_partial_progress_rounds_correctly(self):
  34. # 100g × 33% = 33.0g (rounded to 1 decimal)
  35. assert _compute_run_filament_grams("failed", 100.0, 33, []) == 33.0
  36. def test_failed_with_no_estimate_returns_none(self):
  37. # No estimate, no tracked usage → can't compute anything.
  38. assert _compute_run_filament_grams("failed", None, 50, []) is None
  39. def test_failed_with_no_estimate_but_tracked_uses_tracked(self):
  40. # Tracked spool delta is authoritative even without an estimate.
  41. assert _compute_run_filament_grams("failed", None, 50, [{"weight_used": 5.0}]) == 5.0
  42. def test_tracked_overrides_progress_scale_when_both_available(self):
  43. # If inventory says 8g but progress says 15g, trust inventory (it's measured).
  44. assert _compute_run_filament_grams("failed", 100.0, 15, [{"weight_used": 8.0}]) == 8.0
  45. def test_progress_above_100_clamps_to_full_estimate(self):
  46. # Defensive: progress overshoot doesn't multiply past the estimate.
  47. assert _compute_run_filament_grams("failed", 100.0, 150, []) == 100.0
  48. def test_multiple_tracked_slots_summed(self):
  49. # Multi-filament print, two slots tracked.
  50. usage = [{"weight_used": 5.0}, {"weight_used": 3.5}, {"weight_used": 1.0}]
  51. assert _compute_run_filament_grams("failed", 100.0, 20, usage) == 9.5
  52. def test_completed_with_none_estimate_returns_none(self):
  53. # Archive somehow has no estimate (rare; archive_print parsed nothing).
  54. assert _compute_run_filament_grams("completed", None, 100, []) is None