11from unittest .mock import ANY
2- from uuid import UUID
32
43import pytest
54
65from app .db .model import Asset , Entity
76from app .db .types import AssetLabel , AssetStatus , EntityType
87from app .errors import ApiErrorCode
9- from app .routers .asset import EntityRoute
108from app .schemas .api import ErrorResponse
119from app .schemas .asset import AssetRead
1210from app .utils .s3 import build_s3_path
1816 VIRTUAL_LAB_ID ,
1917 add_db ,
2018 create_reconstruction_morphology_id ,
19+ route ,
20+ upload_entity_asset ,
2121)
2222
2323DIFFERENT_ENTITY_TYPE = "experimental_bouton_density"
2727FILE_EXAMPLE_SIZE = 31
2828
2929
30- def _entity_type_to_route (entity_type : EntityType ) -> EntityRoute :
31- return EntityRoute [entity_type .name ]
32-
33-
34- def _route (entity_type : EntityType ) -> str :
35- return f"/{ _entity_type_to_route (entity_type )} "
36-
37-
38- def _upload_entity_asset (
39- client , entity_type : EntityType , entity_id : UUID , label : str | None = None
40- ):
41- with FILE_EXAMPLE_PATH .open ("rb" ) as f :
42- files = {
43- # (filename, file (or bytes), content_type, headers)
44- "file" : ("a/b/c.txt" , f , "text/plain" )
45- }
46- data = None
47- if label :
48- data = {"label" : label }
49- return client .post (f"{ _route (entity_type )} /{ entity_id } /assets" , files = files , data = data )
50-
51-
5230def _get_expected_full_path (entity , path ):
5331 return build_s3_path (
5432 vlab_id = VIRTUAL_LAB_ID ,
@@ -73,6 +51,17 @@ def entity(client, species_id, strain_id, brain_region_id) -> Entity:
7351 return Entity (id = entity_id , type = entity_type )
7452
7553
54+ def _upload_entity_asset (client , entity_type , entity_id , label = None ):
55+ with FILE_EXAMPLE_PATH .open ("rb" ) as f :
56+ files = {
57+ # (filename, file (or bytes), content_type, headers)
58+ "file" : ("a/b/c.txt" , f , "text/plain" )
59+ }
60+ return upload_entity_asset (
61+ client = client , entity_type = entity_type , entity_id = entity_id , files = files , label = label
62+ )
63+
64+
7665@pytest .fixture
7766def asset (client , entity ) -> AssetRead :
7867 response = _upload_entity_asset (client , entity_type = entity .type , entity_id = entity .id )
@@ -178,7 +167,7 @@ def test_upload_entity_asset__label(monkeypatch, client, entity):
178167
179168
180169def test_get_entity_asset (client , entity , asset ):
181- response = client .get (f"{ _route (entity .type )} /{ entity .id } /assets/{ asset .id } " )
170+ response = client .get (f"{ route (entity .type )} /{ entity .id } /assets/{ asset .id } " )
182171
183172 assert response .status_code == 200 , f"Failed to get asset: { response .text } "
184173 data = response .json ()
@@ -197,20 +186,20 @@ def test_get_entity_asset(client, entity, asset):
197186 }
198187
199188 # try to get an asset with non-existent entity id
200- response = client .get (f"{ _route (entity .type )} /{ MISSING_ID } /assets/{ asset .id } " )
189+ response = client .get (f"{ route (entity .type )} /{ MISSING_ID } /assets/{ asset .id } " )
201190 assert response .status_code == 404 , f"Unexpected result: { response .text } "
202191 error = ErrorResponse .model_validate (response .json ())
203192 assert error .error_code == ApiErrorCode .ENTITY_NOT_FOUND
204193
205194 # try to get an asset with non-existent asset id
206- response = client .get (f"{ _route (entity .type )} /{ entity .id } /assets/{ MISSING_ID } " )
195+ response = client .get (f"{ route (entity .type )} /{ entity .id } /assets/{ MISSING_ID } " )
207196 assert response .status_code == 404 , f"Unexpected result: { response .text } "
208197 error = ErrorResponse .model_validate (response .json ())
209198 assert error .error_code == ApiErrorCode .ASSET_NOT_FOUND
210199
211200
212201def test_get_entity_assets (client , entity , asset ):
213- response = client .get (f"{ _route (entity .type )} /{ entity .id } /assets" )
202+ response = client .get (f"{ route (entity .type )} /{ entity .id } /assets" )
214203
215204 assert response .status_code == 200 , f"Failed to get asset: { response .text } "
216205 data = response .json ()["data" ]
@@ -231,15 +220,15 @@ def test_get_entity_assets(client, entity, asset):
231220 ]
232221
233222 # try to get assets with non-existent entity id
234- response = client .get (f"{ _route (entity .type )} /{ MISSING_ID } /assets" )
223+ response = client .get (f"{ route (entity .type )} /{ MISSING_ID } /assets" )
235224 assert response .status_code == 404 , f"Unexpected result: { response .text } "
236225 error = ErrorResponse .model_validate (response .json ())
237226 assert error .error_code == ApiErrorCode .ENTITY_NOT_FOUND
238227
239228
240229def test_download_entity_asset (client , entity , asset ):
241230 response = client .get (
242- f"{ _route (entity .type )} /{ entity .id } /assets/{ asset .id } /download" ,
231+ f"{ route (entity .type )} /{ entity .id } /assets/{ asset .id } /download" ,
243232 follow_redirects = False ,
244233 )
245234
@@ -250,20 +239,20 @@ def test_download_entity_asset(client, entity, asset):
250239 assert expected_params .issubset (response .next_request .url .params )
251240
252241 # try to download an asset with non-existent entity id
253- response = client .get (f"{ _route (entity .type )} /{ MISSING_ID } /assets/{ asset .id } /download" )
242+ response = client .get (f"{ route (entity .type )} /{ MISSING_ID } /assets/{ asset .id } /download" )
254243 assert response .status_code == 404 , f"Unexpected result: { response .text } "
255244 error = ErrorResponse .model_validate (response .json ())
256245 assert error .error_code == ApiErrorCode .ENTITY_NOT_FOUND
257246
258247 # try to download an asset with non-existent asset id
259- response = client .get (f"{ _route (entity .type )} /{ entity .id } /assets/{ MISSING_ID } /download" )
248+ response = client .get (f"{ route (entity .type )} /{ entity .id } /assets/{ MISSING_ID } /download" )
260249 assert response .status_code == 404 , f"Unexpected result: { response .text } "
261250 error = ErrorResponse .model_validate (response .json ())
262251 assert error .error_code == ApiErrorCode .ASSET_NOT_FOUND
263252
264253 # when downloading a single file asset_path should not be passed as a parameter
265254 response = client .get (
266- f"{ _route (entity .type )} /{ entity .id } /assets/{ asset .id } /download" ,
255+ f"{ route (entity .type )} /{ entity .id } /assets/{ asset .id } /download" ,
267256 params = {"asset_path" : "foo" },
268257 follow_redirects = False ,
269258 )
@@ -273,21 +262,21 @@ def test_download_entity_asset(client, entity, asset):
273262
274263
275264def test_delete_entity_asset (client , entity , asset ):
276- response = client .delete (f"{ _route (entity .type )} /{ entity .id } /assets/{ asset .id } " )
265+ response = client .delete (f"{ route (entity .type )} /{ entity .id } /assets/{ asset .id } " )
277266 assert response .status_code == 200 , f"Failed to delete asset: { response .text } "
278267 data = response .json ()
279268 assert data == asset .model_copy (update = {"status" : AssetStatus .DELETED }).model_dump (mode = "json" )
280269
281270 # try to delete again the same asset
282- response = client .delete (f"{ _route (entity .type )} /{ entity .id } /assets/{ asset .id } " )
271+ response = client .delete (f"{ route (entity .type )} /{ entity .id } /assets/{ asset .id } " )
283272 assert response .status_code == 404 , f"Unexpected result: { response .text } "
284273
285274 # try to delete an asset with non-existent entity id
286- response = client .delete (f"{ _route (entity .type )} /{ MISSING_ID } /assets/{ asset .id } " )
275+ response = client .delete (f"{ route (entity .type )} /{ MISSING_ID } /assets/{ asset .id } " )
287276 assert response .status_code == 404 , f"Unexpected result: { response .text } "
288277
289278 # try to delete an asset with non-existent asset id
290- response = client .delete (f"{ _route (entity .type )} /{ entity .id } /assets/{ MISSING_ID } " )
279+ response = client .delete (f"{ route (entity .type )} /{ entity .id } /assets/{ MISSING_ID } " )
291280 assert response .status_code == 404 , f"Unexpected result: { response .text } "
292281
293282
@@ -297,7 +286,7 @@ def test_upload_delete_upload_entity_asset(client, entity):
297286 data = response .json ()
298287 asset0 = AssetRead .model_validate (data )
299288
300- response = client .delete (f"{ _route (entity .type )} /{ entity .id } /assets/{ asset0 .id } " )
289+ response = client .delete (f"{ route (entity .type )} /{ entity .id } /assets/{ asset0 .id } " )
301290 assert response .status_code == 200 , f"Failed to delete asset: { response .text } "
302291
303292 # upload the asset with the same path
@@ -307,7 +296,7 @@ def test_upload_delete_upload_entity_asset(client, entity):
307296 asset1 = AssetRead .model_validate (data )
308297
309298 # test that the deleted assets are filtered out
310- response = client .get (f"{ _route (entity .type )} /{ entity .id } /assets" )
299+ response = client .get (f"{ route (entity .type )} /{ entity .id } /assets" )
311300
312301 assert response .status_code == 200 , f"Failed to get assest: { response .text } "
313302 data = response .json ()["data" ]
@@ -320,15 +309,15 @@ def test_upload_delete_upload_entity_asset(client, entity):
320309
321310def test_download_directory_file (client , entity , asset_directory ):
322311 response = client .get (
323- url = f"{ _route (entity .type )} /{ entity .id } /assets/{ asset_directory .id } /download" ,
312+ url = f"{ route (entity .type )} /{ entity .id } /assets/{ asset_directory .id } /download" ,
324313 params = {"asset_path" : "file1.txt" },
325314 follow_redirects = False ,
326315 )
327316 assert response .status_code == 307 , f"Failed to download directory file: { response .text } "
328317
329318 # asset_path is mandatory if the asset is a direcotory
330319 response = client .get (
331- url = f"{ _route (entity .type )} /{ entity .id } /assets/{ asset_directory .id } /download" ,
320+ url = f"{ route (entity .type )} /{ entity .id } /assets/{ asset_directory .id } /download" ,
332321 follow_redirects = False ,
333322 )
334323 assert response .status_code == 409 , (
0 commit comments