@@ -341,6 +341,63 @@ describe("uploadFile function", () => {
341341 expect ( formData . get ( "streamable" ) ) . toBe ( "true" ) ;
342342 } ) ;
343343
344+ it ( "should upload file with expires_at timestamp" , async ( ) => {
345+ global . fetch = jest . fn ( ) . mockResolvedValueOnce ( {
346+ ok : true ,
347+ json : jest . fn ( ) . mockResolvedValueOnce ( { data : mockResponse } ) ,
348+ } ) ;
349+
350+ const futureTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ; // 24 hours from now
351+ const mockOptions : UploadOptions = {
352+ expires_at : futureTimestamp ,
353+ } ;
354+
355+ await uploadFile ( mockConfig , mockFile , "public" , mockOptions ) ;
356+
357+ const fetchCall = ( global . fetch as jest . Mock ) . mock . calls [ 0 ] ;
358+ const formData = fetchCall [ 1 ] . body as FormData ;
359+
360+ expect ( formData . get ( "expires_at" ) ) . toBe ( futureTimestamp . toString ( ) ) ;
361+ expect ( global . fetch ) . toHaveBeenCalledWith (
362+ "https://uploads.pinata.cloud/v3/files" ,
363+ expect . objectContaining ( {
364+ method : "POST" ,
365+ headers : {
366+ Source : "sdk/file" ,
367+ Authorization : "Bearer test-jwt" ,
368+ } ,
369+ body : expect . any ( FormData ) ,
370+ } ) ,
371+ ) ;
372+ } ) ;
373+
374+ it ( "should upload file with expires_at combined with other options" , async ( ) => {
375+ global . fetch = jest . fn ( ) . mockResolvedValueOnce ( {
376+ ok : true ,
377+ json : jest . fn ( ) . mockResolvedValueOnce ( { data : mockResponse } ) ,
378+ } ) ;
379+
380+ const futureTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ;
381+ const mockOptions : UploadOptions = {
382+ expires_at : futureTimestamp ,
383+ groupId : "test-group" ,
384+ metadata : {
385+ name : "Test File" ,
386+ keyvalues : { key : "value" } ,
387+ } ,
388+ } ;
389+
390+ await uploadFile ( mockConfig , mockFile , "private" , mockOptions ) ;
391+
392+ const fetchCall = ( global . fetch as jest . Mock ) . mock . calls [ 0 ] ;
393+ const formData = fetchCall [ 1 ] . body as FormData ;
394+
395+ expect ( formData . get ( "expires_at" ) ) . toBe ( futureTimestamp . toString ( ) ) ;
396+ expect ( formData . get ( "group_id" ) ) . toBe ( "test-group" ) ;
397+ expect ( formData . get ( "name" ) ) . toBe ( "Test File" ) ;
398+ expect ( formData . get ( "keyvalues" ) ) . toBe ( JSON . stringify ( { key : "value" } ) ) ;
399+ } ) ;
400+
344401 it ( "should include CID version in metadata for large file upload" , async ( ) => {
345402 // Create a large file (over 90MB) to trigger chunked upload metadata path
346403 const largeFileSize = 94371841 ; // Just over the threshold
@@ -378,4 +435,41 @@ describe("uploadFile function", () => {
378435 expect ( uploadMetadata ) . toContain ( "cid_version" ) ;
379436 expect ( uploadMetadata ) . toContain ( btoa ( "v1" ) ) ;
380437 } ) ;
438+
439+ it ( "should include expires_at in metadata for large file upload" , async ( ) => {
440+ // Create a large file (over 90MB) to trigger chunked upload metadata path
441+ const largeFileSize = 94371841 ; // Just over the threshold
442+ const largeFile = new File (
443+ [ new ArrayBuffer ( largeFileSize ) ] ,
444+ "large-test.txt" ,
445+ {
446+ type : "text/plain" ,
447+ } ,
448+ ) ;
449+
450+ // Mock the first call (initial upload request) to verify metadata
451+ global . fetch = jest . fn ( ) . mockImplementationOnce ( ( ) => {
452+ return Promise . reject ( new Error ( "Test stopped after metadata check" ) ) ;
453+ } ) ;
454+
455+ const futureTimestamp = Math . floor ( Date . now ( ) / 1000 ) + 86400 ;
456+ const mockOptions : UploadOptions = {
457+ expires_at : futureTimestamp ,
458+ } ;
459+
460+ try {
461+ await uploadFile ( mockConfig , largeFile , "private" , mockOptions ) ;
462+ } catch ( error ) {
463+ // Expected to fail, we just want to check the metadata
464+ }
465+
466+ // Check that the initial request contains expires_at in Upload-Metadata
467+ expect ( global . fetch ) . toHaveBeenCalledTimes ( 1 ) ;
468+ const initialCall = ( global . fetch as jest . Mock ) . mock . calls [ 0 ] ;
469+ const uploadMetadata = initialCall [ 1 ] . headers [ "Upload-Metadata" ] ;
470+
471+ // The metadata should contain base64 encoded expires_at
472+ expect ( uploadMetadata ) . toContain ( "expires_at" ) ;
473+ expect ( uploadMetadata ) . toContain ( btoa ( futureTimestamp . toString ( ) ) ) ;
474+ } ) ;
381475} ) ;
0 commit comments