test_setup.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import subprocess
  2. from pathlib import Path
  3. from unittest.mock import call, patch
  4. import pytest
  5. from drill.setup import clone_template, run_assertions
  6. from setup_helpers.base import create_base_repo
  7. from setup_helpers.spec_writing_blind_spot import create_spec_writing_blind_spot
  8. from setup_helpers.worktree import (
  9. add_worktree,
  10. create_caller_consent_plan,
  11. detach_head,
  12. link_gemini_extension,
  13. symlink_superpowers,
  14. )
  15. @pytest.fixture
  16. def fixtures_dir():
  17. return Path(__file__).parent.parent / "fixtures"
  18. @pytest.fixture
  19. def work_dir(tmp_path):
  20. return tmp_path / "test-repo"
  21. class TestCloneTemplate:
  22. def test_clones_template_repo(self, fixtures_dir, work_dir):
  23. clone_template(fixtures_dir / "template-repo", work_dir)
  24. assert (work_dir / "package.json").exists()
  25. assert (work_dir / "src" / "index.js").exists()
  26. result = subprocess.run(
  27. ["git", "log", "--oneline"],
  28. cwd=work_dir,
  29. capture_output=True,
  30. text=True,
  31. )
  32. assert "initial commit" in result.stdout
  33. class TestCreateBaseRepo:
  34. def test_creates_base_repo(self, fixtures_dir, work_dir):
  35. create_base_repo(work_dir, fixtures_dir / "template-repo")
  36. assert (work_dir / "package.json").exists()
  37. result = subprocess.run(
  38. ["git", "branch", "--show-current"],
  39. cwd=work_dir,
  40. capture_output=True,
  41. text=True,
  42. )
  43. assert result.stdout.strip() == "main"
  44. class TestWorktreeHelpers:
  45. def test_add_worktree(self, fixtures_dir, work_dir):
  46. create_base_repo(work_dir, fixtures_dir / "template-repo")
  47. wt_path = work_dir.parent / "feature-wt"
  48. add_worktree(work_dir, "feature-branch", str(wt_path))
  49. assert wt_path.exists()
  50. result = subprocess.run(
  51. ["git", "worktree", "list"],
  52. cwd=work_dir,
  53. capture_output=True,
  54. text=True,
  55. )
  56. assert "feature-branch" in result.stdout
  57. def test_detach_head(self, fixtures_dir, work_dir):
  58. create_base_repo(work_dir, fixtures_dir / "template-repo")
  59. wt_path = work_dir.parent / "detached-wt"
  60. add_worktree(work_dir, "tmp-branch", str(wt_path))
  61. detach_head(str(wt_path))
  62. result = subprocess.run(
  63. ["git", "branch", "--show-current"],
  64. cwd=wt_path,
  65. capture_output=True,
  66. text=True,
  67. )
  68. assert result.stdout.strip() == ""
  69. def test_symlink_superpowers(self, fixtures_dir, work_dir, tmp_path):
  70. create_base_repo(work_dir, fixtures_dir / "template-repo")
  71. fake_sp = tmp_path / "superpowers" / "skills"
  72. fake_sp.mkdir(parents=True)
  73. symlink_superpowers(work_dir, str(tmp_path / "superpowers"))
  74. link = work_dir / ".agents" / "skills" / "superpowers"
  75. assert link.is_symlink()
  76. def test_link_gemini_extension_relinks_requested_root(self, work_dir, tmp_path):
  77. work_dir.mkdir()
  78. fake_sp = tmp_path / "superpowers"
  79. (fake_sp / "skills" / "using-superpowers" / "references").mkdir(parents=True)
  80. (fake_sp / "gemini-extension.json").write_text('{"name": "custom-superpowers"}')
  81. with patch("setup_helpers.worktree.subprocess.run") as run:
  82. link_gemini_extension(work_dir, str(fake_sp))
  83. assert run.call_args_list == [
  84. call(["gemini", "extensions", "uninstall", "custom-superpowers"], capture_output=True),
  85. call(
  86. ["gemini", "extensions", "link", str(fake_sp)],
  87. capture_output=True,
  88. input="y\n",
  89. text=True,
  90. check=True,
  91. ),
  92. ]
  93. assert (work_dir / "GEMINI.md").read_text() == (
  94. f"@{fake_sp}/skills/using-superpowers/SKILL.md\n"
  95. f"@{fake_sp}/skills/using-superpowers/references/gemini-tools.md\n"
  96. )
  97. def test_create_caller_consent_plan(self, fixtures_dir, work_dir):
  98. create_base_repo(work_dir, fixtures_dir / "template-repo")
  99. create_caller_consent_plan(work_dir)
  100. plan = work_dir / "docs" / "superpowers" / "plans" / "custom-greeting.md"
  101. assert plan.exists()
  102. assert "REQUIRED SUB-SKILL" in plan.read_text()
  103. result = subprocess.run(
  104. ["git", "status", "--short"],
  105. cwd=work_dir,
  106. capture_output=True,
  107. text=True,
  108. )
  109. assert result.stdout.strip() == ""
  110. class TestSpecWritingBlindSpot:
  111. def test_creates_repo_structure(self, tmp_path):
  112. workdir = tmp_path / "blind-spot-repo"
  113. create_spec_writing_blind_spot(workdir)
  114. assert (workdir / "src" / "components" / "AdminPanel.tsx").exists()
  115. assert (workdir / "src" / "components" / "TeamOverview.tsx").exists()
  116. assert (workdir / "src" / "router.tsx").exists()
  117. assert (workdir / "CLAUDE.md").exists()
  118. assert not (workdir / "src" / "components" / "ActivityFeed.tsx").exists()
  119. result = subprocess.run(
  120. ["git", "branch", "--show-current"],
  121. cwd=workdir,
  122. capture_output=True,
  123. text=True,
  124. )
  125. assert result.stdout.strip() == "main"
  126. result = subprocess.run(
  127. ["git", "log", "--oneline"],
  128. cwd=workdir,
  129. capture_output=True,
  130. text=True,
  131. )
  132. assert result.stdout.count("\n") >= 3
  133. class TestRunAssertions:
  134. def test_passing_assertions(self, fixtures_dir, work_dir):
  135. create_base_repo(work_dir, fixtures_dir / "template-repo")
  136. assertions = [
  137. "git rev-parse --is-inside-work-tree",
  138. "git branch --show-current | grep main",
  139. ]
  140. run_assertions(assertions, work_dir)
  141. def test_failing_assertion_raises(self, fixtures_dir, work_dir):
  142. create_base_repo(work_dir, fixtures_dir / "template-repo")
  143. with pytest.raises(AssertionError, match="Setup assertion failed"):
  144. run_assertions(["git branch --show-current | grep nonexistent"], work_dir)