kin: KIN-ARCH-003 Сделать path nullable для operations-проектов

This commit is contained in:
Gros Frumos 2026-03-16 09:52:44 +02:00
parent 39acc9cc4b
commit 295a95bc7f
3 changed files with 229 additions and 0 deletions

View file

@ -1504,3 +1504,79 @@ def test_create_research_project_type_accepted(client):
})
assert r.status_code == 200
assert r.json()["project_type"] == "research"
# ---------------------------------------------------------------------------
# KIN-ARCH-003 — path nullable для operations-проектов
# Исправляет баг: workaround с пустой строкой ("") для operations-проектов
# ---------------------------------------------------------------------------
def test_kin_arch_003_operations_project_without_path_returns_200(client):
"""KIN-ARCH-003: POST /api/projects с project_type='operations' без path → 200.
До фикса: path="" передавался как workaround для NOT NULL constraint.
После фикса: path не передаётся вовсе, сохраняется как NULL.
"""
r = client.post("/api/projects", json={
"id": "ops_null_path",
"name": "Ops Null Path",
"project_type": "operations",
"ssh_host": "10.0.0.1",
})
assert r.status_code == 200
data = r.json()
assert data["path"] is None, (
"KIN-ARCH-003 регрессия: path должен быть NULL, а не пустой строкой"
)
def test_kin_arch_003_development_project_without_path_returns_422(client):
"""KIN-ARCH-003: POST /api/projects с project_type='development' без path → 422.
Pydantic validate_fields: path обязателен для non-operations проектов.
"""
r = client.post("/api/projects", json={
"id": "dev_no_path",
"name": "Dev No Path",
"project_type": "development",
})
assert r.status_code == 422
def test_kin_arch_003_development_without_path_error_mentions_path(client):
"""KIN-ARCH-003: тело 422-ответа содержит упоминание об обязательности path."""
r = client.post("/api/projects", json={
"id": "dev_no_path_msg",
"name": "Dev No Path Msg",
"project_type": "development",
})
assert r.status_code == 422
detail_str = str(r.json())
assert "path" in detail_str
def test_kin_arch_003_deploy_operations_project_null_path_uses_cwd_none(client):
"""KIN-ARCH-003: deploy_project для operations-проекта с path=NULL
не вызывает Path.exists() передаёт cwd=None в subprocess.run."""
from unittest.mock import patch, MagicMock
client.post("/api/projects", json={
"id": "ops_deploy_null",
"name": "Ops Deploy Null Path",
"project_type": "operations",
"ssh_host": "10.0.0.1",
})
client.patch("/api/projects/ops_deploy_null", json={"deploy_command": "echo ok"})
mock_result = MagicMock()
mock_result.returncode = 0
mock_result.stdout = "ok\n"
mock_result.stderr = ""
with patch("subprocess.run", return_value=mock_result) as mock_run:
r = client.post("/api/projects/ops_deploy_null/deploy")
assert r.status_code == 200
call_kwargs = mock_run.call_args.kwargs
assert call_kwargs.get("cwd") is None, (
"KIN-ARCH-003: для operations-проектов без path, cwd должен быть None"
)