11from __future__ import annotations
22
3+ from dataclasses import dataclass
34from time import sleep
45from typing import TYPE_CHECKING
56from uuid import uuid4
1011from storage3 .utils import StorageException
1112
1213from .. import AsyncBucketProxy
14+ from ..utils import AsyncClient as HttpxClient
1315from ..utils import AsyncFinalizerFactory
1416
1517if TYPE_CHECKING :
@@ -52,6 +54,12 @@ async def afinalizer():
5254 request .addfinalizer (AsyncFinalizerFactory (afinalizer ).finalizer )
5355
5456
57+ async def bucket_factory (
58+ storage : AsyncStorageClient , uuid_factory : Callable [[], str ], public : bool
59+ ) -> str :
60+ """Creates a test bucket which will be used in the whole storage tests run and deleted at the end"""
61+
62+
5563@pytest .fixture (scope = "module" )
5664async def bucket (storage : AsyncStorageClient , uuid_factory : Callable [[], str ]) -> str :
5765 """Creates a test bucket which will be used in the whole storage tests run and deleted at the end"""
@@ -71,14 +79,53 @@ async def bucket(storage: AsyncStorageClient, uuid_factory: Callable[[], str]) -
7179 temp_test_buckets_ids .remove (bucket_id )
7280
7381
82+ @pytest .fixture (scope = "module" )
83+ async def public_bucket (
84+ storage : AsyncStorageClient , uuid_factory : Callable [[], str ]
85+ ) -> str :
86+ """Creates a test public bucket which will be used in the whole storage tests run and deleted at the end"""
87+ bucket_id = uuid_factory ()
88+
89+ # Store bucket_id in global list
90+ global temp_test_buckets_ids
91+ temp_test_buckets_ids .append (bucket_id )
92+
93+ await storage .create_bucket (id = bucket_id , public = True )
94+
95+ yield bucket_id
96+
97+ await storage .empty_bucket (bucket_id )
98+ await storage .delete_bucket (bucket_id )
99+
100+ temp_test_buckets_ids .remove (bucket_id )
101+
102+
74103@pytest .fixture (scope = "module" )
75104def storage_file_client (storage : AsyncStorageClient , bucket : str ) -> AsyncBucketProxy :
76105 """Creates the storage file client for the whole storage tests run"""
77106 yield storage .from_ (bucket )
78107
79108
109+ @pytest .fixture (scope = "module" )
110+ def storage_file_client_public (
111+ storage : AsyncStorageClient , public_bucket : str
112+ ) -> AsyncBucketProxy :
113+ """Creates the storage file client for the whole storage tests run"""
114+ yield storage .from_ (public_bucket )
115+
116+
117+ @dataclass
118+ class FileForTesting :
119+ name : str
120+ local_path : str
121+ bucket_folder : str
122+ bucket_path : str
123+ mime_type : str
124+ file_content : bytes
125+
126+
80127@pytest .fixture
81- def file (tmp_path : Path , uuid_factory : Callable [[], str ]) -> dict [ str , str ] :
128+ def file (tmp_path : Path , uuid_factory : Callable [[], str ]) -> FileForTesting :
82129 """Creates a different test file (same content but different path) for each test"""
83130 file_name = "test_image.svg"
84131 file_content = (
@@ -100,39 +147,72 @@ def file(tmp_path: Path, uuid_factory: Callable[[], str]) -> dict[str, str]:
100147 with open (file_path , "wb" ) as f :
101148 f .write (file_content )
102149
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- }
150+ return FileForTesting (
151+ name = file_name ,
152+ local_path = str (file_path ),
153+ bucket_folder = bucket_folder ,
154+ bucket_path = bucket_path ,
155+ mime_type = "image/svg+xml" ,
156+ file_content = file_content ,
157+ )
111158
112159
113160# TODO: Test create_bucket, delete_bucket, empty_bucket, list_buckets, fileAPI.list before upload test
114161
115162
116- async def test_client_upload_file (
117- storage_file_client : AsyncBucketProxy , file : dict [ str , str ]
163+ async def test_client_upload (
164+ storage_file_client : AsyncBucketProxy , file : FileForTesting
118165) -> None :
119166 """Ensure we can upload files to a bucket"""
167+ await storage_file_client .upload (
168+ file .bucket_path , file .local_path , {"content-type" : file .mime_type }
169+ )
120170
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 }
171+ sleep (3 )
128172
129- await storage_file_client .upload (bucket_file_path , file_path , options )
173+ image = await storage_file_client .download (file .bucket_path )
174+ files = await storage_file_client .list (file .bucket_folder )
175+ image_info = next ((f for f in files if f .get ("name" ) == file .name ), None )
176+
177+ assert image == file .file_content
178+ assert image_info .get ("metadata" , {}).get ("mimetype" ) == file .mime_type
179+
180+
181+ async def test_client_create_signed_url (
182+ storage_file_client : AsyncBucketProxy , file : FileForTesting
183+ ) -> None :
184+ """Ensure we can create a signed url for a file in a bucket"""
185+ await storage_file_client .upload (
186+ file .bucket_path , file .local_path , {"content-type" : file .mime_type }
187+ )
130188
131189 sleep (3 )
132190
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 )
191+ signed_url = (await storage_file_client .create_signed_url (file .bucket_path , 10 ))[
192+ "signedURL"
193+ ]
194+
195+ async with HttpxClient () as client :
196+ response = await client .get (signed_url )
197+ response .raise_for_status ()
198+
199+ assert response .content == file .file_content
200+
201+
202+ async def test_client_get_public_url (
203+ storage_file_client_public : AsyncBucketProxy , file : FileForTesting
204+ ) -> None :
205+ """Ensure we can get the public url of a file in a bucket"""
206+ await storage_file_client_public .upload (
207+ file .bucket_path , file .local_path , {"content-type" : file .mime_type }
208+ )
209+
210+ sleep (3 )
211+
212+ public_url = await storage_file_client_public .get_public_url (file .bucket_path )
213+
214+ async with HttpxClient () as client :
215+ response = await client .get (public_url )
216+ response .raise_for_status ()
136217
137- assert image == file_content
138- assert image_info .get ("metadata" , {}).get ("mimetype" ) == mime_type
218+ assert response .content == file .file_content
0 commit comments