kin: KIN-ARCH-001 Добавить серверную валидацию ssh_host для operations-проектов

This commit is contained in:
Gros Frumos 2026-03-16 09:44:31 +02:00
parent af554e15fa
commit ba04e7ad84
3 changed files with 141 additions and 5 deletions

View file

@ -1311,16 +1311,110 @@ def test_patch_project_invalid_type_returns_400(client):
def test_create_operations_project_without_ssh_host_allowed(client):
"""KIN-071: API не валидирует ssh_host на стороне бэкенда — проект создаётся без него."""
"""Регрессионный тест KIN-ARCH-001: воспроизводит СЛОМАННОЕ поведение до фикса.
До фикса: POST operations-проекта без ssh_host возвращал 200.
После фикса: должен возвращать 422 (Pydantic model_validator).
Этот тест НАМЕРЕННО проверяет, что старое поведение больше не существует.
"""
r = client.post("/api/projects", json={
"id": "srv2",
"name": "Server No SSH",
"path": "",
"project_type": "operations",
})
# Фикс KIN-ARCH-001: был 200, стал 422
assert r.status_code == 422, (
"Регрессия KIN-ARCH-001: POST operations-проекта без ssh_host "
"должен возвращать 422, а не 200"
)
# ---------------------------------------------------------------------------
# KIN-ARCH-001 — серверная валидация ssh_host для operations-проектов
# ---------------------------------------------------------------------------
def test_kin_arch_001_operations_without_ssh_host_returns_422(client):
"""Регрессионный тест KIN-ARCH-001: POST /api/projects с project_type='operations'
и без ssh_host 422 Unprocessable Entity."""
r = client.post("/api/projects", json={
"id": "ops_no_ssh",
"name": "Ops Without SSH",
"path": "",
"project_type": "operations",
})
assert r.status_code == 422
def test_kin_arch_001_operations_with_empty_ssh_host_returns_422(client):
"""Регрессионный тест KIN-ARCH-001: пустая строка в ssh_host считается отсутствующим
значением 422."""
r = client.post("/api/projects", json={
"id": "ops_empty_ssh",
"name": "Ops Empty SSH",
"path": "",
"project_type": "operations",
"ssh_host": "",
})
assert r.status_code == 422
def test_kin_arch_001_operations_with_valid_ssh_host_returns_200(client):
"""Регрессионный тест KIN-ARCH-001: POST /api/projects с project_type='operations'
и корректным ssh_host 200, проект создаётся."""
r = client.post("/api/projects", json={
"id": "ops_with_ssh",
"name": "Ops With SSH",
"path": "",
"project_type": "operations",
"ssh_host": "10.0.0.42",
})
assert r.status_code == 200
assert r.json()["project_type"] == "operations"
assert r.json()["ssh_host"] is None
data = r.json()
assert data["project_type"] == "operations"
assert data["ssh_host"] == "10.0.0.42"
def test_kin_arch_001_development_without_ssh_host_allowed(client):
"""Регрессионный тест KIN-ARCH-001: project_type='development' без ssh_host
должен создаваться без ошибок валидатор срабатывает только для operations."""
r = client.post("/api/projects", json={
"id": "dev_no_ssh",
"name": "Dev No SSH",
"path": "/dev",
"project_type": "development",
})
assert r.status_code == 200
assert r.json()["project_type"] == "development"
def test_kin_arch_001_research_without_ssh_host_allowed(client):
"""Регрессионный тест KIN-ARCH-001: project_type='research' без ssh_host
должен создаваться без ошибок."""
r = client.post("/api/projects", json={
"id": "res_no_ssh",
"name": "Research No SSH",
"path": "/research",
"project_type": "research",
})
assert r.status_code == 200
assert r.json()["project_type"] == "research"
def test_kin_arch_001_422_error_message_mentions_ssh_host(client):
"""Регрессионный тест KIN-ARCH-001: тело 422-ответа содержит сообщение об ошибке
с упоминанием ssh_host."""
r = client.post("/api/projects", json={
"id": "ops_err_msg",
"name": "Check Error Message",
"path": "",
"project_type": "operations",
})
assert r.status_code == 422
body = r.json()
# Pydantic возвращает detail со списком ошибок
detail_str = str(body)
assert "ssh_host" in detail_str
def test_create_research_project_type_accepted(client):