From 7db2555b7f0bbd48b5451e3460f71739d50a0b5f Mon Sep 17 00:00:00 2001 From: Peter Fox Date: Mon, 22 Jan 2024 15:53:37 +0000 Subject: [PATCH] Adds the HttpFacadeDownloader (#3505) * Adds the HttpFacadeDownloader * Added documentation --- .../using-a-custom-media-downloader.md | 45 +++++++++++++++ src/Downloaders/HttpFacadeDownloader.php | 21 +++++++ tests/Downloader/HttpFacadeDownloaderTest.php | 55 +++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 src/Downloaders/HttpFacadeDownloader.php create mode 100644 tests/Downloader/HttpFacadeDownloaderTest.php diff --git a/docs/advanced-usage/using-a-custom-media-downloader.md b/docs/advanced-usage/using-a-custom-media-downloader.md index 1a179ba1e..980aca5b9 100644 --- a/docs/advanced-usage/using-a-custom-media-downloader.md +++ b/docs/advanced-usage/using-a-custom-media-downloader.md @@ -46,3 +46,48 @@ class CustomDownloader implements Downloader { } ``` + +## Using the Laravel Downloader + +You may configure the medialibrary config to use a downloader compatible more +with Laravel that makes use of the built-in HTTP client. This is the quickest way +to mock any requests made to external URLs. + +```php + // config/media-library.php + + /* + * When using the addMediaFromUrl method you may want to replace the default downloader. + * This is particularly useful when the url of the image is behind a firewall and + * need to add additional flags, possibly using curl. + */ + 'media_downloader' => Spatie\MediaLibrary\Downloaders\HttpFacadeDownloader::class, +``` + +This then makes it easier in tests to mock the download of files. + +```php +$url = 'http://medialibrary.spatie.be/assets/images/mountain.jpg'; +$yourModel + ->addMediaFromUrl($url) + ->toMediaCollection(); +``` + +with a test like this: + +```php +Http::fake([ + // Stub a response where the body will be the contents of the file + 'http://medialibrary.spatie.be/assets/images/mountain.jpg' => Http::response('::file::'), +]); + +// Execute code for the test + +// Then check that a request for the file was made +Http::assertSent(function (Request $request) { + return $request->url() == 'http://medialibrary.spatie.be/assets/images/mountain.jpg'; +}); + +// We may also assert that the contents of any files created +// will contain `::file::` +``` diff --git a/src/Downloaders/HttpFacadeDownloader.php b/src/Downloaders/HttpFacadeDownloader.php new file mode 100644 index 000000000..d56bba8f1 --- /dev/null +++ b/src/Downloaders/HttpFacadeDownloader.php @@ -0,0 +1,21 @@ +throw(fn () => throw new UnreachableUrl($url)) + ->sink($temporaryFile) + ->get($url); + + return $temporaryFile; + } +} diff --git a/tests/Downloader/HttpFacadeDownloaderTest.php b/tests/Downloader/HttpFacadeDownloaderTest.php new file mode 100644 index 000000000..030908280 --- /dev/null +++ b/tests/Downloader/HttpFacadeDownloaderTest.php @@ -0,0 +1,55 @@ +with('Spatie MediaLibrary') + ->once() + ->andReturnSelf() + ->getMock() + ->shouldReceive('throw') + ->once() + ->andReturnSelf() + ->getMock() + ->shouldReceive('sink') + ->once() + ->andReturnSelf() + ->getMock() + ->shouldReceive('get') + ->with($url) + ->once(); + + $downloader = new \Spatie\MediaLibrary\Downloaders\HttpFacadeDownloader(); + + $result = $downloader->getTempFile($url); + + expect($result)->toBeString(); +}); + +it('can be mocked easily for tests', function () { + $url = 'https://example.com'; + + Http::fake([ + // Stub a JSON response for GitHub endpoints... + 'https://example.com' => Http::response('::file::'), + ]); + + $downloader = new \Spatie\MediaLibrary\Downloaders\HttpFacadeDownloader(); + + $result = $downloader->getTempFile($url); + + expect($result) + ->toBeString() + ->and($result) + ->toBeFile() + ->and(\Illuminate\Support\Facades\File::get($result)) + ->toBe('::file::'); + + Http::assertSent(function (Request $request) { + return $request->url() == 'https://example.com'; + }); +});