@@ -58,9 +58,19 @@ describe('file upload command', () => {
5858 } ) ;
5959
6060 it ( 'throws when file does not exist' , async ( ) => {
61- await expect (
62- uploadCommand . execute ( baseConfig , { ...baseFlags , file : '/tmp/nonexistent-file-xxxxx.bin' } ) ,
63- ) . rejects . toThrow ( 'File not found' ) ;
61+ try {
62+ await uploadCommand . execute ( baseConfig , {
63+ ...baseFlags ,
64+ file : '/tmp/nonexistent-file-xxxxx.bin' ,
65+ } ) ;
66+ throw new Error ( 'Expected upload to reject' ) ;
67+ } catch ( error ) {
68+ expect ( error ) . toMatchObject ( {
69+ name : 'CLIError' ,
70+ message : expect . stringContaining ( 'File not found' ) ,
71+ exitCode : 2 ,
72+ } ) ;
73+ }
6474 } ) ;
6575
6676 it ( 'shows dry-run output with file info' , async ( ) => {
@@ -82,4 +92,57 @@ describe('file upload command', () => {
8292 rmSync ( tempDir , { recursive : true , force : true } ) ;
8393 }
8494 } ) ;
95+
96+ it ( 'uploads through the shared multipart operation and formats the response' , async ( ) => {
97+ const tempDir = mkdtempSync ( join ( tmpdir ( ) , 'mmx-upload-test-' ) ) ;
98+ const filePath = join ( tempDir , 'fixture.txt' ) ;
99+ writeFileSync ( filePath , 'shared upload contents' ) ;
100+ const originalFetch = globalThis . fetch ;
101+ let requestUrl = '' ;
102+ let requestInit : RequestInit | undefined ;
103+
104+ globalThis . fetch = ( async ( input , init ) => {
105+ requestUrl = String ( input ) ;
106+ requestInit = init ;
107+ return new Response ( JSON . stringify ( {
108+ base_resp : { status_code : 0 , status_msg : 'success' } ,
109+ file : {
110+ file_id : 'cli-file-id' ,
111+ bytes : 22 ,
112+ created_at : 1 ,
113+ filename : 'fixture.txt' ,
114+ purpose : 'vision' ,
115+ } ,
116+ } ) , {
117+ status : 200 ,
118+ headers : { 'Content-Type' : 'application/json' } ,
119+ } ) ;
120+ } ) as typeof fetch ;
121+
122+ try {
123+ const captured = await captureStdout ( async ( ) => {
124+ await uploadCommand . execute ( baseConfig , {
125+ ...baseFlags ,
126+ file : filePath ,
127+ purpose : 'vision' ,
128+ } ) ;
129+ } ) ;
130+
131+ expect ( requestUrl ) . toBe ( 'https://api.mmx.io/v1/files/upload' ) ;
132+ expect ( requestInit ?. method ) . toBe ( 'POST' ) ;
133+ expect ( requestInit ?. headers ) . toMatchObject ( { Authorization : 'Bearer test-key' } ) ;
134+ expect ( requestInit ?. body ) . toBeInstanceOf ( FormData ) ;
135+
136+ const body = requestInit ?. body as FormData ;
137+ const uploadedFile = body . get ( 'file' ) ;
138+ expect ( uploadedFile ) . toBeInstanceOf ( Blob ) ;
139+ expect ( ( uploadedFile as File ) . name ) . toBe ( 'fixture.txt' ) ;
140+ expect ( await ( uploadedFile as Blob ) . text ( ) ) . toBe ( 'shared upload contents' ) ;
141+ expect ( body . get ( 'purpose' ) ) . toBe ( 'vision' ) ;
142+ expect ( captured ) . toContain ( 'cli-file-id' ) ;
143+ } finally {
144+ globalThis . fetch = originalFetch ;
145+ rmSync ( tempDir , { recursive : true , force : true } ) ;
146+ }
147+ } ) ;
85148} ) ;
0 commit comments