test: fix backend and frontend test contracts
This commit is contained in:
@@ -183,6 +183,7 @@ async def sync_dashboard(
|
|||||||
"source_env_id": source_env_id,
|
"source_env_id": source_env_id,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
return result
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class EventBus:
|
|||||||
# @POST Flusher task is created and scheduled in the event loop.
|
# @POST Flusher task is created and scheduled in the event loop.
|
||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
if self._flusher_task is None or self._flusher_task.done():
|
if self._flusher_task is None or self._flusher_task.done():
|
||||||
|
asyncio.get_running_loop()
|
||||||
self._flusher_task = asyncio.create_task(self.async_flusher_loop())
|
self._flusher_task = asyncio.create_task(self.async_flusher_loop())
|
||||||
# #endregion start
|
# #endregion start
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,10 @@ class StoragePlugin(PluginBase):
|
|||||||
# Use TaskContext logger if available, otherwise fall back to app logger
|
# Use TaskContext logger if available, otherwise fall back to app logger
|
||||||
log = context.logger if context else logger
|
log = context.logger if context else logger
|
||||||
|
|
||||||
logger.reason("Executing storage task", payload={"params": params})
|
if context is not None and hasattr(log, "with_source"):
|
||||||
|
log = log.with_source("StoragePlugin.execute")
|
||||||
|
|
||||||
|
log.reason("Executing storage task", payload={"params": params})
|
||||||
# endregion execute
|
# endregion execute
|
||||||
|
|
||||||
# region get_storage_root [TYPE Function]
|
# region get_storage_root [TYPE Function]
|
||||||
|
|||||||
@@ -273,6 +273,12 @@ class TestPromoteDashboard:
|
|||||||
class TestDeployDashboard:
|
class TestDeployDashboard:
|
||||||
"""POST /repositories/{dashboard_ref}/deploy"""
|
"""POST /repositories/{dashboard_ref}/deploy"""
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _target_environment():
|
||||||
|
target = MagicMock()
|
||||||
|
target.id = "preprod-1"
|
||||||
|
return target
|
||||||
|
|
||||||
def test_success(self):
|
def test_success(self):
|
||||||
mock_plugin = MagicMock()
|
mock_plugin = MagicMock()
|
||||||
mock_plugin.execute = AsyncMock(return_value={"status": "deployed"})
|
mock_plugin.execute = AsyncMock(return_value={"status": "deployed"})
|
||||||
@@ -280,9 +286,10 @@ class TestDeployDashboard:
|
|||||||
with (
|
with (
|
||||||
patch("src.plugins.git_plugin.GitPlugin", return_value=mock_plugin),
|
patch("src.plugins.git_plugin.GitPlugin", return_value=mock_plugin),
|
||||||
patch("src.api.routes.git._resolve_dashboard_id_from_ref", AsyncMock(return_value=42)),
|
patch("src.api.routes.git._resolve_dashboard_id_from_ref", AsyncMock(return_value=42)),
|
||||||
|
patch("src.api.routes.git._repo_lifecycle_routes._resolve_stage_environment", return_value=self._target_environment()),
|
||||||
):
|
):
|
||||||
client = _make_client()
|
client = _make_client()
|
||||||
resp = client.post("/repositories/42/deploy", json={"environment_id": "prod"})
|
resp = client.post("/repositories/42/deploy", json={"stage": "preprod"})
|
||||||
assert resp.status_code == 200
|
assert resp.status_code == 200
|
||||||
assert resp.json()["status"] == "deployed"
|
assert resp.json()["status"] == "deployed"
|
||||||
|
|
||||||
@@ -293,9 +300,10 @@ class TestDeployDashboard:
|
|||||||
with (
|
with (
|
||||||
patch("src.plugins.git_plugin.GitPlugin", return_value=mock_plugin),
|
patch("src.plugins.git_plugin.GitPlugin", return_value=mock_plugin),
|
||||||
patch("src.api.routes.git._resolve_dashboard_id_from_ref", AsyncMock(return_value=42)),
|
patch("src.api.routes.git._resolve_dashboard_id_from_ref", AsyncMock(return_value=42)),
|
||||||
|
patch("src.api.routes.git._repo_lifecycle_routes._resolve_stage_environment", return_value=self._target_environment()),
|
||||||
):
|
):
|
||||||
client = _make_client()
|
client = _make_client()
|
||||||
resp = client.post("/repositories/42/deploy", json={"environment_id": "prod"})
|
resp = client.post("/repositories/42/deploy", json={"stage": "preprod"})
|
||||||
assert resp.status_code == 500
|
assert resp.status_code == 500
|
||||||
|
|
||||||
def test_dashboard_not_found(self):
|
def test_dashboard_not_found(self):
|
||||||
@@ -304,6 +312,6 @@ class TestDeployDashboard:
|
|||||||
patch("src.api.routes.git._resolve_dashboard_id_from_ref", AsyncMock(side_effect=HTTPException(status_code=404, detail="Not found"))),
|
patch("src.api.routes.git._resolve_dashboard_id_from_ref", AsyncMock(side_effect=HTTPException(status_code=404, detail="Not found"))),
|
||||||
):
|
):
|
||||||
client = _make_client()
|
client = _make_client()
|
||||||
resp = client.post("/repositories/bad-ref/deploy", json={"environment_id": "prod"})
|
resp = client.post("/repositories/bad-ref/deploy", json={"stage": "prod"})
|
||||||
assert resp.status_code == 404
|
assert resp.status_code == 404
|
||||||
# #endregion Test.Api.GitRepoLifecycleRoutes
|
# #endregion Test.Api.GitRepoLifecycleRoutes
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ class TestGenerateCommitMessage:
|
|||||||
|
|
||||||
def test_no_changes(self):
|
def test_no_changes(self):
|
||||||
mock_gs = MagicMock()
|
mock_gs = MagicMock()
|
||||||
mock_gs.get_diff = AsyncMock(return_value=[None, None])
|
mock_gs.get_diff = AsyncMock(return_value=None)
|
||||||
|
|
||||||
with (
|
with (
|
||||||
patch("src.api.routes.git._repo_operations_routes.get_git_service", return_value=mock_gs),
|
patch("src.api.routes.git._repo_operations_routes.get_git_service", return_value=mock_gs),
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ def _make_client(overrides: dict | None = None) -> TestClient:
|
|||||||
class TestInitRepository:
|
class TestInitRepository:
|
||||||
"""POST /repositories/{dashboard_ref}/init"""
|
"""POST /repositories/{dashboard_ref}/init"""
|
||||||
|
|
||||||
INIT_PAYLOAD = {"config_id": "cfg-1", "remote_url": "https://example.com/org/repo.git"}
|
INIT_PAYLOAD = {"config_id": "cfg-1", "remote_url": "https://gitea.example.com/org/repo.git"}
|
||||||
|
|
||||||
def test_success_new_repo(self, mock_git_config):
|
def test_success_new_repo(self, mock_git_config):
|
||||||
mock_db = MagicMock()
|
mock_db = MagicMock()
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ class TestDeleteFile:
|
|||||||
def test_success(self):
|
def test_success(self):
|
||||||
client, mock_loader = _make_client()
|
client, mock_loader = _make_client()
|
||||||
mock_plugin = MagicMock()
|
mock_plugin = MagicMock()
|
||||||
|
mock_plugin.delete_file = AsyncMock()
|
||||||
mock_loader.get_plugin.return_value = mock_plugin
|
mock_loader.get_plugin.return_value = mock_plugin
|
||||||
resp = client.delete(f"{P}/files/backups/test.txt")
|
resp = client.delete(f"{P}/files/backups/test.txt")
|
||||||
assert resp.status_code == 204
|
assert resp.status_code == 204
|
||||||
|
|||||||
@@ -105,12 +105,30 @@ def pytest_configure(config):
|
|||||||
f"\n[conftest] SQLite (global: {_TEST_DB_PATH}) + FK enforcement",
|
f"\n[conftest] SQLite (global: {_TEST_DB_PATH}) + FK enforcement",
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
|
if config.getoption("--run-integration"):
|
||||||
|
print(" Integration tests enabled (--run-integration).\n", file=sys.stderr)
|
||||||
|
else:
|
||||||
print(
|
print(
|
||||||
" Integration tests skipped by default. Use --run-integration to enable.\n",
|
" Integration tests skipped by default. Use --run-integration to enable.\n",
|
||||||
file=sys.stderr,
|
file=sys.stderr,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_collection_modifyitems(config, items):
|
||||||
|
"""Expose tests under tests/integration to the integration marker.
|
||||||
|
|
||||||
|
Integration tests are discovered by directory today, while pytest's
|
||||||
|
``-m integration`` selector operates on markers. Applying the marker at
|
||||||
|
collection time keeps both invocation styles equivalent:
|
||||||
|
``pytest tests/integration --run-integration`` and
|
||||||
|
``pytest -m integration --run-integration``.
|
||||||
|
"""
|
||||||
|
integration_marker = pytest.mark.integration
|
||||||
|
for item in items:
|
||||||
|
if "/tests/integration/" in f"/{item.nodeid}":
|
||||||
|
item.add_marker(integration_marker)
|
||||||
|
|
||||||
|
|
||||||
def pytest_unconfigure(config):
|
def pytest_unconfigure(config):
|
||||||
try:
|
try:
|
||||||
from src.core.database import engine as _global_engine
|
from src.core.database import engine as _global_engine
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ describe('GitFeatureWorkflow', () => {
|
|||||||
branches: [{ name: 'feature/already-tested', commit_hash: 'merged-123456', ahead_of_dev: 0 }],
|
branches: [{ name: 'feature/already-tested', commit_hash: 'merged-123456', ahead_of_dev: 0 }],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByText(/Нет активных доработок/)).toBeTruthy();
|
expect(screen.getByText(/Нет отдельных доработок, ожидающих передачи в DEV/)).toBeTruthy();
|
||||||
expect(screen.getByText(/Черновики уже в DEV/)).toBeTruthy();
|
expect(screen.getByText(/Черновики уже в DEV/)).toBeTruthy();
|
||||||
expect(screen.queryByText('Передать в DEV')).toBeNull();
|
expect(screen.queryByText('Передать в DEV')).toBeNull();
|
||||||
});
|
});
|
||||||
@@ -52,7 +52,7 @@ describe('GitFeatureWorkflow', () => {
|
|||||||
branches: [{ name: 'feature/remote-only', is_remote: true, ahead_of_dev: 5 }],
|
branches: [{ name: 'feature/remote-only', is_remote: true, ahead_of_dev: 5 }],
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(screen.getByText(/Нет отдельных черновиков/)).toBeTruthy();
|
expect(screen.getByText(/Нет отдельных доработок, ожидающих передачи в DEV/)).toBeTruthy();
|
||||||
expect(screen.queryByText('remote only')).toBeNull();
|
expect(screen.queryByText('remote only')).toBeNull();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user