test: final 6 agents — 172+ translate tests, llm_analysis 89%, git_plugin 100%, migration/deps/routes polished. 85-94% files pushed to 95%+. Bulk: backup/debug/maintenance plugins

This commit is contained in:
2026-06-15 22:04:40 +03:00
parent 010edfcfdc
commit fd27569488
35 changed files with 7811 additions and 49 deletions

View File

@@ -150,6 +150,18 @@ class TestSyncHelpers:
with pytest.raises(ValueError, match="empty"):
_extract_zip_to_repo(buf.getvalue(), temp_repo)
def test_extract_zip_binary_content(self, temp_repo):
"""Edge: extract zip with binary file content uses copyfileobj."""
buf = io.BytesIO()
raw_bytes = b'\x89PNG\r\n\x1a\nbinary data \x00\xff'
with zipfile.ZipFile(buf, "w", zipfile.ZIP_DEFLATED) as zf:
zf.writestr("export/images/logo.png", raw_bytes)
buf.seek(0)
_extract_zip_to_repo(buf.getvalue(), temp_repo)
out = temp_repo / "images" / "logo.png"
assert out.exists()
assert out.read_bytes() == raw_bytes
def test_extract_zip_nested_dirs(self, temp_repo):
"""Edge: extract zip with nested directory structure."""
zip_bytes = _create_zip({
@@ -443,6 +455,79 @@ class TestHandleSync:
assert result["status"] == "success"
assert "synced" in result["message"]
@pytest.mark.asyncio
async def test_handle_sync_cleanup_backup_on_success(self):
"""Edge: backup dir removed after successful sync."""
plugin, mock_cm = _make_plugin()
log = _mock_log()
mock_env = MagicMock()
mock_env.name = "Test"
mock_cm.get_environment.return_value = mock_env
with patch('src.plugins.git_plugin.run_blocking') as mock_run_blocking:
mock_repo = MagicMock()
mock_repo.working_dir = tempfile.mkdtemp()
mock_repo.git = MagicMock()
async def rb_side(kind='file', fn=None, **kwargs):
if kind == 'git' and fn == plugin.git_service.get_repo:
return mock_repo
if kind == 'git' and fn == mock_repo.git.add:
return None
return None
mock_run_blocking.side_effect = rb_side
with patch('src.plugins.git_plugin.SupersetClient') as MockSupersetClient:
mock_client = MagicMock()
MockSupersetClient.return_value = mock_client
mock_client.authenticate = AsyncMock()
mock_client.export_dashboard = AsyncMock(return_value=(b"zip", "ts"))
# Force backup_dir.exists() → True to trigger rmtree cleanup
with patch('pathlib.Path.exists', return_value=True):
result = await plugin._handle_sync(1, log=log, git_log=log, superset_log=log)
assert result["status"] == "success"
@pytest.mark.asyncio
async def test_handle_sync_git_add_failure(self):
"""Edge: git add failure is logged but does not raise."""
plugin, mock_cm = _make_plugin()
log = _mock_log()
mock_env = MagicMock()
mock_env.name = "Test"
mock_cm.get_environment.return_value = mock_env
with patch('src.plugins.git_plugin.run_blocking') as mock_run_blocking:
mock_repo = MagicMock()
mock_repo.working_dir = tempfile.mkdtemp()
mock_repo.git = MagicMock()
mock_repo.git.add = MagicMock()
call_count = 0
async def rb_side(kind='file', fn=None, **kwargs):
nonlocal call_count
call_count += 1
if kind == 'git' and fn == plugin.git_service.get_repo:
return mock_repo
if kind == 'git' and fn == mock_repo.git.add:
raise RuntimeError("git add failed")
return None
mock_run_blocking.side_effect = rb_side
with patch('src.plugins.git_plugin.SupersetClient') as MockSupersetClient:
mock_client = MagicMock()
MockSupersetClient.return_value = mock_client
mock_client.authenticate = AsyncMock()
mock_client.export_dashboard = AsyncMock(return_value=(b"zip", "ts"))
result = await plugin._handle_sync(1, log=log, git_log=log, superset_log=log)
assert result["status"] == "success"
@pytest.mark.asyncio
async def test_handle_sync_backup_restore_on_failure(self):
"""Negative: on unzip failure, backup is restored and error re-raised."""
@@ -554,6 +639,44 @@ class TestHandleDeploy:
assert result["status"] == "success"
assert "deployed" in result["message"].lower()
@pytest.mark.asyncio
async def test_handle_deploy_cleanup_temp_zip(self):
"""Edge: temp zip is cleaned up in finally block after error."""
plugin, mock_cm = _make_plugin()
log = _mock_log()
mock_env = MagicMock()
mock_env.name = "Target"
mock_cm.get_environment.return_value = mock_env
with patch('src.plugins.git_plugin.run_blocking') as mock_run_blocking:
mock_repo = MagicMock()
mock_repo.working_dir = tempfile.mkdtemp()
async def rb_side(kind='file', fn=None, **kwargs):
if kind == 'git' and fn == plugin.git_service.get_repo:
return mock_repo
if fn.__name__ == '_pack_deploy_zip':
return None
if fn == Path.write_bytes:
return None
if fn == Path.exists:
return True
if fn == os.remove:
return None
return None
mock_run_blocking.side_effect = rb_side
with patch('src.plugins.git_plugin.SupersetClient') as MockSupersetClient:
mock_client = MagicMock()
MockSupersetClient.return_value = mock_client
mock_client.authenticate = AsyncMock()
mock_client.import_dashboard = AsyncMock(side_effect=RuntimeError("import failed"))
with pytest.raises(RuntimeError, match="import failed"):
await plugin._handle_deploy(1, "env-1", log=log, git_log=log, superset_log=log)
@pytest.mark.asyncio
async def test_handle_deploy_missing_env_id(self):
"""Negative: empty env_id raises ValueError."""