1+ from django .urls import reverse
2+ from django .contrib .auth import get_user_model
3+ from rest_framework import status
4+ from rest_framework .test import APITestCase
5+ from unittest .mock import patch
6+
7+ User = get_user_model ()
8+
9+ class DockerAPITests (APITestCase ):
10+ def setUp (self ):
11+ # Create an admin user
12+ self .admin_user = User .objects .create_superuser (
13+ username = 'admin_test' ,
14+ email = 'admin_test@example.com' ,
15+ password = 'admin_password123'
16+ )
17+ # Create a regular user
18+ self .regular_user = User .objects .create_user (
19+ username = 'user_test' ,
20+ email = 'user_test@example.com' ,
21+ password = 'user_password123'
22+ )
23+
24+ self .list_containers_url = reverse ('docker-list-containers' )
25+ # URL for GetDockerContainerPathsView (needs a placeholder container_id)
26+ self .container_paths_url_template = reverse ('docker-container-paths' , kwargs = {'container_id' : 'PLACEHOLDER_ID' })
27+
28+ def test_list_docker_containers_permissions_and_basic_success (self ):
29+ """
30+ Test permissions for the list_docker_containers endpoint and a basic success scenario.
31+ """
32+ # 1. Test unauthenticated access
33+ response = self .client .get (self .list_containers_url )
34+ self .assertEqual (response .status_code , status .HTTP_401_UNAUTHORIZED )
35+
36+ # 2. Test access with regular user (should be forbidden)
37+ self .client .force_authenticate (user = self .regular_user )
38+ response = self .client .get (self .list_containers_url )
39+ self .assertEqual (response .status_code , status .HTTP_403_FORBIDDEN )
40+ self .client .force_authenticate (user = None ) # Clear authentication
41+
42+ # 3. Test access with admin user (should be successful)
43+ # We mock the actual service call to avoid real Docker interaction
44+ mock_container_data = [
45+ {"id" : "abc123xyz" , "name" : "test_container_1" , "image" : "test_image:latest" , "status" : "running" },
46+ {"id" : "def456uvw" , "name" : "test_container_2" , "image" : "another_image:1.0" , "status" : "running" }
47+ ]
48+
49+ with patch ('core.views.list_running_containers' ) as mock_list_containers :
50+ mock_list_containers .return_value = mock_container_data
51+
52+ self .client .force_authenticate (user = self .admin_user )
53+ response = self .client .get (self .list_containers_url )
54+
55+ self .assertEqual (response .status_code , status .HTTP_200_OK )
56+ self .assertEqual (len (response .data ), 2 )
57+ self .assertEqual (response .data [0 ]['name' ], 'test_container_1' )
58+ mock_list_containers .assert_called_once () # Ensure our service function was called
59+
60+ def test_list_docker_containers_service_error (self ):
61+ """
62+ Test the list_docker_containers endpoint when the service returns an error.
63+ """
64+ error_message = "Docker API error: Connection refused"
65+ with patch ('core.views.list_running_containers' ) as mock_list_containers :
66+ mock_list_containers .return_value = error_message
67+
68+ self .client .force_authenticate (user = self .admin_user )
69+ response = self .client .get (self .list_containers_url )
70+
71+ self .assertEqual (response .status_code , status .HTTP_500_INTERNAL_SERVER_ERROR )
72+ self .assertIn ('error' , response .data )
73+ self .assertEqual (response .data ['error' ], error_message )
74+ mock_list_containers .assert_called_once ()
75+
76+ def test_get_container_paths_permissions_and_success (self ):
77+ """
78+ Test permissions and basic success scenario for GetDockerContainerPathsView.
79+ """
80+ test_container_id = "test_container_123"
81+ specific_container_paths_url = self .container_paths_url_template .replace ('PLACEHOLDER_ID' , test_container_id )
82+
83+ # 1. Test unauthenticated access
84+ response = self .client .get (specific_container_paths_url )
85+ self .assertEqual (response .status_code , status .HTTP_401_UNAUTHORIZED )
86+
87+ # 2. Test access with regular user (should be forbidden)
88+ self .client .force_authenticate (user = self .regular_user )
89+ response = self .client .get (specific_container_paths_url )
90+ self .assertEqual (response .status_code , status .HTTP_403_FORBIDDEN )
91+ self .client .force_authenticate (user = None ) # Clear authentication
92+
93+ # 3. Test access with admin user (should be successful)
94+ mock_path_data = ['/mnt/code/project_a' , '/var/www/html' ]
95+ with patch ('core.views.get_container_code_paths' ) as mock_get_paths :
96+ mock_get_paths .return_value = mock_path_data
97+
98+ self .client .force_authenticate (user = self .admin_user )
99+ response = self .client .get (specific_container_paths_url )
100+
101+ self .assertEqual (response .status_code , status .HTTP_200_OK )
102+ self .assertEqual (len (response .data ), 2 )
103+ self .assertEqual (response .data [0 ], '/mnt/code/project_a' )
104+ # Ensure the service function was called with the correct container_id
105+ mock_get_paths .assert_called_once_with (test_container_id )
106+
107+ def test_get_container_paths_not_found (self ):
108+ """
109+ Test GetDockerContainerPathsView when the container is not found.
110+ """
111+ test_container_id = "non_existent_container"
112+ specific_container_paths_url = self .container_paths_url_template .replace ('PLACEHOLDER_ID' , test_container_id )
113+ error_message = f"Container '{ test_container_id } ' not found."
114+
115+ with patch ('core.views.get_container_code_paths' ) as mock_get_paths :
116+ mock_get_paths .return_value = error_message
117+
118+ self .client .force_authenticate (user = self .admin_user )
119+ response = self .client .get (specific_container_paths_url )
120+
121+ self .assertEqual (response .status_code , status .HTTP_404_NOT_FOUND )
122+ self .assertIn ('error' , response .data )
123+ self .assertEqual (response .data ['error' ], error_message )
124+ mock_get_paths .assert_called_once_with (test_container_id )
125+
126+ def test_get_container_paths_service_error (self ):
127+ """
128+ Test GetDockerContainerPathsView when the service returns a generic error.
129+ """
130+ test_container_id = "another_container_id"
131+ specific_container_paths_url = self .container_paths_url_template .replace ('PLACEHOLDER_ID' , test_container_id )
132+ error_message = "Docker API error: Unexpected issue"
133+
134+ with patch ('core.views.get_container_code_paths' ) as mock_get_paths :
135+ mock_get_paths .return_value = error_message
136+
137+ self .client .force_authenticate (user = self .admin_user )
138+ response = self .client .get (specific_container_paths_url )
139+
140+ self .assertEqual (response .status_code , status .HTTP_500_INTERNAL_SERVER_ERROR )
141+ self .assertIn ('error' , response .data )
142+ self .assertEqual (response .data ['error' ], error_message )
143+ mock_get_paths .assert_called_once_with (test_container_id )
144+
145+ # Additional test methods for GetDockerContainerPathsView will be added here
146+ # and for error cases of ListDockerContainersView.
0 commit comments