from types import SimpleNamespace from unittest.mock import AsyncMock import pytest from backend.app.services import print_cost_estimate @pytest.fixture def library_file(tmp_path): path = tmp_path / "queued.gcode.3mf" path.write_bytes(b"stub") return SimpleNamespace(file_path=str(path), file_metadata={}) @pytest.mark.asyncio async def test_archive_without_stored_cost_uses_server_default(monkeypatch): archive = SimpleNamespace( id=7, file_path="missing.gcode.3mf", plate_id=None, filament_used_grams=100.0, cost=None, ) monkeypatch.setattr(print_cost_estimate, "_default_cost_per_kg", AsyncMock(return_value=20.0)) cost = await print_cost_estimate.estimate_queue_source_cost(SimpleNamespace(), archive=archive) assert cost == 2.0 @pytest.mark.asyncio async def test_library_estimate_uses_server_default_cost(monkeypatch, library_file): monkeypatch.setattr( print_cost_estimate.threemf_tools, "extract_plate_metadata_from_3mf", lambda *_args: SimpleNamespace( filament_usage=[ {"slot_id": 1, "used_g": 100.0}, {"slot_id": 2, "used_g": 50.0}, ] ), ) monkeypatch.setattr(print_cost_estimate, "_default_cost_per_kg", AsyncMock(return_value=20.0)) cost = await print_cost_estimate.estimate_queue_source_cost( SimpleNamespace(), library_file=library_file, plate_id=1, ) assert cost == 3.0 @pytest.mark.asyncio async def test_library_estimate_uses_server_spool_assignment_costs(monkeypatch, library_file): monkeypatch.setattr( print_cost_estimate.threemf_tools, "extract_plate_metadata_from_3mf", lambda *_args: SimpleNamespace( filament_usage=[ {"slot_id": 1, "used_g": 100.0}, {"slot_id": 2, "used_g": 50.0}, ] ), ) monkeypatch.setattr(print_cost_estimate, "_default_cost_per_kg", AsyncMock(return_value=20.0)) assignments = [ SimpleNamespace(ams_id=0, tray_id=0, spool=SimpleNamespace(cost_per_kg=10.0)), SimpleNamespace(ams_id=0, tray_id=1, spool=SimpleNamespace(cost_per_kg=30.0)), ] result = SimpleNamespace(scalars=lambda: SimpleNamespace(all=lambda: assignments)) db = SimpleNamespace(execute=AsyncMock(return_value=result)) cost = await print_cost_estimate.estimate_queue_source_cost( db, library_file=library_file, plate_id=1, ams_mapping=[0, 1], printer_id=7, ) assert cost == 2.5 @pytest.mark.asyncio async def test_missing_server_metadata_does_not_fall_back_to_client_hint(monkeypatch, library_file): monkeypatch.setattr( print_cost_estimate.threemf_tools, "extract_plate_metadata_from_3mf", lambda *_args: SimpleNamespace(filament_usage=[]), ) cost = await print_cost_estimate.estimate_queue_source_cost( SimpleNamespace(), library_file=library_file, plate_id=1, ) assert cost is None