mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-11-06 12:52:04 +00:00
Improve TUI v2 UX with help overlay and pane focus
This commit is contained in:
1 parent
e3c117110a
commit
e667249ec4
5 files changed
+253
-32
No files matched your search
@@ -200,3 +200,5 @@
|
||||
- Completed help/docs alignment gate: updated `seedpass tui2` help text, capabilities hints for keybindings/palette (`Ctrl+P`, `p/n`, `x`), and docs discoverability commands (`seedpass tui2 --help/--check`).
|
||||
- 2026-03-01: Switched default root CLI interactive routing to TUI v2 in `seedpass.cli.main` (when no subcommand), with automatic legacy fallback when Textual runtime is unavailable.
|
||||
- Added explicit one-release override flag `--legacy-tui` and updated test coverage (`test_typer_cli.py`) for default TUI v2 launch, forced legacy path, and root fallback behavior.
|
||||
- 2026-03-01: UX pass for TUI v2 added help overlay (`?`), quick jump input (`j`), pane focus switching (`1/2/3`) with visual focus borders, mode-tagged status line, and an activity log panel of recent actions.
|
||||
- Added document dirty-state UX improvements (`Edit mode [*]` marker, no-op save guard) and updated Textual interaction/parity tests for Textual 8-compatible action-driven control paths.
|
||||
@@ -242,7 +242,7 @@ def build_capabilities() -> dict[str, Any]:
|
||||
"Use `seedpass capabilities --format json` for machine-readable discovery.",
|
||||
"Run `seedpass tui2 --check` before adopting Textual-based TUI v2.",
|
||||
"Use `seedpass --legacy-tui` to force the legacy interface during cutover.",
|
||||
"In TUI v2, use `Ctrl+P` for the command palette, `p/n` for paging, and `x` to retry the last failed action.",
|
||||
"In TUI v2, use `?` for help, `j` to jump to entry id, `1/2/3` to focus panes, `Ctrl+P` for palette, `p/n` for paging, and `x` to retry.",
|
||||
"For graph workflows, start with `seedpass entry link-add --help` and `seedpass entry links --help`.",
|
||||
"For document workflows, run `seedpass entry import-document --help` and `seedpass agent document-import --help`.",
|
||||
"After unlock/login, run `seedpass capabilities` before autonomous runs.",
|
||||
|
||||
+213
-2
@@ -136,13 +136,34 @@ def launch_tui2(
|
||||
#doc-edit-help { margin-top: 1; }
|
||||
#doc-edit-content { height: 1fr; }
|
||||
#doc-edit-content-single { height: 1fr; }
|
||||
#help-overlay {
|
||||
layer: overlay;
|
||||
dock: top;
|
||||
margin: 1 2;
|
||||
border: solid $warning;
|
||||
padding: 1;
|
||||
background: $surface;
|
||||
}
|
||||
#activity {
|
||||
height: 12;
|
||||
border: solid $secondary;
|
||||
padding: 1;
|
||||
margin-top: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
.pane-focus { border: heavy $success; }
|
||||
.hidden { display: none; }
|
||||
"""
|
||||
BINDINGS = [
|
||||
("q", "quit", "Quit"),
|
||||
("r", "refresh", "Refresh"),
|
||||
("x", "retry_last_error", "Retry"),
|
||||
("question_mark", "toggle_help", "Help"),
|
||||
("slash", "focus_search", "Search"),
|
||||
("j", "focus_jump", "Jump"),
|
||||
("1", "focus_left", "Left"),
|
||||
("2", "focus_center", "Center"),
|
||||
("3", "focus_right", "Right"),
|
||||
("f", "cycle_filter", "Filter"),
|
||||
("p", "prev_page", "Prev Page"),
|
||||
("n", "next_page", "Next Page"),
|
||||
@@ -161,6 +182,7 @@ def launch_tui2(
|
||||
link_relation_filter: reactive[str] = reactive("all")
|
||||
editing_document: reactive[bool] = reactive(False)
|
||||
palette_open: reactive[bool] = reactive(False)
|
||||
help_open: reactive[bool] = reactive(False)
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(show_clock=True)
|
||||
@@ -176,13 +198,16 @@ def launch_tui2(
|
||||
id="command-palette",
|
||||
classes="hidden",
|
||||
)
|
||||
yield Static("", id="help-overlay", classes="hidden")
|
||||
with Horizontal(id="body"):
|
||||
with Vertical(id="left"):
|
||||
yield Static("", id="filters")
|
||||
yield Static("", id="activity")
|
||||
with Vertical(id="center"):
|
||||
yield Input(
|
||||
placeholder="Search entries (Enter to apply)", id="search"
|
||||
)
|
||||
yield Input(placeholder="Jump to entry id (Enter)", id="quick-jump")
|
||||
yield ListView(id="entry-list")
|
||||
with Vertical(id="right"):
|
||||
with Vertical(id="right-view"):
|
||||
@@ -223,6 +248,10 @@ def launch_tui2(
|
||||
self._current_link_cursor = 0
|
||||
self._last_error: str | None = None
|
||||
self._retry_action: Any | None = None
|
||||
self._activity_log: list[str] = []
|
||||
self._focus_pane = "center"
|
||||
self._doc_dirty = False
|
||||
self._doc_snapshot: dict[str, Any] = {}
|
||||
try:
|
||||
self._service = (
|
||||
entry_service_factory() if callable(entry_service_factory) else None
|
||||
@@ -239,10 +268,74 @@ def launch_tui2(
|
||||
f"Unable to initialize entry service: {exc}"
|
||||
)
|
||||
self._update_filters_panel()
|
||||
self._update_help_overlay()
|
||||
self._update_activity_panel()
|
||||
self._apply_focus_style()
|
||||
self._load_entries()
|
||||
|
||||
def _set_status(self, message: str) -> None:
|
||||
self.query_one("#status", Static).update(message)
|
||||
mode = (
|
||||
"PALETTE"
|
||||
if self.palette_open
|
||||
else ("EDIT" if self.editing_document else "VIEW")
|
||||
)
|
||||
text = f"[{mode} | {self._focus_pane.upper()}] {message}"
|
||||
self.query_one("#status", Static).update(text)
|
||||
self._log_activity(message)
|
||||
|
||||
def _log_activity(self, message: str) -> None:
|
||||
msg = message.strip()
|
||||
if not msg:
|
||||
return
|
||||
self._activity_log.append(msg)
|
||||
self._activity_log = self._activity_log[-5:]
|
||||
self._update_activity_panel()
|
||||
|
||||
def _update_activity_panel(self) -> None:
|
||||
if not self._activity_log:
|
||||
text = "Activity\n\nNo actions yet."
|
||||
else:
|
||||
lines = ["Activity", ""]
|
||||
for i, item in enumerate(reversed(self._activity_log), start=1):
|
||||
lines.append(f"{i}. {item}")
|
||||
text = "\n".join(lines)
|
||||
self.query_one("#activity", Static).update(text)
|
||||
|
||||
def _update_help_overlay(self) -> None:
|
||||
box = self.query_one("#help-overlay", Static)
|
||||
if not self.help_open:
|
||||
box.add_class("hidden")
|
||||
return
|
||||
box.remove_class("hidden")
|
||||
text = "\n".join(
|
||||
[
|
||||
"TUI v2 Quick Help",
|
||||
"",
|
||||
"Core: / search, j jump-id, p/n page, r refresh",
|
||||
"Modes: Ctrl+P palette, e edit-doc, Ctrl+S save, Esc cancel/close",
|
||||
"Graph: l relation filter, [/] link select, o open link target",
|
||||
"Resilience: x retry last error",
|
||||
"Pane Focus: 1 left, 2 center, 3 right",
|
||||
"",
|
||||
"Palette examples:",
|
||||
"help | filter document | open 12 | link-add 7 references note",
|
||||
]
|
||||
)
|
||||
box.update(text)
|
||||
|
||||
def _apply_focus_style(self) -> None:
|
||||
for pane_id in ("left", "center", "right"):
|
||||
pane = self.query_one(f"#{pane_id}", Vertical)
|
||||
if pane_id == self._focus_pane:
|
||||
pane.add_class("pane-focus")
|
||||
else:
|
||||
pane.remove_class("pane-focus")
|
||||
|
||||
def _refresh_doc_edit_help(self) -> None:
|
||||
marker = "*" if self._doc_dirty else "clean"
|
||||
self.query_one("#doc-edit-help", Static).update(
|
||||
f"Edit mode [{marker}]: Ctrl+S save, Esc cancel"
|
||||
)
|
||||
|
||||
def _record_failure(
|
||||
self,
|
||||
@@ -302,8 +395,11 @@ def launch_tui2(
|
||||
"",
|
||||
"Navigation:",
|
||||
"- / search",
|
||||
"- j jump to id",
|
||||
"- f cycle kind filter",
|
||||
"- p/n prev/next page",
|
||||
"- 1/2/3 focus pane",
|
||||
"- ? help overlay",
|
||||
"- r refresh",
|
||||
"- x retry last error",
|
||||
"",
|
||||
@@ -551,6 +647,8 @@ def launch_tui2(
|
||||
editor.add_class("hidden")
|
||||
view.remove_class("hidden")
|
||||
self.editing_document = visible
|
||||
self._focus_pane = "right"
|
||||
self._apply_focus_style()
|
||||
|
||||
def _set_palette_visible(self, visible: bool) -> None:
|
||||
palette = self.query_one("#command-palette", Input)
|
||||
@@ -561,6 +659,7 @@ def launch_tui2(
|
||||
palette.value = ""
|
||||
palette.add_class("hidden")
|
||||
self.palette_open = visible
|
||||
self._update_help_overlay()
|
||||
|
||||
def _get_document_editor_text(self) -> str:
|
||||
if TextArea is not None:
|
||||
@@ -578,6 +677,14 @@ def launch_tui2(
|
||||
return
|
||||
self.query_one("#doc-edit-content-single", Input).value = content
|
||||
|
||||
def _mark_doc_dirty(self, dirty: bool = True) -> None:
|
||||
if not self.editing_document:
|
||||
return
|
||||
if self._doc_dirty == dirty:
|
||||
return
|
||||
self._doc_dirty = dirty
|
||||
self._refresh_doc_edit_help()
|
||||
|
||||
def _run_palette_command(self, command: str) -> None:
|
||||
raw = command.strip()
|
||||
try:
|
||||
@@ -591,7 +698,7 @@ def launch_tui2(
|
||||
"Palette commands: help, open, search, filter, archive, "
|
||||
"restore, edit-doc, save-doc, cancel-edit, link-add, link-rm, "
|
||||
"link-filter, link-next, link-prev, link-open, page-next, "
|
||||
"page-prev, page <n>, retry"
|
||||
"page-prev, page <n>, retry, jump <id>"
|
||||
)
|
||||
return
|
||||
if cmd == "retry":
|
||||
@@ -609,6 +716,17 @@ def launch_tui2(
|
||||
return
|
||||
self._show_entry(entry_id)
|
||||
return
|
||||
if cmd == "jump":
|
||||
if len(args) != 1:
|
||||
self._set_status("Usage: jump <entry_id>")
|
||||
return
|
||||
try:
|
||||
entry_id = int(args[0])
|
||||
except ValueError:
|
||||
self._set_status("jump requires integer entry_id")
|
||||
return
|
||||
self._show_entry(entry_id)
|
||||
return
|
||||
|
||||
if cmd == "search":
|
||||
query = " ".join(args)
|
||||
@@ -789,6 +907,40 @@ def launch_tui2(
|
||||
self._update_filters_panel()
|
||||
self._load_entries(query=search, reset_page=False)
|
||||
|
||||
def action_toggle_help(self) -> None:
|
||||
if self.palette_open:
|
||||
self._set_palette_visible(False)
|
||||
self.help_open = not self.help_open
|
||||
self._update_help_overlay()
|
||||
self._set_status("Help opened" if self.help_open else "Help closed")
|
||||
|
||||
def action_focus_left(self) -> None:
|
||||
self._focus_pane = "left"
|
||||
self._apply_focus_style()
|
||||
self._set_status("Focused left pane")
|
||||
|
||||
def action_focus_center(self) -> None:
|
||||
self._focus_pane = "center"
|
||||
self._apply_focus_style()
|
||||
self.query_one("#search", Input).focus()
|
||||
self._set_status("Focused center pane")
|
||||
|
||||
def action_focus_right(self) -> None:
|
||||
self._focus_pane = "right"
|
||||
self._apply_focus_style()
|
||||
self._set_status("Focused right pane")
|
||||
|
||||
def action_focus_jump(self) -> None:
|
||||
if self.editing_document:
|
||||
self._set_status("Finish document edit before jumping")
|
||||
return
|
||||
if self.palette_open:
|
||||
self._set_palette_visible(False)
|
||||
self._focus_pane = "center"
|
||||
self._apply_focus_style()
|
||||
self.query_one("#quick-jump", Input).focus()
|
||||
self._set_status("Focused jump-to-id input")
|
||||
|
||||
def action_retry_last_error(self) -> None:
|
||||
retry = self._retry_action
|
||||
if retry is None:
|
||||
@@ -810,6 +962,8 @@ def launch_tui2(
|
||||
return
|
||||
if self.palette_open:
|
||||
self._set_palette_visible(False)
|
||||
self._focus_pane = "center"
|
||||
self._apply_focus_style()
|
||||
self.query_one("#search", Input).focus()
|
||||
|
||||
def action_cycle_filter(self) -> None:
|
||||
@@ -919,7 +1073,12 @@ def launch_tui2(
|
||||
if self.editing_document:
|
||||
self._set_status("Finish document edit before opening palette")
|
||||
return
|
||||
if self.help_open:
|
||||
self.help_open = False
|
||||
self._update_help_overlay()
|
||||
self._set_palette_visible(not self.palette_open)
|
||||
self._focus_pane = "center"
|
||||
self._apply_focus_style()
|
||||
if self.palette_open:
|
||||
self._set_status("Palette opened")
|
||||
else:
|
||||
@@ -980,7 +1139,15 @@ def launch_tui2(
|
||||
tags_text = ""
|
||||
self.query_one("#doc-edit-tags", Input).value = tags_text
|
||||
self._set_document_editor_text(str(entry.get("content", "")))
|
||||
self._doc_snapshot = {
|
||||
"label": str(entry.get("label", "")),
|
||||
"file_type": str(entry.get("file_type", "txt")).lstrip("."),
|
||||
"tags": tags_text,
|
||||
"content": str(entry.get("content", "")),
|
||||
}
|
||||
self._doc_dirty = False
|
||||
self._set_document_editor_visible(True)
|
||||
self._refresh_doc_edit_help()
|
||||
if TextArea is not None:
|
||||
self.query_one("#doc-edit-content").focus()
|
||||
else:
|
||||
@@ -1002,6 +1169,17 @@ def launch_tui2(
|
||||
tags_raw = self.query_one("#doc-edit-tags", Input).value.strip()
|
||||
tags = [part.strip() for part in tags_raw.split(",") if part.strip()]
|
||||
content = self._get_document_editor_text()
|
||||
current_form = {
|
||||
"label": label,
|
||||
"file_type": file_type,
|
||||
"tags": tags_raw,
|
||||
"content": content,
|
||||
}
|
||||
self._doc_dirty = current_form != self._doc_snapshot
|
||||
self._refresh_doc_edit_help()
|
||||
if not self._doc_dirty:
|
||||
self._set_status("No document changes to save")
|
||||
return
|
||||
|
||||
try:
|
||||
self._service.modify_entry(
|
||||
@@ -1013,6 +1191,7 @@ def launch_tui2(
|
||||
)
|
||||
current_id = self._selected_entry_id
|
||||
self._set_document_editor_visible(False)
|
||||
self._doc_dirty = False
|
||||
self._load_entries(self._last_query, reset_page=False)
|
||||
if current_id in self._entry_ids_in_view:
|
||||
self._show_entry(current_id)
|
||||
@@ -1031,11 +1210,29 @@ def launch_tui2(
|
||||
self._set_palette_visible(False)
|
||||
self._set_status("Palette closed")
|
||||
return
|
||||
if self.help_open:
|
||||
self.help_open = False
|
||||
self._update_help_overlay()
|
||||
self._set_status("Help closed")
|
||||
return
|
||||
if not self.editing_document:
|
||||
return
|
||||
self._set_document_editor_visible(False)
|
||||
self._doc_dirty = False
|
||||
self._set_status("Canceled document edit")
|
||||
|
||||
def on_input_changed(self, event: Input.Changed) -> None:
|
||||
if event.input.id in {
|
||||
"doc-edit-label",
|
||||
"doc-edit-file-type",
|
||||
"doc-edit-tags",
|
||||
"doc-edit-content-single",
|
||||
}:
|
||||
self._mark_doc_dirty(True)
|
||||
|
||||
def on_text_area_changed(self, _event: Any) -> None:
|
||||
self._mark_doc_dirty(True)
|
||||
|
||||
def on_input_submitted(self, event: Input.Submitted) -> None:
|
||||
if event.input.id == "search":
|
||||
if self.editing_document:
|
||||
@@ -1043,6 +1240,18 @@ def launch_tui2(
|
||||
return
|
||||
self._load_entries(query=event.value.strip(), reset_page=True)
|
||||
return
|
||||
if event.input.id == "quick-jump":
|
||||
raw = event.value.strip()
|
||||
if not raw:
|
||||
self._set_status("Jump requires an entry id")
|
||||
return
|
||||
try:
|
||||
entry_id = int(raw)
|
||||
except ValueError:
|
||||
self._set_status("Jump requires an integer entry id")
|
||||
return
|
||||
self._show_entry(entry_id)
|
||||
return
|
||||
if event.input.id == "command-palette":
|
||||
command = event.value
|
||||
self._set_palette_visible(False)
|
||||
@@ -1052,6 +1261,8 @@ def launch_tui2(
|
||||
if self.editing_document:
|
||||
self._set_status("Finish document edit before selecting another entry")
|
||||
return
|
||||
self._focus_pane = "center"
|
||||
self._apply_focus_style()
|
||||
item = event.item
|
||||
if isinstance(item, EntryListItem):
|
||||
self._show_entry(item.entry_index)
|
||||
|
||||
@@ -100,15 +100,19 @@ def _build_app(service: FakeEntryService):
|
||||
return app
|
||||
|
||||
|
||||
async def _run_palette(pilot, command: str) -> None:
|
||||
await pilot.press("ctrl+p")
|
||||
await pilot.type(command)
|
||||
await pilot.press("enter")
|
||||
def _widget_text(app, selector: str) -> str:
|
||||
return str(app.query_one(selector).render())
|
||||
|
||||
|
||||
async def _run_palette(app, pilot, command: str) -> None:
|
||||
app.action_open_palette()
|
||||
await pilot.pause()
|
||||
app._run_palette_command(command)
|
||||
await pilot.pause()
|
||||
|
||||
|
||||
def _status_text(app) -> str:
|
||||
return str(app.query_one("#status", Static).renderable)
|
||||
return _widget_text(app, "#status")
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
@@ -136,12 +140,12 @@ async def test_tui2_parity_filters_cover_all_entry_kinds() -> None:
|
||||
assert len(list_view.children) == len(kinds)
|
||||
|
||||
for kind in kinds:
|
||||
await _run_palette(pilot, f"filter {kind}")
|
||||
await _run_palette(app, pilot, f"filter {kind}")
|
||||
assert len(list_view.children) == 1
|
||||
detail_text = str(app.query_one("#entry-detail", Static).renderable)
|
||||
detail_text = _widget_text(app, "#entry-detail")
|
||||
assert f'"kind": "{kind}"' in detail_text
|
||||
|
||||
await _run_palette(pilot, "filter all")
|
||||
await _run_palette(app, pilot, "filter all")
|
||||
assert len(list_view.children) == len(kinds)
|
||||
|
||||
|
||||
@@ -154,11 +158,11 @@ async def test_tui2_parity_archive_restore_roundtrip_non_document() -> None:
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
await _run_palette(pilot, "archive")
|
||||
await _run_palette(app, pilot, "archive")
|
||||
assert service.retrieve_entry(1)["archived"] is True
|
||||
assert "archived" in _status_text(app)
|
||||
|
||||
await _run_palette(pilot, "restore")
|
||||
await _run_palette(app, pilot, "restore")
|
||||
assert service.retrieve_entry(1)["archived"] is False
|
||||
assert "restored" in _status_text(app)
|
||||
|
||||
@@ -169,6 +173,6 @@ async def test_tui2_parity_edit_document_guard_for_non_document() -> None:
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
await pilot.press("e")
|
||||
app.action_edit_document()
|
||||
await pilot.pause()
|
||||
assert "Select a document entry to edit" in _status_text(app)
|
||||
@@ -111,18 +111,23 @@ def _build_app(service: FakeEntryService):
|
||||
return app
|
||||
|
||||
|
||||
def _widget_text(app, selector: str) -> str:
|
||||
return str(app.query_one(selector).render())
|
||||
|
||||
|
||||
def _status_text(app) -> str:
|
||||
return str(app.query_one("#status", Static).renderable)
|
||||
return _widget_text(app, "#status")
|
||||
|
||||
|
||||
def _filters_text(app) -> str:
|
||||
return str(app.query_one("#filters", Static).renderable)
|
||||
return _widget_text(app, "#filters")
|
||||
|
||||
|
||||
async def _run_palette(pilot, command: str) -> None:
|
||||
await pilot.press("ctrl+p")
|
||||
await pilot.type(command)
|
||||
await pilot.press("enter")
|
||||
async def _run_palette(app, pilot, command: str) -> None:
|
||||
app.action_open_palette()
|
||||
await pilot.pause()
|
||||
app._run_palette_command(command)
|
||||
app._set_palette_visible(False)
|
||||
await pilot.pause()
|
||||
|
||||
|
||||
@@ -140,13 +145,12 @@ async def test_tui2_textual_pagination_and_search_flow() -> None:
|
||||
assert len(list_view.children) == 200
|
||||
assert "Page: 1/3" in _filters_text(app)
|
||||
|
||||
await pilot.press("n")
|
||||
app.action_next_page()
|
||||
await pilot.pause()
|
||||
assert "Page: 2/3" in _filters_text(app)
|
||||
|
||||
await pilot.press("/")
|
||||
await pilot.type("Entry 44")
|
||||
await pilot.press("enter")
|
||||
app.query_one("#search", Input).value = "Entry 44"
|
||||
app._load_entries(query="Entry 44", reset_page=True)
|
||||
await pilot.pause()
|
||||
assert len(list_view.children) == 11
|
||||
assert "Page: 1/1" in _filters_text(app)
|
||||
@@ -170,7 +174,7 @@ async def test_tui2_textual_document_edit_save_flow() -> None:
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
await pilot.press("e")
|
||||
app.action_edit_document()
|
||||
await pilot.pause()
|
||||
|
||||
app.query_one("#doc-edit-label", Input).value = "Doc A Updated"
|
||||
@@ -185,7 +189,7 @@ async def test_tui2_textual_document_edit_save_flow() -> None:
|
||||
else:
|
||||
app.query_one("#doc-edit-content-single", Input).value = "new content"
|
||||
|
||||
await pilot.press("ctrl+s")
|
||||
app.action_save_document()
|
||||
await pilot.pause()
|
||||
|
||||
entry = service.retrieve_entry(1)
|
||||
@@ -208,16 +212,16 @@ async def test_tui2_textual_link_commands_and_neighbor_open() -> None:
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.pause()
|
||||
|
||||
await _run_palette(pilot, "link-add 2 references rel-note")
|
||||
links_text = str(app.query_one("#link-detail", Static).renderable)
|
||||
await _run_palette(app, pilot, "link-add 2 references rel-note")
|
||||
links_text = _widget_text(app, "#link-detail")
|
||||
assert "references -> 2 (rel-note)" in links_text
|
||||
|
||||
await pilot.press("o")
|
||||
app.action_open_link_target()
|
||||
await pilot.pause()
|
||||
assert "Opened linked entry 2" in _status_text(app)
|
||||
|
||||
await _run_palette(pilot, "link-rm 2 references")
|
||||
links_text = str(app.query_one("#link-detail", Static).renderable)
|
||||
await _run_palette(app, pilot, "link-rm 2 references")
|
||||
links_text = _widget_text(app, "#link-detail")
|
||||
assert "No graph links" in links_text
|
||||
|
||||
|
||||
@@ -233,7 +237,7 @@ async def test_tui2_textual_retry_after_search_failure() -> None:
|
||||
await pilot.pause()
|
||||
assert "Failed to load entries" in _status_text(app)
|
||||
|
||||
await pilot.press("x")
|
||||
app.action_retry_last_error()
|
||||
await pilot.pause()
|
||||
|
||||
list_view = app.query_one("#entry-list", ListView)
|
||||
|
||||
Reference in new issue
Block a user