11from __future__ import annotations
22
3- from time import sleep
3+ from dataclasses import dataclass
44from typing import TYPE_CHECKING
55from uuid import uuid4
66
1010from storage3 .utils import StorageException
1111
1212from .. import AsyncBucketProxy
13+ from ..utils import AsyncClient as HttpxClient
1314from ..utils import AsyncFinalizerFactory
1415
1516if TYPE_CHECKING :
@@ -52,6 +53,12 @@ async def afinalizer():
5253 request .addfinalizer (AsyncFinalizerFactory (afinalizer ).finalizer )
5354
5455
56+ async def bucket_factory (
57+ storage : AsyncStorageClient , uuid_factory : Callable [[], str ], public : bool
58+ ) -> str :
59+ """Creates a test bucket which will be used in the whole storage tests run and deleted at the end"""
60+
61+
5562@pytest .fixture (scope = "module" )
5663async def bucket (storage : AsyncStorageClient , uuid_factory : Callable [[], str ]) -> str :
5764 """Creates a test bucket which will be used in the whole storage tests run and deleted at the end"""
@@ -71,14 +78,53 @@ async def bucket(storage: AsyncStorageClient, uuid_factory: Callable[[], str]) -
7178 temp_test_buckets_ids .remove (bucket_id )
7279
7380
81+ @pytest .fixture (scope = "module" )
82+ async def public_bucket (
83+ storage : AsyncStorageClient , uuid_factory : Callable [[], str ]
84+ ) -> str :
85+ """Creates a test public bucket which will be used in the whole storage tests run and deleted at the end"""
86+ bucket_id = uuid_factory ()
87+
88+ # Store bucket_id in global list
89+ global temp_test_buckets_ids
90+ temp_test_buckets_ids .append (bucket_id )
91+
92+ await storage .create_bucket (id = bucket_id , public = True )
93+
94+ yield bucket_id
95+
96+ await storage .empty_bucket (bucket_id )
97+ await storage .delete_bucket (bucket_id )
98+
99+ temp_test_buckets_ids .remove (bucket_id )
100+
101+
74102@pytest .fixture (scope = "module" )
75103def storage_file_client (storage : AsyncStorageClient , bucket : str ) -> AsyncBucketProxy :
76104 """Creates the storage file client for the whole storage tests run"""
77105 yield storage .from_ (bucket )
78106
79107
108+ @pytest .fixture (scope = "module" )
109+ def storage_file_client_public (
110+ storage : AsyncStorageClient , public_bucket : str
111+ ) -> AsyncBucketProxy :
112+ """Creates the storage file client for the whole storage tests run"""
113+ yield storage .from_ (public_bucket )
114+
115+
116+ @dataclass
117+ class FileForTesting :
118+ name : str
119+ local_path : str
120+ bucket_folder : str
121+ bucket_path : str
122+ mime_type : str
123+ file_content : bytes
124+
125+
80126@pytest .fixture
81- def file (tmp_path : Path , uuid_factory : Callable [[], str ]) -> dict [ str , str ] :
127+ def file (tmp_path : Path , uuid_factory : Callable [[], str ]) -> FileForTesting :
82128 """Creates a different test file (same content but different path) for each test"""
83129 file_name = "test_image.svg"
84130 file_content = (
@@ -100,39 +146,66 @@ def file(tmp_path: Path, uuid_factory: Callable[[], str]) -> dict[str, str]:
100146 with open (file_path , "wb" ) as f :
101147 f .write (file_content )
102148
103- return {
104- " name" : file_name ,
105- " local_path" : str (file_path ),
106- " bucket_folder" : bucket_folder ,
107- " bucket_path" : bucket_path ,
108- " mime_type" : "image/svg+xml" ,
109- " file_content" : file_content ,
110- }
149+ return FileForTesting (
150+ name = file_name ,
151+ local_path = str (file_path ),
152+ bucket_folder = bucket_folder ,
153+ bucket_path = bucket_path ,
154+ mime_type = "image/svg+xml" ,
155+ file_content = file_content ,
156+ )
111157
112158
113159# TODO: Test create_bucket, delete_bucket, empty_bucket, list_buckets, fileAPI.list before upload test
114160
115161
116- async def test_client_upload_file (
117- storage_file_client : AsyncBucketProxy , file : dict [ str , str ]
162+ async def test_client_upload (
163+ storage_file_client : AsyncBucketProxy , file : FileForTesting
118164) -> None :
119165 """Ensure we can upload files to a bucket"""
166+ await storage_file_client .upload (
167+ file .bucket_path , file .local_path , {"content-type" : file .mime_type }
168+ )
169+
170+ image = await storage_file_client .download (file .bucket_path )
171+ files = await storage_file_client .list (file .bucket_folder )
172+ image_info = next ((f for f in files if f .get ("name" ) == file .name ), None )
173+
174+ assert image == file .file_content
175+ assert image_info .get ("metadata" , {}).get ("mimetype" ) == file .mime_type
120176
121- file_name = file ["name" ]
122- file_path = file ["local_path" ]
123- mime_type = file ["mime_type" ]
124- file_content = file ["file_content" ]
125- bucket_file_path = file ["bucket_path" ]
126- bucket_folder = file ["bucket_folder" ]
127- options = {"content-type" : mime_type }
128177
129- await storage_file_client .upload (bucket_file_path , file_path , options )
178+ async def test_client_create_signed_url (
179+ storage_file_client : AsyncBucketProxy , file : FileForTesting
180+ ) -> None :
181+ """Ensure we can create a signed url for a file in a bucket"""
182+ await storage_file_client .upload (
183+ file .bucket_path , file .local_path , {"content-type" : file .mime_type }
184+ )
185+
186+ signed_url = (await storage_file_client .create_signed_url (file .bucket_path , 10 ))[
187+ "signedURL"
188+ ]
189+
190+ async with HttpxClient () as client :
191+ response = await client .get (signed_url )
192+ response .raise_for_status ()
193+
194+ assert response .content == file .file_content
195+
196+
197+ async def test_client_get_public_url (
198+ storage_file_client_public : AsyncBucketProxy , file : FileForTesting
199+ ) -> None :
200+ """Ensure we can get the public url of a file in a bucket"""
201+ await storage_file_client_public .upload (
202+ file .bucket_path , file .local_path , {"content-type" : file .mime_type }
203+ )
130204
131- sleep ( 3 )
205+ public_url = await storage_file_client_public . get_public_url ( file . bucket_path )
132206
133- image = await storage_file_client . download ( bucket_file_path )
134- files = await storage_file_client . list ( bucket_folder )
135- image_info = next (( f for f in files if f . get ( "name" ) == file_name ), None )
207+ async with HttpxClient ( timeout = None ) as client :
208+ response = await client . get ( public_url )
209+ response . raise_for_status ( )
136210
137- assert image == file_content
138- assert image_info .get ("metadata" , {}).get ("mimetype" ) == mime_type
211+ assert response .content == file .file_content
0 commit comments