test: use real directories in TUI/integration project tests

ProjectService now rejects non-existent paths (path-validation feature), so
the TUI and integration tests must seed projects with real tmp_path dirs.
Completes the path-validation test updates beyond test_services.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 21:01:54 -04:00
parent d78d8ee149
commit f796590746
2 changed files with 47 additions and 20 deletions
+2 -2
View File
@@ -43,11 +43,11 @@ def setup():
@pytest.mark.asyncio @pytest.mark.asyncio
async def test_full_lifecycle(setup): async def test_full_lifecycle(setup, tmp_path):
proj_svc, sess_svc, tmux = setup proj_svc, sess_svc, tmux = setup
# Create project # Create project
project = proj_svc.create(name="test-proj", path="/tmp/test-proj") project = proj_svc.create(name="test-proj", path=str(tmp_path))
assert project.id == 1 assert project.id == 1
# Create session # Create session
+45 -18
View File
@@ -619,12 +619,12 @@ async def test_project_form_add_mode_defaults_name_to_basename():
@pytest.mark.asyncio @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() app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot: async with app.run_test(size=(120, 40)) as pilot:
from hqt.tui.widgets.project_list import ProjectList 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() app._load_projects()
await app.workers.wait_for_complete() await app.workers.wait_for_complete()
await pilot.pause() await pilot.pause()
@@ -669,14 +669,22 @@ async def test_edit_project_no_selection_warns():
@pytest.mark.asyncio @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() app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot: async with app.run_test(size=(120, 40)) as pilot:
from pathlib import Path
from textual.widgets import Input from textual.widgets import Input
from hqt.tui.screens.project_form import ProjectFormScreen from hqt.tui.screens.project_form import ProjectFormScreen
from hqt.tui.widgets.project_list import ProjectList 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() app._load_projects()
await app.workers.wait_for_complete() await app.workers.wait_for_complete()
await pilot.pause() await pilot.pause()
@@ -692,25 +700,35 @@ async def test_edit_project_opens_prefilled_form_and_updates():
assert isinstance(app.screen, ProjectFormScreen) assert isinstance(app.screen, ProjectFormScreen)
assert app.screen.query_one("#name-input", Input).value == "oldname" 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() await pilot.pause()
refreshed = app._project_service.get(p.id) refreshed = app._project_service.get(p.id)
assert refreshed.name == "newname" assert refreshed.name == "newname"
assert refreshed.path == "/tmp/newpath" assert refreshed.path == str(Path(new_path).resolve())
@pytest.mark.asyncio @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() app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot: async with app.run_test(size=(120, 40)) as pilot:
from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
from hqt.tui.widgets.project_list import ProjectList from hqt.tui.widgets.project_list import ProjectList
app._project_service.create("first", "/tmp/first") first_dir = tmp_path / "first"
p2 = app._project_service.create("second", "/tmp/second") 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() app._load_projects()
await app.workers.wait_for_complete() await app.workers.wait_for_complete()
await pilot.pause() await pilot.pause()
@@ -729,7 +747,8 @@ async def test_edit_project_duplicate_path_notifies_error():
): ):
await app.run_action("edit_project") await app.run_action("edit_project")
await pilot.pause() 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() await pilot.pause()
assert any( assert any(
@@ -737,7 +756,7 @@ async def test_edit_project_duplicate_path_notifies_error():
for msg, kw in notify_calls for msg, kw in notify_calls
), f"Expected duplicate-path error notification, got: {notify_calls}" ), f"Expected duplicate-path error notification, got: {notify_calls}"
# DB unchanged # 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())
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -882,14 +901,18 @@ async def test_dialog_button_focus_is_visibly_highlighted():
@pytest.mark.asyncio @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.""" """If a project exists, the first is selected on load with no key press."""
app = HqtApp() app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot: async with app.run_test(size=(120, 40)) as pilot:
from hqt.tui.widgets.project_list import ProjectList from hqt.tui.widgets.project_list import ProjectList
app._project_service.create("p1", "/tmp/p1-auto") d1 = tmp_path / "p1-auto"
app._project_service.create("p2", "/tmp/p2-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() app._load_projects()
await app.workers.wait_for_complete() await app.workers.wait_for_complete()
await pilot.pause() await pilot.pause()
@@ -1152,14 +1175,18 @@ async def test_rename_session_opens_prefilled_and_updates():
@pytest.mark.asyncio @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.""" """j/k move the highlight down/up in the project list like the arrow keys."""
app = HqtApp() app = HqtApp()
async with app.run_test(size=(120, 40)) as pilot: async with app.run_test(size=(120, 40)) as pilot:
from hqt.tui.widgets.project_list import ProjectList from hqt.tui.widgets.project_list import ProjectList
p1 = app._project_service.create("first", "/tmp/jk-first") d1 = tmp_path / "jk-first"
p2 = app._project_service.create("second", "/tmp/jk-second") 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() app._load_projects()
await app.workers.wait_for_complete() await app.workers.wait_for_complete()
await pilot.pause() await pilot.pause()