velxio/test/backend/unit/test_arduino_cli_error_mess...

92 lines
4.3 KiB
Python

"""arduino-cli failures reach the UI / agent as one actionable sentence.
Regression for 2026-08-17: a fresh desktop install has no library index
yet; when arduino-cli could not download it (firewall / proxy) `lib search`
returned a JSON blob on stderr and we forwarded it verbatim, so the in-app
agent told the user "the library server returns a JSON error" ten times in
a row. The strings below are the real arduino-cli 1.0.4 output captured
offline (`unshare -n`) against an empty data dir.
"""
from __future__ import annotations
import sys
from pathlib import Path
_REPO = Path(__file__).resolve().parents[3]
sys.path.insert(0, str(_REPO / "backend"))
from app.services.arduino_cli import humanize_cli_error # noqa: E402
SEARCH_JSON_STDERR = (
'{\n "error": "Error updating library index: Error downloading index '
"'https://downloads.arduino.cc/libraries/library_index.tar.bz2': Get "
'\\"https://downloads.arduino.cc/libraries/library_index.tar.bz2\\": dial tcp: '
'lookup downloads.arduino.cc on 127.0.0.53:53: dial udp 127.0.0.53:53: connect: '
'network is unreachable",\n "warnings": [\n "Error initializing instance: '
"Error downloading index 'https://downloads.arduino.cc/libraries/library_index.tar.bz2'\"\n ]\n}"
)
INSTALL_NO_INDEX_STDERR = (
"Error initializing instance: Error downloading index "
"'https://downloads.arduino.cc/libraries/library_index.tar.bz2': Get "
'"https://downloads.arduino.cc/libraries/library_index.tar.bz2": dial tcp: lookup '
"downloads.arduino.cc on 127.0.0.53:53: dial udp 127.0.0.53:53: connect: network is unreachable\n"
"Error initializing instance: Loading index file: reading library_index.json: open "
"/x/data/library_index.json: no such file or directory\n"
)
INSTALL_NO_NET_WITH_INDEX = (
"Downloading Adafruit GFX Library@1.12.6...\n"
'Adafruit GFX Library@1.12.6 Get "https://downloads.arduino.cc/libraries/github.com/adafruit/'
'Adafruit_GFX_Library-1.12.6.zip?query=install": dial tcp: lookup downloads.arduino.cc on '
"127.0.0.53:53: dial udp 127.0.0.53:53: connect: network is unreachable\n"
"Error installing Adafruit GFX Library: Can't download library: Get "
'"https://downloads.arduino.cc/libraries/github.com/adafruit/Adafruit_GFX_Library-1.12.6.zip'
'?query=install": dial tcp: lookup downloads.arduino.cc on 127.0.0.53:53: dial udp '
"127.0.0.53:53: connect: network is unreachable\n"
)
def test_search_json_error_becomes_index_download_sentence():
msg = humanize_cli_error(SEARCH_JSON_STDERR, action="search libraries")
assert msg.startswith("Could not search libraries:")
assert "library index" in msg
assert "downloads.arduino.cc" in msg
assert "firewall or proxy" in msg
# No JSON leaks through to the user / agent.
assert "{" not in msg and "warnings" not in msg
def test_install_without_index_is_the_same_story():
msg = humanize_cli_error(INSTALL_NO_INDEX_STDERR, action="install Adafruit GFX Library")
assert msg.startswith("Could not install Adafruit GFX Library:")
assert "library index" in msg
assert "downloads.arduino.cc" in msg
def test_install_with_index_but_no_network_names_the_download():
msg = humanize_cli_error(INSTALL_NO_NET_WITH_INDEX, action="install Adafruit GFX Library")
assert msg.startswith("Could not install Adafruit GFX Library:")
assert "download from downloads.arduino.cc failed" in msg
assert "firewall or proxy" in msg
def test_unknown_library_passes_the_cli_line_through():
msg = humanize_cli_error("Error installing NoSuchLib: Library 'NoSuchLib' not found", action="install NoSuchLib")
assert msg == "Could not install NoSuchLib: Error installing NoSuchLib: Library 'NoSuchLib' not found"
def test_empty_and_unknown_shapes_still_return_a_sentence():
assert humanize_cli_error("", action="search libraries") == (
"Could not search libraries: arduino-cli returned no output."
)
assert humanize_cli_error(None, action="search libraries").startswith("Could not search libraries:")
long = "x" * 1000
msg = humanize_cli_error(long, action="search libraries")
assert msg.startswith("Could not search libraries: ") and len(msg) < 400
def test_multiline_unknown_error_uses_first_line_only():
msg = humanize_cli_error("\n\nfirst line here\nsecond line\n", action="search libraries")
assert msg == "Could not search libraries: first line here"