Files
docker-swarm-termina/backend/tests/test_exec.py
Claude 1f1608e081 Achieve 88% test coverage with all tests passing
**Test Improvements:**
- Fixed all mock patch paths for refactored module structure
- Updated patches to target where functions are used, not defined
- Added test_coverage_boost.py with 9 new tests for exception handling

**Coverage Breakdown:**
- All routes: 100% coverage 
- Main app & config: 100% coverage 
- Most utilities: 89-100% coverage
- Handler logic: 38-100% coverage (edge cases remain)

**Test Results:**
- Total tests: 88/88 passing 
- Coverage: 88% (up from 62%)
- All critical paths covered
- Remaining 12% is error handling and diagnostics

**Uncovered Code:**
- Terminal disconnect cleanup (38%)
- Terminal input error paths (77%)
- Docker diagnostics (58%)
- Thread error handling (78%)

These are defensive code paths that are difficult to test
in isolation but don't affect core functionality.

https://claude.ai/code/session_011PzvkCnVrsatoxbY3HbGXz
2026-02-01 05:34:39 +00:00

125 lines
4.7 KiB
Python

import pytest
from unittest.mock import MagicMock, patch
class TestContainerExec:
"""Test container command execution"""
def test_exec_unauthorized(self, client):
"""Test exec without auth"""
response = client.post('/api/containers/abc123/exec', json={
'command': 'ls'
})
assert response.status_code == 401
@patch('routes.containers.exec.get_docker_client')
def test_exec_simple_command(self, mock_get_client, client, auth_headers, auth_token):
"""Test executing a simple command"""
# Mock exec result
mock_exec_result = MagicMock()
mock_exec_result.output = b'file1.txt\nfile2.txt\n::WORKDIR::/app'
mock_exec_result.exit_code = 0
mock_container = MagicMock()
mock_container.exec_run.return_value = mock_exec_result
mock_client = MagicMock()
mock_client.containers.get.return_value = mock_container
mock_get_client.return_value = mock_client
response = client.post('/api/containers/abc123/exec',
headers=auth_headers,
json={'command': 'ls'})
assert response.status_code == 200
data = response.get_json()
assert data['exit_code'] == 0
assert 'file1.txt' in data['output']
assert data['workdir'] == '/app'
@patch('routes.containers.exec.get_docker_client')
def test_exec_cd_command(self, mock_get_client, client, auth_headers, auth_token):
"""Test executing cd command"""
# Mock exec result for cd command
mock_exec_result = MagicMock()
mock_exec_result.output = b'/home/user\n'
mock_exec_result.exit_code = 0
mock_container = MagicMock()
mock_container.exec_run.return_value = mock_exec_result
mock_client = MagicMock()
mock_client.containers.get.return_value = mock_container
mock_get_client.return_value = mock_client
response = client.post('/api/containers/abc123/exec',
headers=auth_headers,
json={'command': 'cd /home/user'})
assert response.status_code == 200
data = response.get_json()
assert data['exit_code'] == 0
assert data['workdir'] == '/home/user'
assert data['output'] == ''
@patch('routes.containers.exec.get_docker_client')
def test_exec_command_with_error(self, mock_get_client, client, auth_headers, auth_token):
"""Test executing a command that fails"""
# Mock exec result with error
mock_exec_result = MagicMock()
mock_exec_result.output = b'command not found::WORKDIR::/app'
mock_exec_result.exit_code = 127
mock_container = MagicMock()
mock_container.exec_run.return_value = mock_exec_result
mock_client = MagicMock()
mock_client.containers.get.return_value = mock_container
mock_get_client.return_value = mock_client
response = client.post('/api/containers/abc123/exec',
headers=auth_headers,
json={'command': 'invalidcommand'})
assert response.status_code == 200
data = response.get_json()
assert data['exit_code'] == 127
assert 'command not found' in data['output']
@patch('routes.containers.exec.get_docker_client')
def test_exec_docker_unavailable(self, mock_get_client, client, auth_headers):
"""Test exec when Docker is unavailable"""
mock_get_client.return_value = None
response = client.post('/api/containers/abc123/exec',
headers=auth_headers,
json={'command': 'ls'})
assert response.status_code == 500
data = response.get_json()
assert 'error' in data
@patch('routes.containers.exec.get_docker_client')
def test_exec_unicode_handling(self, mock_get_client, client, auth_headers, auth_token):
"""Test exec with unicode output"""
# Mock exec result with unicode
mock_exec_result = MagicMock()
mock_exec_result.output = 'Hello 世界\n::WORKDIR::/app'.encode('utf-8')
mock_exec_result.exit_code = 0
mock_container = MagicMock()
mock_container.exec_run.return_value = mock_exec_result
mock_client = MagicMock()
mock_client.containers.get.return_value = mock_container
mock_get_client.return_value = mock_client
response = client.post('/api/containers/abc123/exec',
headers=auth_headers,
json={'command': 'echo "Hello 世界"'})
assert response.status_code == 200
data = response.get_json()
assert data['exit_code'] == 0
assert '世界' in data['output']