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.
85 lines
3.1 KiB
Python
85 lines
3.1 KiB
Python
"""Unit tests for FileService."""
|
|
|
|
import os
|
|
import tempfile
|
|
|
|
import pytest
|
|
|
|
from src.models import Workspace
|
|
from src.services.shared.file_service import FileService
|
|
|
|
|
|
@pytest.fixture
|
|
def temp_workspace():
|
|
"""Create a temporary workspace directory."""
|
|
with tempfile.TemporaryDirectory() as 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 TestFileService:
|
|
"""Tests for FileService."""
|
|
|
|
def test_list_directory_empty(self, temp_workspace: Workspace):
|
|
"""Returns empty list for empty directory."""
|
|
service = FileService()
|
|
entries = service.list_directory(temp_workspace)
|
|
assert entries == []
|
|
|
|
def test_list_directory_with_files(self, temp_workspace: Workspace):
|
|
"""Returns entries sorted (dirs first, then files)."""
|
|
# Create files and dirs
|
|
os.makedirs(os.path.join(temp_workspace.path, "src"))
|
|
with open(os.path.join(temp_workspace.path, "README.md"), "w") as f:
|
|
f.write("# Test")
|
|
with open(os.path.join(temp_workspace.path, "main.py"), "w") as f:
|
|
f.write("print('hello')")
|
|
|
|
service = FileService()
|
|
entries = service.list_directory(temp_workspace)
|
|
|
|
assert len(entries) == 3
|
|
assert entries[0].name == "src" and entries[0].type == "directory"
|
|
assert entries[1].name == "main.py" and entries[1].type == "file"
|
|
assert entries[2].name == "README.md" and entries[2].type == "file"
|
|
|
|
def test_read_file(self, temp_workspace: Workspace):
|
|
"""Reads text file content."""
|
|
with open(os.path.join(temp_workspace.path, "test.txt"), "w") as f:
|
|
f.write("hello world")
|
|
|
|
service = FileService()
|
|
content = service.read_file(temp_workspace, "test.txt")
|
|
assert content == "hello world"
|
|
|
|
def test_read_binary_file_rejected(self, temp_workspace: Workspace):
|
|
"""Rejects binary files."""
|
|
with open(os.path.join(temp_workspace.path, "binary.bin"), "wb") as f:
|
|
f.write(b"\x00\x01\x02")
|
|
|
|
service = FileService()
|
|
with pytest.raises(ValueError, match="Binary"):
|
|
service.read_file(temp_workspace, "binary.bin")
|
|
|
|
def test_write_file(self, temp_workspace: Workspace):
|
|
"""Writes file to workspace."""
|
|
service = FileService()
|
|
service.write_file(temp_workspace, "nested/file.txt", "content")
|
|
|
|
assert os.path.exists(os.path.join(temp_workspace.path, "nested", "file.txt"))
|
|
with open(os.path.join(temp_workspace.path, "nested", "file.txt")) as f:
|
|
assert f.read() == "content"
|
|
|
|
def test_path_escapes_workspace(self, temp_workspace: Workspace):
|
|
"""Rejects paths that escape workspace directory."""
|
|
service = FileService()
|
|
with pytest.raises(ValueError, match="escapes"):
|
|
service.list_directory(temp_workspace, "../outside")
|