| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- """A Spoolman spool's own slicer preset is used for its slot.
- The spool keeps its preset in Spoolman (extra.bambu_slicer_filament). Configure
- AMS Slot and the K-profile lookup passed no fallback for a Spoolman spool, so
- one without a per-model override opened with no preset and the K-profile
- matched against the tray's own filament id. Read from Spoolman, remembered for
- a minute per spool.
- """
- from unittest.mock import AsyncMock, MagicMock, patch
- import pytest
- from httpx import AsyncClient
- from backend.app.services import spool_filament_preset
- URL = "/api/v1/printers/{pid}/slots/0/0/spool-defaults"
- SPOOL = {
- "id": 42,
- "filament": {"id": 1, "name": "PLA Matte", "material": "PLA", "color_hex": "000000", "weight": 1000},
- "remaining_weight": 800.0,
- "used_weight": 200.0,
- "archived": False,
- "extra": {
- "bambu_slicer_filament": '"GFA01"',
- "bambu_slicer_filament_name": '"Bambu PLA Matte @BBL X1C"',
- },
- }
- @pytest.fixture(autouse=True)
- def _empty_cache():
- spool_filament_preset._spoolman_own_presets.clear()
- yield
- spool_filament_preset._spoolman_own_presets.clear()
- @pytest.fixture
- async def spoolman_slot(db_session, printer_factory):
- from backend.app.models.settings import Settings
- from backend.app.models.spoolman_k_profile import SpoolmanKProfile
- from backend.app.models.spoolman_slot_assignment import SpoolmanSlotAssignment
- db_session.add(Settings(key="spoolman_enabled", value="true"))
- db_session.add(Settings(key="spoolman_url", value="http://localhost:7912"))
- printer = await printer_factory(model="X1C")
- db_session.add(SpoolmanSlotAssignment(printer_id=printer.id, ams_id=0, tray_id=0, spoolman_spool_id=42))
- db_session.add(
- SpoolmanKProfile(
- spoolman_spool_id=42, printer_id=printer.id, extruder=0, nozzle_diameter="0.4", k_value=0.02, cali_idx=7
- )
- )
- await db_session.commit()
- return printer.id
- @pytest.fixture
- def spoolman():
- client = MagicMock()
- client.get_spool = AsyncMock(return_value=SPOOL)
- with patch("backend.app.services.spoolman.get_spoolman_client", AsyncMock(return_value=client)):
- yield client
- class _Nozzle:
- nozzle_diameter = "0.4"
- @pytest.fixture
- def printer_state():
- state = MagicMock(nozzles=[_Nozzle()], ams_extruder_map={"0": 0}, ams_switch_inlet=None, raw_data={})
- with patch("backend.app.api.routes.printers.printer_manager") as pm:
- pm.get_status = MagicMock(return_value=state)
- pm.get_model = MagicMock(return_value="X1C")
- yield pm
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_configure_slot_opens_with_the_spools_own_preset(
- async_client: AsyncClient, spoolman_slot, spoolman, printer_state
- ):
- body = (await async_client.get(URL.format(pid=spoolman_slot))).json()
- assert body["slicer_filament"] == "GFA01"
- assert body["slicer_filament_name"] == "Bambu PLA Matte @BBL X1C"
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_the_k_profile_lookup_uses_the_spools_own_preset(db_session, spoolman_slot, spoolman):
- from backend.app.services.slot_kprofile import find_slot_kprofile_for_extruder
- profile = await find_slot_kprofile_for_extruder(db_session, spoolman_slot, 0, 0, 0, "0.4", "X1C", None)
- assert (profile.cali_idx, profile.filament_id) == (7, "GFA01")
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_a_per_model_override_wins_without_asking_spoolman(db_session, spoolman_slot, spoolman):
- from backend.app.models.spool_filament_preset import SpoolmanFilamentPreset
- from backend.app.services.slot_kprofile import find_slot_kprofile_for_extruder
- db_session.add(
- SpoolmanFilamentPreset(spoolman_spool_id=42, printer_model="X1C", nozzle_diameter=None, slicer_filament="GFA05")
- )
- await db_session.commit()
- profile = await find_slot_kprofile_for_extruder(db_session, spoolman_slot, 0, 0, 0, "0.4", "X1C", None)
- assert profile.filament_id == "GFA05"
- spoolman.get_spool.assert_not_called()
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_the_own_preset_is_remembered_and_dropped_on_an_edit(spoolman):
- await spool_filament_preset.spoolman_spool_own_preset(42)
- await spool_filament_preset.spoolman_spool_own_preset(42)
- assert spoolman.get_spool.await_count == 1
- spool_filament_preset.forget_spoolman_spool_own_preset(42)
- await spool_filament_preset.spoolman_spool_own_preset(42)
- assert spoolman.get_spool.await_count == 2
- @pytest.mark.asyncio
- @pytest.mark.integration
- async def test_an_override_left_blank_on_purpose_keeps_the_slot_without_a_preset(db_session, spoolman_slot, spoolman):
- from backend.app.models.spool_filament_preset import SpoolmanFilamentPreset
- from backend.app.services.slot_kprofile import find_slot_kprofile_for_extruder
- db_session.add(
- SpoolmanFilamentPreset(spoolman_spool_id=42, printer_model="X1C", nozzle_diameter=None, slicer_filament=None)
- )
- await db_session.commit()
- profile = await find_slot_kprofile_for_extruder(db_session, spoolman_slot, 0, 0, 0, "0.4", "X1C", None)
- assert profile.filament_id is None
- spoolman.get_spool.assert_not_called()
- @pytest.mark.asyncio
- @pytest.mark.integration
- @pytest.mark.parametrize("stored,expected", [('"GFSA01_02"', "GFA01"), ('"38"', None)])
- async def test_the_k_profile_filament_id_is_the_one_the_printer_takes(
- db_session, spoolman_slot, spoolman, stored, expected
- ):
- """The cloud picker stores the setting-id form; a local preset is stored
- by its number, which only the slicer resolver turns into a filament id."""
- from backend.app.services.slot_kprofile import find_slot_kprofile_for_extruder
- spoolman.get_spool = AsyncMock(return_value={**SPOOL, "extra": {"bambu_slicer_filament": stored}})
- profile = await find_slot_kprofile_for_extruder(db_session, spoolman_slot, 0, 0, 0, "0.4", "X1C", None)
- assert profile.filament_id == expected
|