import base64 import os import stat import pytest from fastapi.testclient import TestClient from app.bridge import Bridge from app.sshsource import KeyStore from app.storage import SettingsStore from app.web import create_app from .fakes import FakeCC2, FakeReader, FakeSpoolman from .test_ssh import _new_key_text H = {"X-Bridge-Request": "1"} def make_client(tmp_path, env=None): settings = SettingsStore(tmp_path, env={}) sm = FakeSpoolman() sm.add(5, material="PLA+", color="1E40AF") bridge = Bridge(tmp_path, settings, KeyStore(tmp_path), reader_factory=lambda s: FakeReader(), cc2_factory=lambda s: FakeCC2(), spoolman_factory=lambda s: sm) app = create_app(tmp_path, bridge=bridge, start_loop=False, env=env or {}) return TestClient(app), bridge def test_pages_render(tmp_path): c, _ = make_client(tmp_path) for path in ("/", "/tags", "/settings"): r = c.get(path) assert r.status_code == 200 and "CC2" in r.text def test_writes_need_marker_header(tmp_path): c, _ = make_client(tmp_path) assert c.post("/api/settings", json={"dry_run": False}).status_code == 403 assert c.post("/api/settings", json={"dry_run": True}, headers=H).status_code == 200 def test_settings_roundtrip_and_validation(tmp_path): c, _ = make_client(tmp_path) s = c.get("/api/settings").json() assert s["dry_run"] is True and s["id_offset"] == 10000 r = c.post("/api/settings", json={"poll_interval": "7", "location_storage": "Regal"}, headers=H) assert r.json()["poll_interval"] == 7.0 assert c.get("/api/settings").json()["location_storage"] == "Regal" assert c.post("/api/settings", json={"location_slot": "Slot"}, headers=H).status_code == 400 assert SettingsStore(tmp_path).get().location_storage == "Regal" def test_ssh_key_upload_never_returned(tmp_path): c, _ = make_client(tmp_path) text = _new_key_text() r = c.post("/api/ssh/key", json={"key": text}, headers=H) assert r.status_code == 200 body = r.text + c.get("/api/ssh").text + c.get("/api/status").text assert "PRIVATE KEY" not in body and text.splitlines()[1] not in body assert r.json()["key"]["fingerprint"].startswith("SHA256:") path = tmp_path / "ssh" / "id_key" assert stat.S_IMODE(os.stat(path).st_mode) == 0o600 assert c.post("/api/ssh/key", json={"key": "junk"}, headers=H).status_code == 400 assert c.delete("/api/ssh/key", headers=H).json() == {"key": None} assert not path.exists() def test_hostkey_only_from_last_test(tmp_path): c, _ = make_client(tmp_path) r = c.post("/api/printers/p1/ssh/hostkey", json={"fingerprint": "SHA256:forged"}, headers=H) assert r.status_code == 400 assert c.post("/api/printers/nope/ssh/hostkey", json={"fingerprint": "x"}, headers=H).status_code == 404 def test_tag_endpoint(tmp_path): c, _ = make_client(tmp_path) r = c.post("/api/tag", json={"spool_id": 5, "color": "2850DF", "material": "PLA", "subtype": 1, "temp_min": 190, "temp_max": 230}, headers=H) assert r.status_code == 200 d = r.json() assert "A2:14:2850DFFF" in d["commands"] and "A2:17:00AF2715" in d["commands"] assert d["decoded"]["spool_id"] == 5 and d["qr_svg"].startswith("