From 5e4aa8b101639627c058145f392795d1e5ef359e Mon Sep 17 00:00:00 2001 From: Andrew Pimenov Date: Sun, 9 Aug 2026 03:49:53 +0300 Subject: [PATCH] exporter: surface a skipped module's warning as its placeholder reason unavailable() only ever read module.errors for the placeholder detail text, so a deliberately skipped section (speed in --quick or target mode, which reports its reason as a warning, not an error) always fell through to the generic 'no data was collected for this section' line even though the real reason ('speedtest skipped in target mode') was sitting right there in the json. spec says a skipped speedtest must say why, not just that it's missing. --- src/netcheck/exporter.py | 2 ++ tests/test_exporter.py | 12 ++++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/netcheck/exporter.py b/src/netcheck/exporter.py index a75453f..99bd241 100644 --- a/src/netcheck/exporter.py +++ b/src/netcheck/exporter.py @@ -208,6 +208,8 @@ def unavailable(report: dict[str, Any], section: str) -> str | None: if module.get("status") in ("ok", "partial") and module.get("data") is not None: return None detail = "; ".join(f"{e.get('source')}: {e.get('message')}" for e in module.get("errors") or []) + if not detail: + detail = "; ".join(module.get("warnings") or []) if not detail: detail = "no data was collected for this section" return f"_Not available — {module.get('status', 'skipped')}: {detail}._" diff --git a/tests/test_exporter.py b/tests/test_exporter.py index 1e6883d..cfa5f48 100644 --- a/tests/test_exporter.py +++ b/tests/test_exporter.py @@ -570,6 +570,18 @@ def test_unavailable_explains_a_skipped_module_without_inventing_an_error(): assert "skipped" in note +def test_unavailable_surfaces_the_skip_reason_from_warnings(): + report = build_report( + meta(), + {"speed": ModuleResult(name="speed", status="skipped", warnings=["speedtest skipped in target mode"])}, + [], + {}, + ) + note = unavailable(report, "speed") + assert note is not None + assert "speedtest skipped in target mode" in note + + def test_an_all_modules_failed_run_still_renders_every_section(): text = render_markdown(dead_report()) headings = [line for line in text.splitlines() if line.startswith("## ")]