Add tests for M4 workspace files and wizard

- test_settings.py: Add TestDocsModeSettings and TestWorkspaceExportImport
- test_paths.py: Comprehensive PathResolver tests with proper isolation
- test_wizard.py: Wizard structure and settings integration tests

All 71 tests pass.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2026-01-25 05:57:59 -04:00
parent 5742b7088b
commit b60af09922
3 changed files with 821 additions and 0 deletions

308
tests/test_paths.py Normal file
View File

@ -0,0 +1,308 @@
"""Tests for the PathResolver module."""
import pytest
from pathlib import Path
from unittest.mock import patch, MagicMock
from development_hub.paths import PathResolver, paths
from development_hub.settings import Settings
class TestPathResolver:
"""Test PathResolver path resolution."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create isolated settings for testing."""
Settings._instance = None
PathResolver._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
PathResolver._instance = None
def test_singleton_pattern(self):
"""PathResolver is a singleton."""
PathResolver._instance = None
resolver1 = PathResolver()
resolver2 = PathResolver()
assert resolver1 is resolver2
PathResolver._instance = None
def test_projects_root_from_settings(self, isolated_settings, tmp_path):
"""Projects root comes from settings."""
isolated_settings.project_search_paths = [str(tmp_path / "my-projects")]
resolver = PathResolver()
assert resolver.projects_root == tmp_path / "my-projects"
def test_projects_root_default(self, isolated_settings, tmp_path):
"""Projects root defaults to ~/Projects when not set."""
isolated_settings.project_search_paths = []
resolver = PathResolver()
assert resolver.projects_root == Path.home() / "Projects"
def test_docs_root_from_settings(self, isolated_settings, tmp_path):
"""Docs root comes from settings."""
isolated_settings.docs_mode = "standalone"
resolver = PathResolver()
docs_root = resolver.docs_root
assert "development-hub" in str(docs_root)
def test_project_docs_dir(self, isolated_settings, tmp_path):
"""Project docs dir returns docusaurus path."""
project_docs = tmp_path / "project-docs"
project_docs.mkdir()
isolated_settings.project_search_paths = [str(tmp_path)]
resolver = PathResolver()
assert resolver.project_docs_dir == project_docs
def test_project_docs_dir_none_when_not_exists(self, isolated_settings, tmp_path):
"""Project docs dir is None when not configured."""
isolated_settings.project_search_paths = [str(tmp_path)]
# No project-docs folder
resolver = PathResolver()
assert resolver.project_docs_dir is None
def test_progress_dir(self, isolated_settings):
"""Progress dir comes from settings."""
resolver = PathResolver()
progress = resolver.progress_dir
assert isinstance(progress, Path)
def test_build_script_when_exists(self, isolated_settings, tmp_path):
"""Build script returns path when it exists."""
project_docs = tmp_path / "project-docs"
scripts_dir = project_docs / "scripts"
scripts_dir.mkdir(parents=True)
build_script = scripts_dir / "build-public-docs.sh"
build_script.touch()
isolated_settings.project_search_paths = [str(tmp_path)]
resolver = PathResolver()
assert resolver.build_script == build_script
def test_build_script_none_when_not_exists(self, isolated_settings, tmp_path):
"""Build script is None when it doesn't exist."""
isolated_settings.project_search_paths = [str(tmp_path)]
resolver = PathResolver()
assert resolver.build_script is None
def test_project_docs_path(self, isolated_settings):
"""project_docs_path returns correct path for project."""
resolver = PathResolver()
path = resolver.project_docs_path("my-project")
assert path.name == "my-project"
assert "projects" in str(path)
def test_git_url_not_configured(self, isolated_settings):
"""git_url returns empty string when not configured."""
resolver = PathResolver()
assert resolver.git_url() == ""
assert resolver.git_url("owner", "repo") == ""
def test_git_url_configured(self, isolated_settings):
"""git_url returns correct URL when configured."""
isolated_settings.git_host_type = "github"
isolated_settings.git_host_url = "https://github.com"
isolated_settings.git_host_owner = "testowner"
resolver = PathResolver()
assert resolver.git_url() == "https://github.com/testowner"
assert resolver.git_url("testowner", "testrepo") == "https://github.com/testowner/testrepo"
def test_git_url_custom_owner(self, isolated_settings):
"""git_url can use custom owner."""
isolated_settings.git_host_type = "github"
isolated_settings.git_host_url = "https://github.com"
isolated_settings.git_host_owner = "default"
resolver = PathResolver()
assert resolver.git_url("custom", "repo") == "https://github.com/custom/repo"
def test_pages_url_not_configured(self, isolated_settings):
"""pages_url returns empty string when not configured."""
resolver = PathResolver()
assert resolver.pages_url() == ""
def test_pages_url_configured(self, isolated_settings):
"""pages_url returns correct URL when configured."""
isolated_settings.git_host_owner = "testowner"
isolated_settings.pages_url = "https://pages.example.com"
resolver = PathResolver()
assert "pages.example.com" in resolver.pages_url()
assert "testowner" in resolver.pages_url()
def test_is_docs_enabled(self, isolated_settings):
"""is_docs_enabled reflects settings."""
isolated_settings.docs_mode = "standalone"
resolver = PathResolver()
assert resolver.is_docs_enabled == True
def test_is_git_configured(self, isolated_settings):
"""is_git_configured reflects settings."""
resolver = PathResolver()
assert resolver.is_git_configured == False
isolated_settings.git_host_type = "github"
isolated_settings.git_host_url = "https://github.com"
isolated_settings.git_host_owner = "user"
assert resolver.is_git_configured == True
def test_effective_docs_mode(self, isolated_settings, tmp_path):
"""effective_docs_mode reflects settings."""
isolated_settings.project_search_paths = [str(tmp_path)]
isolated_settings.docs_mode = "auto"
resolver = PathResolver()
# No project-docs, so standalone
assert resolver.effective_docs_mode == "standalone"
# Create project-docs
(tmp_path / "project-docs").mkdir()
assert resolver.effective_docs_mode == "project-docs"
class TestCmdForgeAvailability:
"""Test CmdForge availability checks."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create isolated settings for testing."""
Settings._instance = None
PathResolver._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
# Use isolated paths to prevent finding real CmdForge
settings.project_search_paths = [str(tmp_path)]
yield settings
Settings._instance = None
PathResolver._instance = None
def test_cmdforge_path_explicit(self, isolated_settings, tmp_path):
"""CmdForge path from explicit setting."""
cmdforge_dir = tmp_path / "CmdForge"
cmdforge_dir.mkdir()
isolated_settings.cmdforge_path = cmdforge_dir
resolver = PathResolver()
assert resolver.cmdforge_path == cmdforge_dir
def test_cmdforge_executable_from_venv(self, isolated_settings, tmp_path):
"""CmdForge executable found in venv."""
cmdforge_dir = tmp_path / "CmdForge"
venv_bin = cmdforge_dir / ".venv" / "bin"
venv_bin.mkdir(parents=True)
cmdforge_exe = venv_bin / "cmdforge"
cmdforge_exe.touch()
isolated_settings.cmdforge_path = cmdforge_dir
resolver = PathResolver()
assert resolver.cmdforge_executable == cmdforge_exe
@patch("development_hub.paths.shutil.which")
def test_cmdforge_executable_from_path(self, mock_which, isolated_settings, tmp_path):
"""CmdForge executable found in PATH when not in explicit location."""
mock_which.return_value = "/usr/local/bin/cmdforge"
# Ensure no explicit cmdforge path is set
isolated_settings.cmdforge_path = None
resolver = PathResolver()
exe = resolver.cmdforge_executable
assert exe == Path("/usr/local/bin/cmdforge")
@patch("development_hub.paths.shutil.which")
def test_cmdforge_executable_not_found(self, mock_which, isolated_settings, tmp_path):
"""CmdForge executable None when not found."""
mock_which.return_value = None
# Ensure no explicit cmdforge path is set
isolated_settings.cmdforge_path = None
resolver = PathResolver()
assert resolver.cmdforge_executable is None
@patch("development_hub.paths.shutil.which")
def test_is_cmdforge_available_false(self, mock_which, isolated_settings, tmp_path):
"""is_cmdforge_available is False when not found."""
mock_which.return_value = None
isolated_settings.cmdforge_path = None
resolver = PathResolver()
assert resolver.is_cmdforge_available == False
@patch("development_hub.paths.shutil.which")
def test_is_cmdforge_available_true(self, mock_which, isolated_settings, tmp_path):
"""is_cmdforge_available is True when found in PATH."""
mock_which.return_value = "/usr/bin/cmdforge"
isolated_settings.cmdforge_path = None
resolver = PathResolver()
assert resolver.is_cmdforge_available == True
class TestGlobalPathsInstance:
"""Test the global paths singleton instance."""
def test_paths_is_path_resolver(self):
"""Global paths is a PathResolver instance."""
assert isinstance(paths, PathResolver)
def test_paths_has_expected_properties(self):
"""Global paths has expected properties."""
assert hasattr(paths, "projects_root")
assert hasattr(paths, "docs_root")
assert hasattr(paths, "project_docs_dir")
assert hasattr(paths, "progress_dir")
assert hasattr(paths, "build_script")
assert hasattr(paths, "cmdforge_path")
assert hasattr(paths, "cmdforge_executable")
assert hasattr(paths, "is_docs_enabled")
assert hasattr(paths, "is_cmdforge_available")
assert hasattr(paths, "is_git_configured")
def test_paths_has_expected_methods(self):
"""Global paths has expected methods."""
assert callable(paths.project_docs_path)
assert callable(paths.git_url)
assert callable(paths.pages_url)
if __name__ == "__main__":
pytest.main([__file__, "-v"])

View File

@ -245,5 +245,291 @@ class TestGitHostSettings:
assert settings.is_git_configured == False assert settings.is_git_configured == False
class TestDocsModeSettings:
"""Test documentation mode configuration."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create an isolated Settings instance."""
Settings._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
def test_default_docs_mode(self, isolated_settings):
"""Default docs mode is auto."""
settings = isolated_settings
assert settings.docs_mode == "auto"
def test_set_docs_mode(self, isolated_settings):
"""Can set docs mode."""
settings = isolated_settings
settings.docs_mode = "standalone"
assert settings.docs_mode == "standalone"
settings.docs_mode = "project-docs"
assert settings.docs_mode == "project-docs"
def test_effective_docs_mode_standalone_when_no_project_docs(self, isolated_settings, tmp_path):
"""Effective mode is standalone when project-docs doesn't exist."""
settings = isolated_settings
settings.project_search_paths = [str(tmp_path)]
# No project-docs folder exists
assert settings.effective_docs_mode == "standalone"
def test_effective_docs_mode_project_docs_when_exists(self, isolated_settings, tmp_path):
"""Effective mode is project-docs when folder exists."""
settings = isolated_settings
settings.project_search_paths = [str(tmp_path)]
# Create project-docs folder
(tmp_path / "project-docs").mkdir()
assert settings.effective_docs_mode == "project-docs"
def test_explicit_mode_overrides_auto(self, isolated_settings, tmp_path):
"""Explicit mode setting overrides auto-detection."""
settings = isolated_settings
settings.project_search_paths = [str(tmp_path)]
# Create project-docs (would trigger project-docs mode in auto)
(tmp_path / "project-docs").mkdir()
# But explicitly set to standalone
settings.docs_mode = "standalone"
assert settings.effective_docs_mode == "standalone"
def test_docs_root_standalone_mode(self, isolated_settings):
"""Docs root in standalone mode uses local share."""
settings = isolated_settings
settings.docs_mode = "standalone"
docs_root = settings.docs_root
assert ".local/share/development-hub" in str(docs_root)
def test_docusaurus_path_property(self, isolated_settings, tmp_path):
"""Can set and get docusaurus path."""
settings = isolated_settings
settings.docusaurus_path = tmp_path / "my-docs"
assert settings.docusaurus_path == tmp_path / "my-docs"
def test_pages_url_property(self, isolated_settings):
"""Can set and get pages URL."""
settings = isolated_settings
settings.pages_url = "https://pages.example.com"
assert settings.pages_url == "https://pages.example.com"
def test_pages_url_derived_from_gitea(self, isolated_settings):
"""Pages URL can be derived from gitea URL."""
settings = isolated_settings
settings.git_host_type = "gitea"
settings.git_host_url = "https://gitea.example.com"
# When not explicitly set, should derive
assert "pages.example.com" in settings.pages_url
def test_is_docs_enabled_standalone(self, isolated_settings):
"""Docs are always enabled in standalone mode."""
settings = isolated_settings
settings.docs_mode = "standalone"
assert settings.is_docs_enabled == True
def test_cmdforge_path_property(self, isolated_settings, tmp_path):
"""Can set and get cmdforge path."""
settings = isolated_settings
settings.cmdforge_path = tmp_path / "CmdForge"
assert settings.cmdforge_path == tmp_path / "CmdForge"
def test_progress_dir_property(self, isolated_settings, tmp_path):
"""Can set and get progress directory."""
settings = isolated_settings
settings.progress_dir = tmp_path / "progress"
assert settings.progress_dir == tmp_path / "progress"
class TestWorkspaceExportImport:
"""Test workspace file export/import."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create an isolated Settings instance."""
Settings._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
def test_export_workspace_creates_file(self, isolated_settings, tmp_path):
"""Export creates a YAML workspace file."""
settings = isolated_settings
workspace_path = tmp_path / "workspace.yaml"
settings.export_workspace(workspace_path)
assert workspace_path.exists()
def test_export_workspace_contains_required_fields(self, isolated_settings, tmp_path):
"""Exported workspace contains required fields."""
import yaml
settings = isolated_settings
settings.project_search_paths = [str(tmp_path / "projects")]
workspace_path = tmp_path / "workspace.yaml"
settings.export_workspace(workspace_path)
with open(workspace_path) as f:
workspace = yaml.safe_load(f)
assert "name" in workspace
assert "version" in workspace
assert workspace["version"] == 1
assert "paths" in workspace
assert "projects_root" in workspace["paths"]
assert "documentation" in workspace
assert "features" in workspace
def test_export_includes_git_hosting_when_configured(self, isolated_settings, tmp_path):
"""Exported workspace includes git hosting when configured."""
import yaml
settings = isolated_settings
settings.git_host_type = "github"
settings.git_host_url = "https://github.com"
settings.git_host_owner = "testuser"
workspace_path = tmp_path / "workspace.yaml"
settings.export_workspace(workspace_path)
with open(workspace_path) as f:
workspace = yaml.safe_load(f)
assert "git_hosting" in workspace
assert workspace["git_hosting"]["type"] == "github"
assert workspace["git_hosting"]["url"] == "https://github.com"
assert workspace["git_hosting"]["owner"] == "testuser"
def test_import_workspace_sets_values(self, isolated_settings, tmp_path):
"""Import workspace sets settings values."""
import yaml
settings = isolated_settings
workspace = {
"name": "Test Workspace",
"version": 1,
"paths": {
"projects_root": str(tmp_path / "my-projects")
},
"documentation": {
"mode": "standalone"
}
}
workspace_path = tmp_path / "workspace.yaml"
with open(workspace_path, "w") as f:
yaml.dump(workspace, f)
results = settings.import_workspace(workspace_path)
assert "projects_root" in results["imported"]
assert settings.project_search_paths == [str(tmp_path / "my-projects")]
assert settings.docs_mode == "standalone"
def test_import_workspace_sets_git_hosting(self, isolated_settings, tmp_path):
"""Import workspace sets git hosting values."""
import yaml
settings = isolated_settings
workspace = {
"name": "Test",
"version": 1,
"paths": {"projects_root": str(tmp_path)},
"git_hosting": {
"type": "gitea",
"url": "https://git.example.com",
"owner": "myorg",
"pages_url": "https://pages.example.com"
}
}
workspace_path = tmp_path / "workspace.yaml"
with open(workspace_path, "w") as f:
yaml.dump(workspace, f)
settings.import_workspace(workspace_path)
assert settings.git_host_type == "gitea"
assert settings.git_host_url == "https://git.example.com"
assert settings.git_host_owner == "myorg"
assert settings.pages_url == "https://pages.example.com"
def test_import_marks_setup_completed(self, isolated_settings, tmp_path):
"""Import workspace marks setup as completed."""
import yaml
settings = isolated_settings
workspace = {
"name": "Test",
"version": 1,
"paths": {"projects_root": str(tmp_path)}
}
workspace_path = tmp_path / "workspace.yaml"
with open(workspace_path, "w") as f:
yaml.dump(workspace, f)
settings.import_workspace(workspace_path)
assert settings.get("setup_completed") == True
def test_export_import_round_trip(self, isolated_settings, tmp_path):
"""Export and import preserves settings."""
settings = isolated_settings
# Configure settings
settings.project_search_paths = [str(tmp_path / "projects")]
settings.docs_mode = "project-docs"
settings.git_host_type = "gitlab"
settings.git_host_url = "https://gitlab.com"
settings.git_host_owner = "myuser"
# Export
workspace_path = tmp_path / "workspace.yaml"
settings.export_workspace(workspace_path)
# Reset settings
Settings._instance = None
new_settings = Settings()
# Import
new_settings.import_workspace(workspace_path)
assert new_settings.project_search_paths == [str(tmp_path / "projects")]
assert new_settings.docs_mode == "project-docs"
assert new_settings.git_host_type == "gitlab"
assert new_settings.git_host_url == "https://gitlab.com"
assert new_settings.git_host_owner == "myuser"
if __name__ == "__main__": if __name__ == "__main__":
pytest.main([__file__, "-v"]) pytest.main([__file__, "-v"])

227
tests/test_wizard.py Normal file
View File

@ -0,0 +1,227 @@
"""Tests for the SetupWizardDialog."""
import pytest
from pathlib import Path
from unittest.mock import patch, MagicMock
from development_hub.settings import Settings
class TestSetupWizardStructure:
"""Test SetupWizardDialog structure without Qt app."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create isolated settings for testing."""
Settings._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
def test_wizard_import_succeeds(self):
"""SetupWizardDialog can be imported."""
from development_hub.dialogs import SetupWizardDialog
assert SetupWizardDialog is not None
def test_wizard_has_expected_methods(self):
"""SetupWizardDialog has expected methods."""
from development_hub.dialogs import SetupWizardDialog
# Check for key methods
assert hasattr(SetupWizardDialog, "_create_welcome_page")
assert hasattr(SetupWizardDialog, "_create_simple_mode_page")
assert hasattr(SetupWizardDialog, "_create_docs_mode_page")
assert hasattr(SetupWizardDialog, "_create_import_page")
assert hasattr(SetupWizardDialog, "_finish_simple_mode")
assert hasattr(SetupWizardDialog, "_finish_docs_mode")
assert hasattr(SetupWizardDialog, "_finish_import")
class TestWizardSettingsIntegration:
"""Test wizard settings integration logic."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create isolated settings for testing."""
Settings._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
def test_simple_mode_sets_standalone_docs(self, isolated_settings, tmp_path):
"""Simple mode configuration sets standalone docs mode."""
settings = isolated_settings
# Simulate what _finish_simple_mode does
projects_path = tmp_path / "Projects"
projects_path.mkdir()
settings.default_project_path = projects_path
settings.project_search_paths = [str(projects_path)]
settings.docs_mode = "standalone"
settings.set("setup_completed", True)
assert settings.docs_mode == "standalone"
assert settings.get("setup_completed") == True
def test_docs_mode_sets_project_docs(self, isolated_settings, tmp_path):
"""Documentation mode configuration sets project-docs mode."""
settings = isolated_settings
# Simulate what _finish_docs_mode does
projects_path = tmp_path / "PycharmProjects"
projects_path.mkdir()
docusaurus_path = projects_path / "project-docs"
docusaurus_path.mkdir()
settings.default_project_path = projects_path
settings.project_search_paths = [str(projects_path)]
settings.docs_mode = "project-docs"
settings.docusaurus_path = docusaurus_path
settings.auto_start_docs_server = True
settings.git_host_type = "gitea"
settings.git_host_url = "https://gitea.example.com"
settings.git_host_owner = "testuser"
settings.set("setup_completed", True)
assert settings.docs_mode == "project-docs"
assert settings.docusaurus_path == docusaurus_path
assert settings.auto_start_docs_server == True
assert settings.is_git_configured == True
assert settings.get("setup_completed") == True
def test_import_workspace_integration(self, isolated_settings, tmp_path):
"""Import workspace correctly sets all values."""
import yaml
settings = isolated_settings
# Create a workspace file
workspace = {
"name": "Test Workspace",
"version": 1,
"paths": {
"projects_root": str(tmp_path / "projects")
},
"documentation": {
"mode": "project-docs",
"docusaurus_path": str(tmp_path / "docs"),
"auto_start_server": False
},
"git_hosting": {
"type": "github",
"url": "https://github.com",
"owner": "myorg"
}
}
workspace_path = tmp_path / "test-workspace.yaml"
with open(workspace_path, "w") as f:
yaml.dump(workspace, f)
# Import (simulates _finish_import)
results = settings.import_workspace(workspace_path)
assert settings.project_search_paths == [str(tmp_path / "projects")]
assert settings.docs_mode == "project-docs"
assert settings.docusaurus_path == tmp_path / "docs"
assert settings.auto_start_docs_server == False
assert settings.git_host_type == "github"
assert settings.git_host_owner == "myorg"
assert settings.get("setup_completed") == True
class TestWizardModeSelection:
"""Test wizard mode selection logic."""
def test_mode_values(self):
"""Test expected mode values."""
modes = ["simple", "docs", "import"]
# These are the modes used in the wizard
for mode in modes:
assert isinstance(mode, str)
def test_docs_mode_settings_values(self):
"""Test valid docs_mode setting values."""
valid_modes = ["auto", "standalone", "project-docs"]
for mode in valid_modes:
assert isinstance(mode, str)
class TestWizardGitTypeHandling:
"""Test git type handling in wizard."""
@pytest.fixture
def isolated_settings(self, tmp_path, monkeypatch):
"""Create isolated settings."""
Settings._instance = None
monkeypatch.setattr(Settings, "_settings_file", tmp_path / "settings.json")
monkeypatch.setattr(Settings, "_session_file", tmp_path / "session.json")
settings = Settings()
yield settings
Settings._instance = None
def test_github_configuration(self, isolated_settings):
"""GitHub configuration sets correct values."""
settings = isolated_settings
settings.git_host_type = "github"
settings.git_host_url = "https://github.com"
settings.git_host_owner = "testuser"
assert settings.is_git_configured == True
assert settings.git_host_type == "github"
def test_gitlab_configuration(self, isolated_settings):
"""GitLab configuration sets correct values."""
settings = isolated_settings
settings.git_host_type = "gitlab"
settings.git_host_url = "https://gitlab.com"
settings.git_host_owner = "testuser"
assert settings.is_git_configured == True
assert settings.git_host_type == "gitlab"
def test_gitea_configuration(self, isolated_settings):
"""Gitea configuration sets correct values."""
settings = isolated_settings
settings.git_host_type = "gitea"
settings.git_host_url = "https://gitea.example.com"
settings.git_host_owner = "testuser"
assert settings.is_git_configured == True
assert settings.git_host_type == "gitea"
def test_optional_git_in_simple_mode(self, isolated_settings, tmp_path):
"""Git is optional in simple mode."""
settings = isolated_settings
# Simple mode without git
settings.docs_mode = "standalone"
settings.project_search_paths = [str(tmp_path)]
settings.set("setup_completed", True)
# Git not configured is OK
assert settings.is_git_configured == False
assert settings.get("setup_completed") == True
if __name__ == "__main__":
pytest.main([__file__, "-v"])