mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-05 12:22:06 +00:00
fix(tui-v2): handle non-existent entries and tree nav focus feedback
Opening a non-existent entry now shows "Entry not found" instead of rendering a broken empty board. Tree navigation commands now give clear feedback when focus is on wrong pane or sidebar is collapsed. Co-Authored-By: Claude Opus 4.6 <[email protected]>
This commit is contained in:
1 parent
08e71bd1b4
commit
6f2b9a6d18
4 files changed
+82
-2
No files matched your search
@@ -1268,3 +1268,26 @@ Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `58 passed`.
|
||||
|
||||
## 36) Progress Update (2026-03-03, Slice: UX Bug Fixes from Walkthrough)
|
||||
|
||||
Completed:
|
||||
|
||||
1. Fixed `open <non-existent-id>` showing broken empty board:
|
||||
- Now checks for empty dict (not just None) from retrieve_entry.
|
||||
- Shows clear "Entry #N not found" message in inspector.
|
||||
- Clears selection state so action strip doesn't show stale context.
|
||||
2. Fixed tree navigation silently ignoring commands when focus is on wrong pane:
|
||||
- `profile-tree-next`, `profile-tree-prev`, `profile-tree-open` now show
|
||||
"Focus left pane first (press 1)" instead of silently returning.
|
||||
- Also shows "Sidebar is collapsed. Press Ctrl+B to expand." when sidebar is collapsed.
|
||||
|
||||
Regression coverage:
|
||||
|
||||
1. Added `test_tui2_textual_open_nonexistent_entry_shows_not_found`.
|
||||
2. Added `test_tui2_textual_tree_nav_feedback_when_wrong_pane`.
|
||||
|
||||
Validation:
|
||||
|
||||
1. `poetry run pytest -q src/tests/test_tui_v2_textual_interactions.py src/tests/test_tui_v2_action_matrix.py`
|
||||
2. Result: `60 passed`.
|
||||
@@ -221,3 +221,10 @@
|
||||
|
||||
### Verification
|
||||
- Focused TUI v2 gate: `58 passed`.
|
||||
|
||||
## Session Update (2026-03-03, Slice 10)
|
||||
|
||||
### UX bug fixes from interactive walkthrough
|
||||
- Fixed `open <non-existent-id>` rendering broken empty board (now shows "not found" and clears selection).
|
||||
- Fixed tree nav commands (`profile-tree-next/prev/open`) silently ignoring when focus is on wrong pane (now shows guidance).
|
||||
- Added 2 regression tests. Gate: `60 passed`.
|
||||
@@ -2449,13 +2449,18 @@ def launch_tui2(
|
||||
self._set_totp_board_visible(False)
|
||||
try:
|
||||
entry = self._service.retrieve_entry(entry_index)
|
||||
if not isinstance(entry, dict):
|
||||
self.query_one("#entry-detail", Static).update("Entry not found.")
|
||||
if not isinstance(entry, dict) or not entry:
|
||||
self.query_one("#entry-detail", Static).update(
|
||||
f"Entry #{entry_index} not found.\n\nThe entry may have been deleted or the ID is invalid."
|
||||
)
|
||||
self.query_one("#link-detail", Static).update(
|
||||
"Links: entry not found."
|
||||
)
|
||||
self._current_links = []
|
||||
self._current_link_cursor = 0
|
||||
self._selected_entry_id = None
|
||||
self._selected_entry = None
|
||||
self._update_action_strip()
|
||||
self._set_status(f"Entry {entry_index} not found")
|
||||
return
|
||||
self._selected_entry_id = int(entry_index)
|
||||
@@ -5635,8 +5640,10 @@ def launch_tui2(
|
||||
|
||||
def action_profile_tree_next(self) -> None:
|
||||
if self._sidebar_collapsed:
|
||||
self._set_status("Sidebar is collapsed. Press Ctrl+B to expand.")
|
||||
return
|
||||
if self._focus_pane != "left":
|
||||
self._set_status("Focus left pane first (press 1)")
|
||||
return
|
||||
self._refresh_profile_tree()
|
||||
nodes = self._profile_tree_visible_nodes()
|
||||
@@ -5650,8 +5657,10 @@ def launch_tui2(
|
||||
|
||||
def action_profile_tree_prev(self) -> None:
|
||||
if self._sidebar_collapsed:
|
||||
self._set_status("Sidebar is collapsed. Press Ctrl+B to expand.")
|
||||
return
|
||||
if self._focus_pane != "left":
|
||||
self._set_status("Focus left pane first (press 1)")
|
||||
return
|
||||
self._refresh_profile_tree()
|
||||
nodes = self._profile_tree_visible_nodes()
|
||||
@@ -5665,8 +5674,10 @@ def launch_tui2(
|
||||
|
||||
def action_profile_tree_open(self) -> None:
|
||||
if self._sidebar_collapsed:
|
||||
self._set_status("Sidebar is collapsed. Press Ctrl+B to expand.")
|
||||
return
|
||||
if self._focus_pane != "left":
|
||||
self._set_status("Focus left pane first (press 1)")
|
||||
return
|
||||
self._refresh_profile_tree()
|
||||
nodes = self._profile_tree_visible_nodes()
|
||||
|
||||
@@ -1583,6 +1583,45 @@ async def test_tui2_textual_password_board_uses_card_sections() -> None:
|
||||
assert "+- Quick Actions " in board
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_open_nonexistent_entry_shows_not_found() -> None:
|
||||
service = FakeEntryService(
|
||||
[{"id": 1, "kind": "password", "label": "Login 1", "length": 16}]
|
||||
)
|
||||
app = _build_app(service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
app._run_palette_command("open 999")
|
||||
await pilot.pause()
|
||||
board = _widget_text(app, "#entry-detail")
|
||||
assert "not found" in board.lower()
|
||||
status_text = _widget_text(app, "#status")
|
||||
assert "not found" in status_text.lower()
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_tree_nav_feedback_when_wrong_pane() -> None:
|
||||
service = FakeEntryService(
|
||||
[{"id": 1, "kind": "password", "label": "Login 1", "length": 16}]
|
||||
)
|
||||
profile_service = FakeProfileService(["fp-default"])
|
||||
app = _build_app(service, profile_service=profile_service)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
# Focus is on center by default, tree-next should give feedback
|
||||
app._run_palette_command("profile-tree-next")
|
||||
await pilot.pause()
|
||||
status_text = _widget_text(app, "#status")
|
||||
assert "focus" in status_text.lower() or "left" in status_text.lower()
|
||||
|
||||
app._run_palette_command("profile-tree-open")
|
||||
await pilot.pause()
|
||||
status_text = _widget_text(app, "#status")
|
||||
assert "focus" in status_text.lower() or "left" in status_text.lower()
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_tui2_textual_filters_panel_tracks_selected_entry() -> None:
|
||||
service = FakeEntryService(
|
||||
|
||||
Reference in new issue
Block a user