22import zipfile
33import io
44
5+ import pytest
56from django .core .files .uploadedfile import UploadedFile
67from rest_framework import status
78
89from kirovy import settings , typing as t
9- from kirovy .constants .api_codes import UploadApiCodes
10+ from kirovy .constants .api_codes import UploadApiCodes , FileUploadApiCodes
1011from kirovy .models .cnc_map import CncMapImageFile
1112from kirovy .utils import file_utils
1213from kirovy .models import CncMap , CncMapFile , MapCategory
1314from kirovy .response import KirovyResponse
1415from kirovy .services .cnc_gen_2_services import CncGen2MapParser
16+ from kirovy .views .cnc_map_views import MapImageFileUploadView
1517
1618_UPLOAD_URL = "/maps/upload/"
1719_CLIENT_URL = "/maps/client/upload/"
1820
1921
20- def test_map_file_upload_happy_path (client_user , file_map_desert , game_yuri , extension_map , tmp_media_root ):
22+ def test_map_file_upload_happy_path (
23+ client_user , file_map_desert , game_yuri , extension_map , tmp_media_root , get_file_path_for_uploaded_file_url
24+ ):
2125 response : KirovyResponse = client_user .post (
2226 _UPLOAD_URL ,
2327 {"file" : file_map_desert , "game_id" : str (game_yuri .id )},
@@ -30,11 +34,9 @@ def test_map_file_upload_happy_path(client_user, file_map_desert, game_yuri, ext
3034 uploaded_file_url : str = response .data ["result" ]["cnc_map_file" ]
3135 uploaded_image_url : str = response .data ["result" ]["extracted_preview_file" ]
3236
33- # We need to strip the url path off of the files,
34- # then check the tmp directory to make sure the uploaded files were saved
35- strip_media_url = f"/{ settings .MEDIA_URL } "
36- uploaded_file_path = pathlib .Path (tmp_media_root ) / uploaded_file_url .lstrip (strip_media_url )
37- uploaded_image = pathlib .Path (tmp_media_root ) / uploaded_image_url .lstrip (strip_media_url )
37+ # We need to check the tmp directory to make sure the uploaded files were saved
38+ uploaded_file_path = get_file_path_for_uploaded_file_url (uploaded_file_url )
39+ uploaded_image = get_file_path_for_uploaded_file_url (uploaded_image_url )
3840 assert uploaded_file_path .exists ()
3941 assert uploaded_image .exists ()
4042
@@ -115,3 +117,108 @@ def test_map_file_upload_banned_map(banned_cheat_map, file_map_unfair, client_an
115117 assert response .status_code == status .HTTP_400_BAD_REQUEST
116118 assert response .data ["code" ] == UploadApiCodes .DUPLICATE_MAP
117119 assert response .data ["additional" ]["existing_map_id" ] == str (banned_cheat_map .id )
120+
121+
122+ def test_map_image_upload__happy_path (create_cnc_map , file_map_image , client_user , get_file_path_for_uploaded_file_url ):
123+ """Test that we can upload an image as a verified user, who has created a map"""
124+ cnc_map = create_cnc_map (user_id = client_user .kirovy_user .id , is_legacy = False , is_published = True , is_temporary = False )
125+ original_image_count = cnc_map .cncmapimagefile_set .select_related ().count ()
126+ response = client_user .post (
127+ "/maps/img/" ,
128+ {"file" : file_map_image , "cnc_map_id" : str (cnc_map .id )},
129+ format = "multipart" ,
130+ content_type = None ,
131+ )
132+
133+ assert response .status_code == status .HTTP_201_CREATED
134+ assert response .data ["message" ] == MapImageFileUploadView .success_message
135+ saved_file = CncMapImageFile .objects .get (id = response .data ["result" ]["file_id" ])
136+ image_url : str = response .data ["result" ]["file_url" ]
137+ parent_id : str = response .data ["result" ]["parent_object_id" ]
138+
139+ assert parent_id == cnc_map .id
140+ expected_date = saved_file .created .date ().isoformat ()
141+ assert image_url == f"/silo/yr/map_images/{ cnc_map .id .hex } /{ expected_date } _{ saved_file .id .hex } .png"
142+
143+ assert get_file_path_for_uploaded_file_url (image_url ).exists ()
144+
145+ assert cnc_map .cncmapimagefile_set .select_related ().count () == original_image_count + 1
146+ # Image order starts at 0, then gets incremented, so image_order should be current_count - 1
147+ assert saved_file .image_order == original_image_count
148+ assert saved_file .name == pathlib .Path (file_map_image .name ).name
149+ assert saved_file .file_extension .extension == "png"
150+ # Width and height are from the image itself.
151+ assert saved_file .width == 768
152+ assert saved_file .height == 494
153+
154+
155+ def test_map_image_upload__jpg (create_cnc_map , file_map_image_jpg , client_user , get_file_path_for_uploaded_file_url ):
156+ """Test that we can upload a jpg."""
157+ cnc_map = create_cnc_map (user_id = client_user .kirovy_user .id , is_legacy = False , is_published = True , is_temporary = False )
158+ response = client_user .post (
159+ "/maps/img/" ,
160+ {"file" : file_map_image_jpg , "cnc_map_id" : str (cnc_map .id )},
161+ format = "multipart" ,
162+ content_type = None ,
163+ )
164+
165+ assert response .status_code == status .HTTP_201_CREATED
166+ assert response .data ["message" ] == MapImageFileUploadView .success_message
167+ saved_file = CncMapImageFile .objects .get (id = response .data ["result" ]["file_id" ])
168+ assert saved_file .name == pathlib .Path (file_map_image_jpg .name ).name
169+ assert saved_file .file_extension .extension == "jpg"
170+
171+ # Width and height are from the image itself.
172+ assert saved_file .width == 993
173+ assert saved_file .height == 740
174+
175+
176+ @pytest .mark .parametrize ("map_kwargs" , [{"is_legacy" : True }, {"is_temporary" : True }])
177+ def test_map_image_upload__unsupported_map (create_cnc_map , file_map_image , client_user , map_kwargs ):
178+ """Test that map image uploads fail for legacy and temporary maps."""
179+ cnc_map = create_cnc_map (user_id = client_user .kirovy_user .id , ** map_kwargs )
180+ original_image_count = cnc_map .cncmapimagefile_set .select_related ().count ()
181+ response = client_user .post (
182+ "/maps/img/" ,
183+ {"file" : file_map_image , "cnc_map_id" : str (cnc_map .id )},
184+ format = "multipart" ,
185+ content_type = None ,
186+ )
187+
188+ assert response .status_code == status .HTTP_400_BAD_REQUEST
189+ assert response .data ["message" ] == "Map type does not support custom preview images"
190+ assert response .data ["code" ] == FileUploadApiCodes .UNSUPPORTED
191+
192+ assert cnc_map .cncmapimagefile_set .select_related ().count () == original_image_count
193+
194+
195+ def test_map_image_upload__user_is_banned (create_cnc_map , file_map_image , client_banned ):
196+ """Test that map image uploads fail for banned users."""
197+ cnc_map = create_cnc_map (user_id = client_banned .kirovy_user .id )
198+ original_image_count = cnc_map .cncmapimagefile_set .select_related ().count ()
199+ response = client_banned .post (
200+ "/maps/img/" ,
201+ {"file" : file_map_image , "cnc_map_id" : str (cnc_map .id )},
202+ format = "multipart" ,
203+ content_type = None ,
204+ )
205+
206+ assert response .status_code == status .HTTP_403_FORBIDDEN
207+
208+ assert cnc_map .cncmapimagefile_set .select_related ().count () == original_image_count
209+
210+
211+ def test_map_image_upload__map_is_banned (create_cnc_map , file_map_image , client_user ):
212+ """Test that map image uploads fail for banned maps."""
213+ cnc_map = create_cnc_map (user_id = client_user .kirovy_user .id , is_banned = True )
214+ original_image_count = cnc_map .cncmapimagefile_set .select_related ().count ()
215+ response = client_user .post (
216+ "/maps/img/" ,
217+ {"file" : file_map_image , "cnc_map_id" : str (cnc_map .id )},
218+ format = "multipart" ,
219+ content_type = None ,
220+ )
221+
222+ assert response .status_code == status .HTTP_403_FORBIDDEN
223+
224+ assert cnc_map .cncmapimagefile_set .select_related ().count () == original_image_count
0 commit comments