11import { provideHttpClient } from '@angular/common/http' ;
22import { HttpTestingController , provideHttpClientTesting } from '@angular/common/http/testing' ;
3- import { fakeAsync , flush , TestBed } from '@angular/core/testing' ;
3+ import { TestBed } from '@angular/core/testing' ;
44import { MatSnackBarModule } from '@angular/material/snack-bar' ;
55import { NotificationsService } from './notifications.service' ;
66import { S3Service } from './s3.service' ;
@@ -62,12 +62,8 @@ describe('S3Service', () => {
6262 const fieldName = 'avatar' ;
6363 const rowPrimaryKey = { id : 1 } ;
6464
65- it ( 'should fetch file URL successfully' , fakeAsync ( ( ) => {
66- let result : any ;
67-
68- service . getFileUrl ( connectionId , tableName , fieldName , rowPrimaryKey ) . then ( ( res ) => {
69- result = res ;
70- } ) ;
65+ it ( 'should fetch file URL successfully' , async ( ) => {
66+ const resultPromise = service . getFileUrl ( connectionId , tableName , fieldName , rowPrimaryKey ) ;
7167
7268 const req = httpMock . expectOne (
7369 ( request ) =>
@@ -78,41 +74,34 @@ describe('S3Service', () => {
7874 ) ;
7975 expect ( req . request . method ) . toBe ( 'GET' ) ;
8076 req . flush ( mockFileUrlResponse ) ;
81- flush ( ) ;
8277
78+ const result = await resultPromise ;
8379 expect ( result ) . toEqual ( mockFileUrlResponse ) ;
84- } ) ) ;
80+ } ) ;
8581
86- it ( 'should handle complex primary key' , fakeAsync ( ( ) => {
82+ it ( 'should handle complex primary key' , async ( ) => {
8783 const complexPrimaryKey = { user_id : 1 , org_id : 'abc' } ;
88- let result : any ;
8984
90- service . getFileUrl ( connectionId , tableName , fieldName , complexPrimaryKey ) . then ( ( res ) => {
91- result = res ;
92- } ) ;
85+ const resultPromise = service . getFileUrl ( connectionId , tableName , fieldName , complexPrimaryKey ) ;
9386
9487 const req = httpMock . expectOne (
9588 ( request ) =>
9689 request . url === `/s3/file/${ connectionId } ` &&
9790 request . params . get ( 'rowPrimaryKey' ) === JSON . stringify ( complexPrimaryKey ) ,
9891 ) ;
9992 req . flush ( mockFileUrlResponse ) ;
100- flush ( ) ;
10193
94+ const result = await resultPromise ;
10295 expect ( result ) . toEqual ( mockFileUrlResponse ) ;
103- } ) ) ;
104-
105- it ( 'should show error alert on failure' , fakeAsync ( ( ) => {
106- let result : any ;
96+ } ) ;
10797
108- service . getFileUrl ( connectionId , tableName , fieldName , rowPrimaryKey ) . then ( ( res ) => {
109- result = res ;
110- } ) ;
98+ it ( 'should show error alert on failure' , async ( ) => {
99+ const resultPromise = service . getFileUrl ( connectionId , tableName , fieldName , rowPrimaryKey ) ;
111100
112101 const req = httpMock . expectOne ( ( request ) => request . url === `/s3/file/${ connectionId } ` ) ;
113102 req . flush ( fakeError , { status : 400 , statusText : 'Bad Request' } ) ;
114- flush ( ) ;
115103
104+ const result = await resultPromise ;
116105 expect ( result ) . toBeNull ( ) ;
117106 expect ( fakeNotifications . showAlert ) . toHaveBeenCalledWith (
118107 expect . anything ( ) ,
@@ -122,21 +111,17 @@ describe('S3Service', () => {
122111 } ) ,
123112 expect . any ( Array ) ,
124113 ) ;
125- } ) ) ;
126-
127- it ( 'should return null on error' , fakeAsync ( ( ) => {
128- let result : any = 'not-null' ;
114+ } ) ;
129115
130- service . getFileUrl ( connectionId , tableName , fieldName , rowPrimaryKey ) . then ( ( res ) => {
131- result = res ;
132- } ) ;
116+ it ( 'should return null on error' , async ( ) => {
117+ const resultPromise = service . getFileUrl ( connectionId , tableName , fieldName , rowPrimaryKey ) ;
133118
134119 const req = httpMock . expectOne ( ( request ) => request . url === `/s3/file/${ connectionId } ` ) ;
135120 req . flush ( fakeError , { status : 400 , statusText : 'Bad Request' } ) ;
136- flush ( ) ;
137121
122+ const result = await resultPromise ;
138123 expect ( result ) . toBeNull ( ) ;
139- } ) ) ;
124+ } ) ;
140125 } ) ;
141126
142127 describe ( 'getUploadUrl' , ( ) => {
@@ -146,12 +131,8 @@ describe('S3Service', () => {
146131 const filename = 'document.pdf' ;
147132 const contentType = 'application/pdf' ;
148133
149- it ( 'should fetch upload URL successfully' , fakeAsync ( ( ) => {
150- let result : any ;
151-
152- service . getUploadUrl ( connectionId , tableName , fieldName , filename , contentType ) . then ( ( res ) => {
153- result = res ;
154- } ) ;
134+ it ( 'should fetch upload URL successfully' , async ( ) => {
135+ const resultPromise = service . getUploadUrl ( connectionId , tableName , fieldName , filename , contentType ) ;
155136
156137 const req = httpMock . expectOne (
157138 ( request ) =>
@@ -162,37 +143,34 @@ describe('S3Service', () => {
162143 expect ( req . request . method ) . toBe ( 'POST' ) ;
163144 expect ( req . request . body ) . toEqual ( { filename, contentType } ) ;
164145 req . flush ( mockUploadUrlResponse ) ;
165- flush ( ) ;
166146
147+ const result = await resultPromise ;
167148 expect ( result ) . toEqual ( mockUploadUrlResponse ) ;
168- } ) ) ;
149+ } ) ;
169150
170- it ( 'should handle image upload' , fakeAsync ( ( ) => {
151+ it ( 'should handle image upload' , async ( ) => {
171152 const imageFilename = 'photo.jpg' ;
172153 const imageContentType = 'image/jpeg' ;
173154
174- service . getUploadUrl ( connectionId , tableName , fieldName , imageFilename , imageContentType ) ;
155+ const resultPromise = service . getUploadUrl ( connectionId , tableName , fieldName , imageFilename , imageContentType ) ;
175156
176157 const req = httpMock . expectOne ( ( request ) => request . url === `/s3/upload-url/${ connectionId } ` ) ;
177158 expect ( req . request . body ) . toEqual ( {
178159 filename : imageFilename ,
179160 contentType : imageContentType ,
180161 } ) ;
181162 req . flush ( mockUploadUrlResponse ) ;
182- flush ( ) ;
183- } ) ) ;
184163
185- it ( 'should show error alert on failure' , fakeAsync ( ( ) => {
186- let result : any ;
164+ await resultPromise ;
165+ } ) ;
187166
188- service . getUploadUrl ( connectionId , tableName , fieldName , filename , contentType ) . then ( ( res ) => {
189- result = res ;
190- } ) ;
167+ it ( 'should show error alert on failure' , async ( ) => {
168+ const resultPromise = service . getUploadUrl ( connectionId , tableName , fieldName , filename , contentType ) ;
191169
192170 const req = httpMock . expectOne ( ( request ) => request . url === `/s3/upload-url/${ connectionId } ` ) ;
193171 req . flush ( fakeError , { status : 400 , statusText : 'Bad Request' } ) ;
194- flush ( ) ;
195172
173+ const result = await resultPromise ;
196174 expect ( result ) . toBeNull ( ) ;
197175 expect ( fakeNotifications . showAlert ) . toHaveBeenCalledWith (
198176 expect . anything ( ) ,
@@ -202,73 +180,64 @@ describe('S3Service', () => {
202180 } ) ,
203181 expect . any ( Array ) ,
204182 ) ;
205- } ) ) ;
206-
207- it ( 'should return null on error' , fakeAsync ( ( ) => {
208- let result : any = 'not-null' ;
183+ } ) ;
209184
210- service . getUploadUrl ( connectionId , tableName , fieldName , filename , contentType ) . then ( ( res ) => {
211- result = res ;
212- } ) ;
185+ it ( 'should return null on error' , async ( ) => {
186+ const resultPromise = service . getUploadUrl ( connectionId , tableName , fieldName , filename , contentType ) ;
213187
214188 const req = httpMock . expectOne ( ( request ) => request . url === `/s3/upload-url/${ connectionId } ` ) ;
215189 req . flush ( fakeError , { status : 400 , statusText : 'Bad Request' } ) ;
216- flush ( ) ;
217190
191+ const result = await resultPromise ;
218192 expect ( result ) . toBeNull ( ) ;
219- } ) ) ;
193+ } ) ;
220194 } ) ;
221195
222196 describe ( 'uploadToS3' , ( ) => {
223197 const uploadUrl = 'https://s3.amazonaws.com/bucket/file.pdf?signature=abc123' ;
224198
225- it ( 'should upload file to S3 successfully' , fakeAsync ( ( ) => {
199+ it ( 'should upload file to S3 successfully' , async ( ) => {
226200 const file = new File ( [ 'test content' ] , 'test.pdf' , {
227201 type : 'application/pdf' ,
228202 } ) ;
229- let result : boolean | undefined ;
230203
231- service . uploadToS3 ( uploadUrl , file ) . then ( ( res ) => {
232- result = res ;
233- } ) ;
204+ const resultPromise = service . uploadToS3 ( uploadUrl , file ) ;
234205
235206 const req = httpMock . expectOne ( uploadUrl ) ;
236207 expect ( req . request . method ) . toBe ( 'PUT' ) ;
237208 expect ( req . request . headers . get ( 'Content-Type' ) ) . toBe ( 'application/pdf' ) ;
238209 expect ( req . request . body ) . toBe ( file ) ;
239210 req . flush ( null ) ;
240- flush ( ) ;
241211
212+ const result = await resultPromise ;
242213 expect ( result ) . toBe ( true ) ;
243- } ) ) ;
214+ } ) ;
244215
245- it ( 'should upload image file with correct content type' , fakeAsync ( ( ) => {
216+ it ( 'should upload image file with correct content type' , async ( ) => {
246217 const file = new File ( [ 'image data' ] , 'photo.jpg' , {
247218 type : 'image/jpeg' ,
248219 } ) ;
249220
250- service . uploadToS3 ( uploadUrl , file ) ;
221+ const resultPromise = service . uploadToS3 ( uploadUrl , file ) ;
251222
252223 const req = httpMock . expectOne ( uploadUrl ) ;
253224 expect ( req . request . headers . get ( 'Content-Type' ) ) . toBe ( 'image/jpeg' ) ;
254225 req . flush ( null ) ;
255- flush ( ) ;
256- } ) ) ;
257226
258- it ( 'should show error alert on upload failure' , fakeAsync ( ( ) => {
227+ await resultPromise ;
228+ } ) ;
229+
230+ it ( 'should show error alert on upload failure' , async ( ) => {
259231 const file = new File ( [ 'test content' ] , 'test.pdf' , {
260232 type : 'application/pdf' ,
261233 } ) ;
262- let result : boolean | undefined ;
263234
264- service . uploadToS3 ( uploadUrl , file ) . then ( ( res ) => {
265- result = res ;
266- } ) ;
235+ const resultPromise = service . uploadToS3 ( uploadUrl , file ) ;
267236
268237 const req = httpMock . expectOne ( uploadUrl ) ;
269238 req . flush ( null , { status : 500 , statusText : 'Internal Server Error' } ) ;
270- flush ( ) ;
271239
240+ const result = await resultPromise ;
272241 expect ( result ) . toBe ( false ) ;
273242 expect ( fakeNotifications . showAlert ) . toHaveBeenCalledWith (
274243 expect . anything ( ) ,
@@ -277,40 +246,34 @@ describe('S3Service', () => {
277246 } ) ,
278247 expect . any ( Array ) ,
279248 ) ;
280- } ) ) ;
249+ } ) ;
281250
282- it ( 'should return false on error' , fakeAsync ( ( ) => {
251+ it ( 'should return false on error' , async ( ) => {
283252 const file = new File ( [ 'test content' ] , 'test.pdf' , {
284253 type : 'application/pdf' ,
285254 } ) ;
286- let result : boolean | undefined ;
287255
288- service . uploadToS3 ( uploadUrl , file ) . then ( ( res ) => {
289- result = res ;
290- } ) ;
256+ const resultPromise = service . uploadToS3 ( uploadUrl , file ) ;
291257
292258 const req = httpMock . expectOne ( uploadUrl ) ;
293259 req . flush ( null , { status : 500 , statusText : 'Internal Server Error' } ) ;
294- flush ( ) ;
295260
261+ const result = await resultPromise ;
296262 expect ( result ) . toBe ( false ) ;
297- } ) ) ;
263+ } ) ;
298264 } ) ;
299265
300266 describe ( 'uploadFile' , ( ) => {
301267 const connectionId = 'conn-123' ;
302268 const tableName = 'users' ;
303269 const fieldName = 'avatar' ;
304270
305- it ( 'should get upload URL and upload file successfully' , fakeAsync ( ( ) => {
271+ it ( 'should get upload URL and upload file successfully' , async ( ) => {
306272 const file = new File ( [ 'test content' ] , 'test.pdf' , {
307273 type : 'application/pdf' ,
308274 } ) ;
309- let result : { key : string ; previewUrl : string } | null | undefined ;
310275
311- service . uploadFile ( connectionId , tableName , fieldName , file ) . then ( ( res ) => {
312- result = res ;
313- } ) ;
276+ const resultPromise = service . uploadFile ( connectionId , tableName , fieldName , file ) ;
314277
315278 // First request: get upload URL
316279 const uploadUrlReq = httpMock . expectOne ( ( request ) => request . url === `/s3/upload-url/${ connectionId } ` ) ;
@@ -320,61 +283,59 @@ describe('S3Service', () => {
320283 contentType : 'application/pdf' ,
321284 } ) ;
322285 uploadUrlReq . flush ( mockUploadUrlResponse ) ;
323- flush ( ) ;
286+
287+ // Allow the first promise to resolve so the second request starts
288+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) ) ;
324289
325290 // Second request: upload to S3
326291 const uploadReq = httpMock . expectOne ( mockUploadUrlResponse . uploadUrl ) ;
327292 expect ( uploadReq . request . method ) . toBe ( 'PUT' ) ;
328293 expect ( uploadReq . request . body ) . toBe ( file ) ;
329294 uploadReq . flush ( null ) ;
330- flush ( ) ;
331295
296+ const result = await resultPromise ;
332297 expect ( result ) . toEqual ( {
333298 key : mockUploadUrlResponse . key ,
334299 previewUrl : mockUploadUrlResponse . previewUrl ,
335300 } ) ;
336- } ) ) ;
301+ } ) ;
337302
338- it ( 'should return null if getting upload URL fails' , fakeAsync ( ( ) => {
303+ it ( 'should return null if getting upload URL fails' , async ( ) => {
339304 const file = new File ( [ 'test content' ] , 'test.pdf' , {
340305 type : 'application/pdf' ,
341306 } ) ;
342- let result : { key : string ; previewUrl : string } | null | undefined ;
343307
344- service . uploadFile ( connectionId , tableName , fieldName , file ) . then ( ( res ) => {
345- result = res ;
346- } ) ;
308+ const resultPromise = service . uploadFile ( connectionId , tableName , fieldName , file ) ;
347309
348310 const uploadUrlReq = httpMock . expectOne ( ( request ) => request . url === `/s3/upload-url/${ connectionId } ` ) ;
349311 uploadUrlReq . flush ( fakeError , { status : 400 , statusText : 'Bad Request' } ) ;
350- flush ( ) ;
351312
313+ const result = await resultPromise ;
352314 expect ( result ) . toBeNull ( ) ;
353315 expect ( fakeNotifications . showAlert ) . toHaveBeenCalled ( ) ;
354- } ) ) ;
316+ } ) ;
355317
356- it ( 'should return null if S3 upload fails' , fakeAsync ( ( ) => {
318+ it ( 'should return null if S3 upload fails' , async ( ) => {
357319 const file = new File ( [ 'test content' ] , 'test.pdf' , {
358320 type : 'application/pdf' ,
359321 } ) ;
360- let result : { key : string ; previewUrl : string } | null | undefined ;
361322
362- service . uploadFile ( connectionId , tableName , fieldName , file ) . then ( ( res ) => {
363- result = res ;
364- } ) ;
323+ const resultPromise = service . uploadFile ( connectionId , tableName , fieldName , file ) ;
365324
366325 // First request succeeds
367326 const uploadUrlReq = httpMock . expectOne ( ( request ) => request . url === `/s3/upload-url/${ connectionId } ` ) ;
368327 uploadUrlReq . flush ( mockUploadUrlResponse ) ;
369- flush ( ) ;
328+
329+ // Allow the first promise to resolve so the second request starts
330+ await new Promise ( ( resolve ) => setTimeout ( resolve , 0 ) ) ;
370331
371332 // Second request fails
372333 const uploadReq = httpMock . expectOne ( mockUploadUrlResponse . uploadUrl ) ;
373334 uploadReq . flush ( null , { status : 500 , statusText : 'Internal Server Error' } ) ;
374- flush ( ) ;
375335
336+ const result = await resultPromise ;
376337 expect ( result ) . toBeNull ( ) ;
377338 expect ( fakeNotifications . showAlert ) . toHaveBeenCalled ( ) ;
378- } ) ) ;
339+ } ) ;
379340 } ) ;
380341} ) ;
0 commit comments