test_project_locator.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. import sys
  4. from pathlib import Path
  5. def _ensure_scripts_on_path() -> None:
  6. scripts_dir = Path(__file__).resolve().parents[2]
  7. if str(scripts_dir) not in sys.path:
  8. sys.path.insert(0, str(scripts_dir))
  9. def test_resolve_project_root_prefers_cwd_project(tmp_path):
  10. _ensure_scripts_on_path()
  11. from project_locator import resolve_project_root
  12. project_root = tmp_path / "workspace"
  13. (project_root / ".webnovel").mkdir(parents=True, exist_ok=True)
  14. (project_root / ".webnovel" / "state.json").write_text("{}", encoding="utf-8")
  15. resolved = resolve_project_root(cwd=project_root)
  16. assert resolved == project_root.resolve()
  17. def test_resolve_project_root_stops_at_git_root(tmp_path):
  18. _ensure_scripts_on_path()
  19. from project_locator import resolve_project_root
  20. repo_root = tmp_path / "repo"
  21. (repo_root / ".git").mkdir(parents=True, exist_ok=True)
  22. nested = repo_root / "sub" / "dir"
  23. nested.mkdir(parents=True, exist_ok=True)
  24. outside_project = tmp_path / "outside_project"
  25. (outside_project / ".webnovel").mkdir(parents=True, exist_ok=True)
  26. (outside_project / ".webnovel" / "state.json").write_text("{}", encoding="utf-8")
  27. try:
  28. resolve_project_root(cwd=nested)
  29. assert False, "Expected FileNotFoundError when only parent outside git root has project"
  30. except FileNotFoundError:
  31. pass
  32. def test_resolve_project_root_finds_default_subdir_within_git_root(tmp_path):
  33. _ensure_scripts_on_path()
  34. from project_locator import resolve_project_root
  35. repo_root = tmp_path / "repo"
  36. (repo_root / ".git").mkdir(parents=True, exist_ok=True)
  37. default_project = repo_root / "webnovel-project"
  38. (default_project / ".webnovel").mkdir(parents=True, exist_ok=True)
  39. (default_project / ".webnovel" / "state.json").write_text("{}", encoding="utf-8")
  40. nested = repo_root / "sub" / "dir"
  41. nested.mkdir(parents=True, exist_ok=True)
  42. resolved = resolve_project_root(cwd=nested)
  43. assert resolved == default_project.resolve()
  44. def test_resolve_project_root_uses_workspace_pointer(tmp_path):
  45. _ensure_scripts_on_path()
  46. from project_locator import resolve_project_root, write_current_project_pointer
  47. workspace = tmp_path / "workspace"
  48. (workspace / ".claude").mkdir(parents=True, exist_ok=True)
  49. project_root = workspace / "凡人资本论"
  50. (project_root / ".webnovel").mkdir(parents=True, exist_ok=True)
  51. (project_root / ".webnovel" / "state.json").write_text("{}", encoding="utf-8")
  52. pointer_file = write_current_project_pointer(project_root, workspace_root=workspace)
  53. assert pointer_file is not None
  54. assert pointer_file.is_file()
  55. resolved = resolve_project_root(cwd=workspace)
  56. assert resolved == project_root.resolve()
  57. def test_resolve_project_root_ignores_stale_pointer_and_fallbacks(tmp_path):
  58. _ensure_scripts_on_path()
  59. from project_locator import resolve_project_root
  60. workspace = tmp_path / "workspace"
  61. (workspace / ".claude").mkdir(parents=True, exist_ok=True)
  62. # stale pointer
  63. (workspace / ".claude" / ".webnovel-current-project").write_text(
  64. str(workspace / "missing-project"), encoding="utf-8"
  65. )
  66. default_project = workspace / "webnovel-project"
  67. (default_project / ".webnovel").mkdir(parents=True, exist_ok=True)
  68. (default_project / ".webnovel" / "state.json").write_text("{}", encoding="utf-8")
  69. resolved = resolve_project_root(cwd=workspace)
  70. assert resolved == default_project.resolve()