Files
grotti/tests/test_drivers.py
Dominic Gundel db6a85a703 Grotti 3.7.0: Treiber für Kobra 4 und Marlin, smartere Dateien-Auswahl und einstellbare Etiketten.
Senden und Abbruch laufen über den Treiber, Orca-Doppelzeilen und tote Ideen-API fallen weg, Drucker folgen der Datei, Etikettenformat liegt in den Einstellungen.
2026-11-02 14:03:57 +01:00

129 lines
4.9 KiB
Python

"""Treiberwahl und die LAN-Karte. Kein echter Drucker."""
import sys
import unittest
from pathlib import Path
from unittest import mock
ROOT = Path(__file__).resolve().parents[1]
sys.path.insert(0, str(ROOT))
from grotti.drivers import for_printer
from grotti.drivers.anycubic_lan import card_from_info, slots_from_report
from grotti.moonraker import PrinterError
from grotti.printers import family_from_name
class FamilyTests(unittest.TestCase):
def test_existing_names_stay_moonraker(self):
for name, family in (
("Kobra 3 A1", "kobra_3"),
("Kobra S1", "kobra_s1"),
):
self.assertEqual(family_from_name(name), family)
drv = for_printer({"name": name, "family": family, "host": "10.0.0.1"})
self.assertEqual(drv.transport, "moonraker")
self.assertTrue(drv.rinkhals)
self.assertFalse(drv.firmware_restart)
def test_kobra_4_is_lan(self):
self.assertEqual(family_from_name("Kobra 4"), "kobra_4")
drv = for_printer({"family": "kobra_4", "host": "10.0.0.4"})
self.assertEqual(drv.transport, "anycubic_lan")
self.assertFalse(drv.rinkhals)
def test_i3_is_marlin(self):
self.assertEqual(family_from_name("Anycubic i3 Mega"), "anycubic_i3")
drv = for_printer({"family": "anycubic_i3", "host": "usb"})
self.assertEqual(drv.transport, "marlin")
def test_tenlog_is_marlin_with_two_heads(self):
self.assertEqual(family_from_name("Tenlog"), "tenlog")
drv = for_printer({"family": "tenlog", "host": "COM5"})
self.assertEqual(drv.transport, "marlin")
self.assertFalse(drv.rinkhals)
class LanCardTests(unittest.TestCase):
def test_busy_with_file_is_printing(self):
card = card_from_info({
"state": "busy",
"temp": {"curr_nozzle_temp": 210, "curr_hotbed_temp": 60},
"project": {"filename": "teil.gcode", "progress": 40, "curr_layer": 3, "total_layers": 10},
})
self.assertEqual(card["state"], "printing")
self.assertEqual(card["filename"], "teil.gcode")
self.assertAlmostEqual(card["progress"], 0.4)
self.assertEqual(card["nozzle"], 210)
self.assertEqual(card["layer"], 3)
self.assertFalse(card["has_camera"])
self.assertIsNone(card["mesh"])
def test_free_is_standby(self):
card = card_from_info({"state": "free", "project": None})
self.assertEqual(card["state"], "standby")
self.assertEqual(card["filename"], "")
def test_slots_from_boxes(self):
slots = slots_from_report({
"multi_color_box": [{
"slots": [
{"type": "PETG"},
{"type": "PLA"},
{"type": ""},
{"type": "ABS"},
],
}],
})
self.assertEqual([item["type"] for item in slots], ["PETG", "PLA", "ABS"])
self.assertEqual([item["index"] for item in slots], [0, 1, 3])
class LanUploadTests(unittest.TestCase):
def test_posts_filename_and_gcode(self):
captured = {}
class Response:
def __enter__(self):
return self
def __exit__(self, *args):
return False
def read(self):
return b"{}"
def fake_urlopen(request, timeout=0):
captured["url"] = request.full_url
captured["body"] = request.data
captured["length"] = request.headers["X-file-length"]
return Response()
info = {"urls": {"fileUploadurl": "http://10.0.0.4:18910/gcode_upload?s=token"}}
drv = for_printer({"family": "kobra_4", "host": "10.0.0.4"})
with mock.patch("grotti.anycubic_lan.print_info", return_value=info), \
mock.patch("urllib.request.urlopen", fake_urlopen):
name = drv.upload("10.0.0.4", "teil.gcode", b"G1 X1")
self.assertEqual(name, "teil.gcode")
self.assertIn("/gcode_upload", captured["url"])
self.assertIn(b'name="filename"', captured["body"])
self.assertIn(b'name="gcode"', captured["body"])
self.assertIn(b"G1 X1", captured["body"])
self.assertEqual(captured["length"], "5")
def test_missing_url(self):
drv = for_printer({"family": "kobra_4"})
with mock.patch("grotti.anycubic_lan.print_info", return_value={"urls": {}}):
with self.assertRaises(PrinterError):
drv.upload("10.0.0.4", "teil.gcode", b"G1")
class MarlinStubTests(unittest.TestCase):
def test_start_says_service_missing(self):
drv = for_printer({"family": "anycubic_i3", "name": "i3", "host": "COM3"})
cards = drv.snapshot([{"name": "i3", "host": "COM3", "family": "anycubic_i3"}])
self.assertEqual(cards[0]["state"], "offline")
self.assertIn("läuft nicht", cards[0]["message"])
with self.assertRaises(PrinterError):
drv.start_print("COM3", "teil.gcode")