c26e9eacfa
- Delete dead repo-workspace code: RepoWorkspacePage, useRepoWorkspace, WorkspaceLayout, FileBrowser, old git components (git-toolbar, file-editor, commit-panel), and repo-workspace.css. - Fix stale backend test imports for moved models/services. - Add GitOperations unit tests. - Add integration tests for workspace files, git, and instances endpoints. - Add frontend tests for WorkspaceDetailPage and ProjectCard. - Update OpenSpec workspace-first-ui tasks and mark change completed. - Regenerate project maps. Quality gates: npm run typecheck, npm run lint, npm test -- --run (87 passed), python3 -m py_compile on changed backend files, pytest backend workspace tests.
134 lines
4.3 KiB
Python
134 lines
4.3 KiB
Python
"""Unit tests for GitOperations."""
|
|
|
|
import asyncio
|
|
import os
|
|
import subprocess
|
|
import tempfile
|
|
|
|
import pytest
|
|
|
|
from src.models import Workspace
|
|
from src.services.git.git_operations import GitOperations
|
|
|
|
|
|
def _run_git(*args: str, cwd: str) -> None:
|
|
subprocess.run(["git", *args], cwd=cwd, check=True, capture_output=True)
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_workspace():
|
|
"""Create a temporary git workspace."""
|
|
with tempfile.TemporaryDirectory() as tmpdir:
|
|
_run_git("init", cwd=tmpdir)
|
|
_run_git("config", "user.email", "test@test.com", cwd=tmpdir)
|
|
_run_git("config", "user.name", "Test User", cwd=tmpdir)
|
|
|
|
readme = os.path.join(tmpdir, "README.md")
|
|
with open(readme, "w") as f:
|
|
f.write("# Test\n")
|
|
_run_git("add", "README.md", cwd=tmpdir)
|
|
_run_git("commit", "-m", "Initial commit", cwd=tmpdir)
|
|
|
|
ws = Workspace(
|
|
id="00000000-0000-0000-0000-000000000001",
|
|
name="test-ws",
|
|
repo_id="00000000-0000-0000-0000-000000000002",
|
|
user_id="00000000-0000-0000-0000-000000000003",
|
|
branch="main",
|
|
path=tmpdir,
|
|
)
|
|
yield ws
|
|
|
|
|
|
class TestGitOperationsStatus:
|
|
"""Tests for GitOperations.status."""
|
|
|
|
def test_status_clean(self, temp_workspace: Workspace):
|
|
git = GitOperations(temp_workspace)
|
|
status = asyncio.run(git.status())
|
|
assert status.branch == "main"
|
|
assert status.modified == []
|
|
assert status.added == []
|
|
assert status.deleted == []
|
|
assert status.untracked == []
|
|
|
|
def test_status_modified(self, temp_workspace: Workspace):
|
|
with open(os.path.join(temp_workspace.path, "README.md"), "a") as f:
|
|
f.write("modified\n")
|
|
|
|
git = GitOperations(temp_workspace)
|
|
status = asyncio.run(git.status())
|
|
assert "README.md" in status.modified
|
|
|
|
def test_status_untracked(self, temp_workspace: Workspace):
|
|
with open(os.path.join(temp_workspace.path, "new.py"), "w") as f:
|
|
f.write("print('hello')\n")
|
|
|
|
git = GitOperations(temp_workspace)
|
|
status = asyncio.run(git.status())
|
|
assert "new.py" in status.untracked
|
|
|
|
|
|
class TestGitOperationsCommit:
|
|
"""Tests for GitOperations.commit."""
|
|
|
|
def test_commit_stages_and_commits(self, temp_workspace: Workspace):
|
|
with open(os.path.join(temp_workspace.path, "new.py"), "w") as f:
|
|
f.write("print('hello')\n")
|
|
|
|
git = GitOperations(temp_workspace)
|
|
asyncio.run(git.commit("Add new file"))
|
|
|
|
status = asyncio.run(git.status())
|
|
assert "new.py" not in status.untracked
|
|
assert "new.py" not in status.added
|
|
|
|
history = asyncio.run(git.history())
|
|
assert history[0].message == "Add new file"
|
|
|
|
def test_commit_fails_without_changes(self, temp_workspace: Workspace):
|
|
git = GitOperations(temp_workspace)
|
|
with pytest.raises(RuntimeError):
|
|
asyncio.run(git.commit("Nothing to commit"))
|
|
|
|
|
|
class TestGitOperationsHistory:
|
|
"""Tests for GitOperations.history."""
|
|
|
|
def test_history_returns_commits(self, temp_workspace: Workspace):
|
|
git = GitOperations(temp_workspace)
|
|
history = asyncio.run(git.history())
|
|
assert len(history) >= 1
|
|
assert history[0].message == "Initial commit"
|
|
|
|
def test_history_filters_by_path(self, temp_workspace: Workspace):
|
|
with open(os.path.join(temp_workspace.path, "new.py"), "w") as f:
|
|
f.write("print('hello')\n")
|
|
|
|
git = GitOperations(temp_workspace)
|
|
asyncio.run(git.commit("Add new file"))
|
|
|
|
history = asyncio.run(git.history(path="new.py"))
|
|
assert len(history) == 1
|
|
assert history[0].message == "Add new file"
|
|
|
|
|
|
class TestGitOperationsBranches:
|
|
"""Tests for GitOperations.branches."""
|
|
|
|
def test_branches_lists_main(self, temp_workspace: Workspace):
|
|
git = GitOperations(temp_workspace)
|
|
branches, current = asyncio.run(git.branches())
|
|
assert "main" in branches
|
|
assert current == "main"
|
|
|
|
def test_checkout_switches_branch(self, temp_workspace: Workspace):
|
|
_run_git("checkout", "-b", "feature", cwd=temp_workspace.path)
|
|
_run_git("checkout", "main", cwd=temp_workspace.path)
|
|
|
|
git = GitOperations(temp_workspace)
|
|
asyncio.run(git.checkout("feature"))
|
|
|
|
status = asyncio.run(git.status())
|
|
assert status.branch == "feature"
|