@@ -209,18 +209,155 @@ public function testPatchWithFormParameters()
209209 $ this ->assertEquals ('ok ' , (string ) $ response ->getBody ());
210210 }
211211
212- public function testBearerAuthenticationHeader ()
212+ public function testUploadFile (): void
213+ {
214+ $ mockResponse = new Response (201 , [], 'uploaded ' );
215+
216+ $ filePath = sys_get_temp_dir ().'/test_upload.txt ' ;
217+ file_put_contents ($ filePath , 'test content ' );
218+ $ file = new \SplFileInfo ($ filePath );
219+
220+ $ client = $ this ->createMock (Client::class);
221+ $ client ->expects ($ this ->once ())
222+ ->method ('post ' )
223+ ->with (
224+ 'https://example.com/upload ' ,
225+ $ this ->callback (
226+ function (mixed $ options ) use ($ file ): bool {
227+ return isset ($ options ['body ' ])
228+ && stream_get_contents ($ options ['body ' ]) === file_get_contents ($ file ->getPathname ());
229+ }
230+ )
231+ )
232+ ->willReturn ($ mockResponse );
233+
234+ $ adapter = new HttpAdapter ($ client );
235+ $ adapter ->setBaseUri ('https://example.com ' );
236+
237+ $ response = $ adapter ->upload ('/upload ' , $ file );
238+
239+ $ this ->assertEquals (201 , $ response ->getStatusCode ());
240+ $ this ->assertEquals ('uploaded ' , (string ) $ response ->getBody ());
241+
242+ unlink ($ filePath );
243+ }
244+
245+ public function testReplaceFile (): void
246+ {
247+ $ mockResponse = new Response (200 , [], 'replaced ' );
248+
249+ $ filePath = sys_get_temp_dir ().'/test_replace.txt ' ;
250+ file_put_contents ($ filePath , 'replace content ' );
251+ $ file = new \SplFileInfo ($ filePath );
252+
253+ $ client = $ this ->createMock (Client::class);
254+ $ client ->expects ($ this ->once ())
255+ ->method ('put ' )
256+ ->with (
257+ 'https://example.com/replace ' ,
258+ $ this ->callback (
259+ function (mixed $ options ) use ($ file ): bool {
260+ return isset ($ options ['body ' ])
261+ && stream_get_contents ($ options ['body ' ]) === file_get_contents ($ file ->getPathname ());
262+ }
263+ )
264+ )
265+ ->willReturn ($ mockResponse );
266+
267+ $ adapter = new HttpAdapter ($ client );
268+ $ adapter ->setBaseUri ('https://example.com ' );
269+
270+ $ response = $ adapter ->replace ('/replace ' , $ file );
271+
272+ $ this ->assertEquals (200 , $ response ->getStatusCode ());
273+ $ this ->assertEquals ('replaced ' , (string ) $ response ->getBody ());
274+
275+ unlink ($ filePath );
276+ }
277+
278+ public function testUploadFileThrowsExceptionIfFileCannotBeOpened (): void
279+ {
280+ $ this ->expectException (\RuntimeException::class);
281+ $ this ->expectExceptionMessage ('Cannot open file ' );
282+
283+ $ file = new \SplFileInfo ('/path/to/nonexistent/file.txt ' );
284+
285+ $ client = $ this ->createMock (Client::class);
286+ $ adapter = new HttpAdapter ($ client );
287+
288+ $ adapter ->upload ('/upload ' , $ file );
289+ }
290+
291+ public function testReplaceFileThrowsExceptionIfFileCannotBeOpened (): void
292+ {
293+ $ this ->expectException (\RuntimeException::class);
294+ $ this ->expectExceptionMessage ('Cannot open file ' );
295+
296+ $ file = new \SplFileInfo ('/path/to/nonexistent/file.txt ' );
297+
298+ $ client = $ this ->createMock (Client::class);
299+ $ adapter = new HttpAdapter ($ client );
300+
301+ $ adapter ->replace ('/replace ' , $ file );
302+ }
303+
304+ public function testUploadFileWithGuzzleException (): void
305+ {
306+ $ this ->expectException (\GuzzleHttp \Exception \GuzzleException::class);
307+
308+ $ filePath = sys_get_temp_dir ().'/test_upload.txt ' ;
309+ file_put_contents ($ filePath , 'test content ' );
310+ $ file = new \SplFileInfo ($ filePath );
311+
312+ $ client = $ this ->createMock (Client::class);
313+ $ client ->method ('post ' )->willThrowException (
314+ new class extends \Exception implements \GuzzleHttp \Exception \GuzzleException {}
315+ );
316+
317+ $ adapter = new HttpAdapter ($ client );
318+
319+ $ adapter ->upload ('/upload ' , $ file );
320+
321+ unlink ($ filePath );
322+ }
323+
324+ public function testReplaceFileWithGuzzleException (): void
325+ {
326+ $ this ->expectException (\GuzzleHttp \Exception \GuzzleException::class);
327+
328+ $ filePath = sys_get_temp_dir ().'/test_replace.txt ' ;
329+ file_put_contents ($ filePath , 'replace content ' );
330+ $ file = new \SplFileInfo ($ filePath );
331+
332+ $ client = $ this ->createMock (Client::class);
333+ $ client ->method ('put ' )->willThrowException (
334+ new class extends \Exception implements \GuzzleHttp \Exception \GuzzleException {}
335+ );
336+
337+ $ adapter = new HttpAdapter ($ client );
338+
339+ $ adapter ->replace ('/replace ' , $ file );
340+
341+ unlink ($ filePath );
342+ }
343+
344+ public function testBearerAuthenticationHeader (): void
213345 {
214346 $ mockResponse = new Response (200 , [], 'ok ' );
215347
216348 /** @var Client|MockObject $client */
217349 $ client = $ this ->createMock (Client::class);
218350 $ client ->expects ($ this ->once ())
219351 ->method ('get ' )
220- ->with ('https://example.com/test ' , $ this ->callback (function ($ options ) {
221- return isset ($ options ['headers ' ]['Authorization ' ])
222- && 'Bearer TOKEN123 ' === $ options ['headers ' ]['Authorization ' ];
223- }))
352+ ->with (
353+ 'https://example.com/test ' ,
354+ $ this ->callback (
355+ function (mixed $ options ): bool {
356+ return isset ($ options ['headers ' ]['Authorization ' ])
357+ && 'Bearer TOKEN123 ' === $ options ['headers ' ]['Authorization ' ];
358+ }
359+ )
360+ )
224361 ->willReturn ($ mockResponse );
225362
226363 $ adapter = new HttpAdapter ($ client );
0 commit comments