Merge branch 'main' into worktree-sessions

# Conflicts:
#	src/hqt/sessions/service.py
#	tests/test_sessions.py
This commit is contained in:
2026-06-10 21:07:20 -04:00
14 changed files with 1826 additions and 133 deletions
+45 -18
View File
@@ -626,12 +626,12 @@ async def test_project_form_add_mode_defaults_name_to_basename():
@pytest.mark.asyncio
async def test_project_list_get_selected_project_id():
async def test_project_list_get_selected_project_id(tmp_path):
app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot:
from hqt.tui.widgets.project_list import ProjectList
p = app._project_service.create("selproj", "/tmp/selproj")
p = app._project_service.create("selproj", str(tmp_path))
app._load_projects()
await app.workers.wait_for_complete()
await pilot.pause()
@@ -676,14 +676,22 @@ async def test_edit_project_no_selection_warns():
@pytest.mark.asyncio
async def test_edit_project_opens_prefilled_form_and_updates():
async def test_edit_project_opens_prefilled_form_and_updates(tmp_path):
app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot:
from pathlib import Path
from textual.widgets import Input
from hqt.tui.screens.project_form import ProjectFormScreen
from hqt.tui.widgets.project_list import ProjectList
p = app._project_service.create("oldname", "/tmp/oldpath")
old_dir = tmp_path / "oldpath"
old_dir.mkdir()
new_dir = tmp_path / "newpath"
new_dir.mkdir()
old_path = str(old_dir)
new_path = str(new_dir)
p = app._project_service.create("oldname", old_path)
app._load_projects()
await app.workers.wait_for_complete()
await pilot.pause()
@@ -699,25 +707,35 @@ async def test_edit_project_opens_prefilled_form_and_updates():
assert isinstance(app.screen, ProjectFormScreen)
assert app.screen.query_one("#name-input", Input).value == "oldname"
assert app.screen.query_one("#path-input", Input).value == "/tmp/oldpath"
assert app.screen.query_one("#path-input", Input).value == str(
Path(old_path).resolve()
)
app.screen.dismiss(("newname", "/tmp/newpath"))
app.screen.dismiss(("newname", new_path))
await pilot.pause()
refreshed = app._project_service.get(p.id)
assert refreshed.name == "newname"
assert refreshed.path == "/tmp/newpath"
assert refreshed.path == str(Path(new_path).resolve())
@pytest.mark.asyncio
async def test_edit_project_duplicate_path_notifies_error():
async def test_edit_project_duplicate_path_notifies_error(tmp_path):
app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot:
from pathlib import Path
from unittest.mock import patch
from hqt.tui.widgets.project_list import ProjectList
app._project_service.create("first", "/tmp/first")
p2 = app._project_service.create("second", "/tmp/second")
first_dir = tmp_path / "first"
first_dir.mkdir()
second_dir = tmp_path / "second"
second_dir.mkdir()
first_path = str(first_dir)
second_path = str(second_dir)
app._project_service.create("first", first_path)
p2 = app._project_service.create("second", second_path)
app._load_projects()
await app.workers.wait_for_complete()
await pilot.pause()
@@ -736,7 +754,8 @@ async def test_edit_project_duplicate_path_notifies_error():
):
await app.run_action("edit_project")
await pilot.pause()
app.screen.dismiss(("second", "/tmp/first"))
# Move "second" onto "first"'s path to trigger the duplicate error.
app.screen.dismiss(("second", first_path))
await pilot.pause()
assert any(
@@ -744,7 +763,7 @@ async def test_edit_project_duplicate_path_notifies_error():
for msg, kw in notify_calls
), f"Expected duplicate-path error notification, got: {notify_calls}"
# DB unchanged
assert app._project_service.get(p2.id).path == "/tmp/second"
assert app._project_service.get(p2.id).path == str(Path(second_path).resolve())
# ---------------------------------------------------------------------------
@@ -889,14 +908,18 @@ async def test_dialog_button_focus_is_visibly_highlighted():
@pytest.mark.asyncio
async def test_first_project_selected_on_load():
async def test_first_project_selected_on_load(tmp_path):
"""If a project exists, the first is selected on load with no key press."""
app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot:
from hqt.tui.widgets.project_list import ProjectList
app._project_service.create("p1", "/tmp/p1-auto")
app._project_service.create("p2", "/tmp/p2-auto")
d1 = tmp_path / "p1-auto"
d1.mkdir()
d2 = tmp_path / "p2-auto"
d2.mkdir()
app._project_service.create("p1", str(d1))
app._project_service.create("p2", str(d2))
app._load_projects()
await app.workers.wait_for_complete()
await pilot.pause()
@@ -1159,14 +1182,18 @@ async def test_rename_session_opens_prefilled_and_updates():
@pytest.mark.asyncio
async def test_project_list_jk_navigation():
async def test_project_list_jk_navigation(tmp_path):
"""j/k move the highlight down/up in the project list like the arrow keys."""
app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot:
from hqt.tui.widgets.project_list import ProjectList
p1 = app._project_service.create("first", "/tmp/jk-first")
p2 = app._project_service.create("second", "/tmp/jk-second")
d1 = tmp_path / "jk-first"
d1.mkdir()
d2 = tmp_path / "jk-second"
d2.mkdir()
p1 = app._project_service.create("first", str(d1))
p2 = app._project_service.create("second", str(d2))
app._load_projects()
await app.workers.wait_for_complete()
await pilot.pause()