mirror of
https://github.com/basnijholt/compose-farm.git
synced 2026-02-03 14:13:26 +00:00
feat(web): Add Console page with terminal and editor (#17)
This commit is contained in:
54
tests/web/test_backup.py
Normal file
54
tests/web/test_backup.py
Normal file
@@ -0,0 +1,54 @@
|
||||
"""Tests for file backup functionality."""
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
from compose_farm.web.routes.api import _backup_file, _save_with_backup
|
||||
|
||||
|
||||
def test_backup_creates_timestamped_file(tmp_path: Path) -> None:
|
||||
"""Test that backup creates file in .backups with correct content."""
|
||||
test_file = tmp_path / "test.yaml"
|
||||
test_file.write_text("original content")
|
||||
|
||||
backup_path = _backup_file(test_file)
|
||||
|
||||
assert backup_path is not None
|
||||
assert backup_path.parent.name == ".backups"
|
||||
assert backup_path.name.startswith("test.yaml.")
|
||||
assert backup_path.read_text() == "original content"
|
||||
|
||||
|
||||
def test_backup_returns_none_for_nonexistent_file(tmp_path: Path) -> None:
|
||||
"""Test that backup returns None if file doesn't exist."""
|
||||
assert _backup_file(tmp_path / "nonexistent.yaml") is None
|
||||
|
||||
|
||||
def test_save_creates_new_file(tmp_path: Path) -> None:
|
||||
"""Test that save creates new file without backup."""
|
||||
test_file = tmp_path / "new.yaml"
|
||||
|
||||
assert _save_with_backup(test_file, "content") is True
|
||||
assert test_file.read_text() == "content"
|
||||
assert not (tmp_path / ".backups").exists()
|
||||
|
||||
|
||||
def test_save_skips_unchanged_content(tmp_path: Path) -> None:
|
||||
"""Test that save returns False and creates no backup if unchanged."""
|
||||
test_file = tmp_path / "test.yaml"
|
||||
test_file.write_text("same")
|
||||
|
||||
assert _save_with_backup(test_file, "same") is False
|
||||
assert not (tmp_path / ".backups").exists()
|
||||
|
||||
|
||||
def test_save_creates_backup_before_overwrite(tmp_path: Path) -> None:
|
||||
"""Test that save backs up original before overwriting."""
|
||||
test_file = tmp_path / "test.yaml"
|
||||
test_file.write_text("original")
|
||||
|
||||
assert _save_with_backup(test_file, "new") is True
|
||||
assert test_file.read_text() == "new"
|
||||
|
||||
backups = list((tmp_path / ".backups").glob("test.yaml.*"))
|
||||
assert len(backups) == 1
|
||||
assert backups[0].read_text() == "original"
|
||||
111
tests/web/test_template_context.py
Normal file
111
tests/web/test_template_context.py
Normal file
@@ -0,0 +1,111 @@
|
||||
"""Tests to verify template context variables match what templates expect.
|
||||
|
||||
Uses runtime validation by actually rendering templates and catching errors.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from compose_farm.config import Config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_config(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Config:
|
||||
"""Create a minimal mock config for template testing."""
|
||||
compose_dir = tmp_path / "compose"
|
||||
compose_dir.mkdir()
|
||||
|
||||
# Create minimal service directory
|
||||
svc_dir = compose_dir / "test-service"
|
||||
svc_dir.mkdir()
|
||||
(svc_dir / "compose.yaml").write_text("services:\n app:\n image: nginx\n")
|
||||
|
||||
config_path = tmp_path / "compose-farm.yaml"
|
||||
config_path.write_text(f"""
|
||||
compose_dir: {compose_dir}
|
||||
hosts:
|
||||
local-host:
|
||||
address: localhost
|
||||
services:
|
||||
test-service: local-host
|
||||
""")
|
||||
|
||||
state_path = tmp_path / "compose-farm-state.yaml"
|
||||
state_path.write_text("deployed:\n test-service: local-host\n")
|
||||
|
||||
from compose_farm.config import load_config
|
||||
|
||||
config = load_config(config_path)
|
||||
|
||||
# Patch get_config in all relevant modules
|
||||
from compose_farm.web import deps
|
||||
from compose_farm.web.routes import api, pages
|
||||
|
||||
monkeypatch.setattr(deps, "get_config", lambda: config)
|
||||
monkeypatch.setattr(api, "get_config", lambda: config)
|
||||
monkeypatch.setattr(pages, "get_config", lambda: config)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(mock_config: Config) -> TestClient:
|
||||
"""Create a test client with mocked config."""
|
||||
from compose_farm.web.app import create_app
|
||||
|
||||
return TestClient(create_app())
|
||||
|
||||
|
||||
class TestPageTemplatesRender:
|
||||
"""Test that page templates render without missing variables."""
|
||||
|
||||
def test_index_renders(self, client: TestClient) -> None:
|
||||
"""Test index page renders without errors."""
|
||||
response = client.get("/")
|
||||
assert response.status_code == 200
|
||||
assert "Compose Farm" in response.text
|
||||
|
||||
def test_console_renders(self, client: TestClient) -> None:
|
||||
"""Test console page renders without errors."""
|
||||
response = client.get("/console")
|
||||
assert response.status_code == 200
|
||||
assert "Console" in response.text
|
||||
assert "Terminal" in response.text
|
||||
|
||||
def test_service_detail_renders(self, client: TestClient) -> None:
|
||||
"""Test service detail page renders without errors."""
|
||||
response = client.get("/service/test-service")
|
||||
assert response.status_code == 200
|
||||
assert "test-service" in response.text
|
||||
|
||||
|
||||
class TestPartialTemplatesRender:
|
||||
"""Test that partial templates render without missing variables."""
|
||||
|
||||
def test_sidebar_renders(self, client: TestClient) -> None:
|
||||
"""Test sidebar partial renders without errors."""
|
||||
response = client.get("/partials/sidebar")
|
||||
assert response.status_code == 200
|
||||
assert "Dashboard" in response.text
|
||||
assert "Console" in response.text
|
||||
|
||||
def test_stats_renders(self, client: TestClient) -> None:
|
||||
"""Test stats partial renders without errors."""
|
||||
response = client.get("/partials/stats")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_pending_renders(self, client: TestClient) -> None:
|
||||
"""Test pending partial renders without errors."""
|
||||
response = client.get("/partials/pending")
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_services_by_host_renders(self, client: TestClient) -> None:
|
||||
"""Test services_by_host partial renders without errors."""
|
||||
response = client.get("/partials/services-by-host")
|
||||
assert response.status_code == 200
|
||||
Reference in New Issue
Block a user