feat: server search/filter + test-all health column #30

Merged
the_og merged 2 commits from feat/server-list-ux into main 2026-07-08 11:56:37 -04:00
Owner

Closes #27
Closes #28

Issue #27 — Server search / filter box

  • bcc_core.py: server_matches_filter(entry, query) — case-insensitive substring match on server name, plus command (stdio) or url (remote). Empty/whitespace query matches everything. filter_servers(entries, query) is the list-level convenience wrapper.
  • bcc.py: a QLineEdit search box above the server tables (placeholder "Search servers by name, command, or url…", clear button). textChanged re-runs _refresh_tables, which now filters both the active and disabled tables via core.server_matches_filter, skipping non-matching rows. Clearing the box restores all rows. Empty-state placeholders distinguish "no matches for this filter" from "genuinely empty section".

Issue #28 — "Test all" + per-server health/status column

  • bcc_core.py: HealthStatus (plain string constants UNTESTED/OK/FAILED, matching the existing plain-string status convention used by check_dependency) and health_from_spawn_result(result) -> (status, short_summary), which maps a spawn_test() result dict to that tri-state without duplicating any of spawn_test's own subprocess/outcome logic. outcome == "ok" → OK, "not_applicable" (remote/no command) → UNTESTED, everything else (exited/crashed/not_found) → FAILED, with the first line of stderr folded into the summary when present.
  • bcc.py: a new "Health" column (5th column) on both server tables — a colored dot (grey untested / green ok / red failed) with a tooltip carrying the summary. A "Test all" button in the action bar spawn-tests every enabled, stdio server sequentially off the UI thread (reusing SpawnTester/spawn_test, one at a time so the app never spawns a pile of processes at once), updating each row's dot as results land and showing Testing N/total… progress. Remote servers are shown as untested with a tooltip pointing at the editor's existing "Test connection" button rather than being spawn-tested. Editing a server's fields invalidates its cached health (reverts the dot to untested) since the old result no longer reflects what's on disk. Health results are cleared on profile switch/reload.

Testing

  • New pure-logic unit tests in tests/test_core.py for both features (filter: name/command/url match, case-insensitivity, empty query, no match, list-level filter_servers; health mapping: ok/not_applicable/crashed/exited/not_found, plus a check that a reason with no stderr doesn't get a stray dash appended).
  • Test count: 136 → 150 (all passing).
  • ruff check . and ruff format --check . both clean.
  • bcc.py GUI changes verified via ast.parse + ruff only (no PySide6 install in this environment, per repo convention); all new pure logic lives in bcc_core.py and is Qt-free/pytest-covered.

Notes / decisions

  • Health is a distinct "Health" column, separate from the existing "Status" column (which reflects PATH/dependency resolution, not spawn-test results) — keeping the two concerns visually distinct.
  • "Test all" only targets enabled stdio servers per the issue description; disabled servers and remote servers are left out of the run (remote already has a dedicated "Test connection" flow in the editor).
Closes #27 Closes #28 ## Issue #27 — Server search / filter box - `bcc_core.py`: `server_matches_filter(entry, query)` — case-insensitive substring match on server name, plus command (stdio) or url (remote). Empty/whitespace query matches everything. `filter_servers(entries, query)` is the list-level convenience wrapper. - `bcc.py`: a `QLineEdit` search box above the server tables (placeholder "Search servers by name, command, or url…", clear button). `textChanged` re-runs `_refresh_tables`, which now filters both the active and disabled tables via `core.server_matches_filter`, skipping non-matching rows. Clearing the box restores all rows. Empty-state placeholders distinguish "no matches for this filter" from "genuinely empty section". ## Issue #28 — "Test all" + per-server health/status column - `bcc_core.py`: `HealthStatus` (plain string constants `UNTESTED`/`OK`/`FAILED`, matching the existing plain-string status convention used by `check_dependency`) and `health_from_spawn_result(result) -> (status, short_summary)`, which maps a `spawn_test()` result dict to that tri-state without duplicating any of `spawn_test`'s own subprocess/outcome logic. `outcome == "ok"` → OK, `"not_applicable"` (remote/no command) → UNTESTED, everything else (`exited`/`crashed`/`not_found`) → FAILED, with the first line of stderr folded into the summary when present. - `bcc.py`: a new "Health" column (5th column) on both server tables — a colored dot (grey untested / green ok / red failed) with a tooltip carrying the summary. A "Test all" button in the action bar spawn-tests every **enabled, stdio** server sequentially off the UI thread (reusing `SpawnTester`/`spawn_test`, one at a time so the app never spawns a pile of processes at once), updating each row's dot as results land and showing `Testing N/total…` progress. Remote servers are shown as untested with a tooltip pointing at the editor's existing "Test connection" button rather than being spawn-tested. Editing a server's fields invalidates its cached health (reverts the dot to untested) since the old result no longer reflects what's on disk. Health results are cleared on profile switch/reload. ## Testing - New pure-logic unit tests in `tests/test_core.py` for both features (filter: name/command/url match, case-insensitivity, empty query, no match, list-level `filter_servers`; health mapping: ok/not_applicable/crashed/exited/not_found, plus a check that a reason with no stderr doesn't get a stray dash appended). - Test count: 136 → 150 (all passing). - `ruff check .` and `ruff format --check .` both clean. - `bcc.py` GUI changes verified via `ast.parse` + ruff only (no PySide6 install in this environment, per repo convention); all new pure logic lives in `bcc_core.py` and is Qt-free/pytest-covered. ## Notes / decisions - Health is a distinct "Health" column, separate from the existing "Status" column (which reflects PATH/dependency resolution, not spawn-test results) — keeping the two concerns visually distinct. - "Test all" only targets enabled stdio servers per the issue description; disabled servers and remote servers are left out of the run (remote already has a dedicated "Test connection" flow in the editor).
the_og added the P1 label 2026-07-08 11:53:55 -04:00
the_og added 1 commit 2026-07-08 11:53:56 -04:00
feat: server search/filter + test-all health column (#27, #28)
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 8s
CI / Tests (py3.12) (pull_request) Successful in 7s
668fb903d0
the_og added 1 commit 2026-07-08 11:55:57 -04:00
Merge remote-tracking branch 'origin/main' into feat/server-list-ux
CI / Lint (ruff) (pull_request) Successful in 6s
CI / Tests (py3.10) (pull_request) Successful in 8s
CI / Tests (py3.12) (pull_request) Successful in 8s
f4d4301c26
the_og merged commit 3b5379a2b8 into main 2026-07-08 11:56:37 -04:00
the_og deleted branch feat/server-list-ux 2026-07-08 11:56:37 -04:00
Sign in to join this conversation.