diff --git a/src/central/adapter.py b/src/central/adapter.py index 2a408b0..76ab04e 100644 --- a/src/central/adapter.py +++ b/src/central/adapter.py @@ -85,5 +85,16 @@ class SourceAdapter(ABC): Return list[dict] (framework renders as a generic table; columns come from the first dict's keys, in insertion order). Return None to skip preview. Raise to surface an error banner — framework catches at the route boundary. + + Contract: + - Preview is a pure function of `settings`. Do NOT access + self._config_store or cursor_db state — the framework may instantiate + adapters with a stub config_store solely to call this method. + - Network preview implementations must open their own short-lived + aiohttp session (the adapter's polling session may not exist; the GUI + process never calls startup()). + - Return None when preview is not meaningful (e.g., required settings + like region are unset). Return [] explicitly if the query ran and + matched zero rows — the framework renders that distinctly from None. """ return None diff --git a/src/central/gui/templates/_adapter_preview.html b/src/central/gui/templates/_adapter_preview.html index ff9ef0c..ab8a7f1 100644 --- a/src/central/gui/templates/_adapter_preview.html +++ b/src/central/gui/templates/_adapter_preview.html @@ -2,9 +2,10 @@
{{ preview_error }}
-{% elif preview_rows %} +{% elif preview_rows is not none %}
Preview ({{ preview_rows|length }} rows) + {% if preview_rows %} @@ -19,5 +20,6 @@ {% endfor %}
+ {% endif %}
{% endif %} diff --git a/tests/test_preview_hook.py b/tests/test_preview_hook.py index e9fbd30..88b9b1b 100644 --- a/tests/test_preview_hook.py +++ b/tests/test_preview_hook.py @@ -106,3 +106,15 @@ def test_partial_renders_nothing_when_both_none(): assert "Preview Unavailable" not in out # Either empty or only whitespace/newlines from the template. assert "Preview (" not in out + + +def test_partial_renders_empty_list(): + """Empty list -> legend with (0 rows), no table. + + Distinct from None (which renders nothing at all). Lets adapters signal + 'query ran, matched zero rows' separately from 'preview not meaningful'. + """ + out = _render_partial(preview_rows=[], preview_error=None) + assert "Preview (0 rows)" in out + assert "" not in out