Skip to content

Commit

Permalink
Merge pull request #573 from alleyinteractive/feature/fake-request-wi…
Browse files Browse the repository at this point in the history
…th-image

Adding is_blob/is_file helper to response and with_image() helper to mock request
  • Loading branch information
srtfisher authored Aug 12, 2024
2 parents 3601a5f + 631ece2 commit 9868347
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added a `with_image()` helper to mocked HTTP responses.
- Added a `is_blob()` and `is_file()` helper to `Mantle\Http_Client\Response`.
- Added `with_real_thumbnail()` method to post factory for creating posts with
real underlying thumbnail files.

Expand Down
14 changes: 14 additions & 0 deletions src/mantle/http-client/class-response.php
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,20 @@ public function is_xml(): bool {
return str_starts_with( trim( strtolower( $this->body() ) ), '<?xml' );
}

/**
* Check if the response body is a file download (a Binary Large OBject).
*/
public function is_blob(): bool {
return false === mb_detect_encoding( $this->body(), 'UTF-8', true ) && ! ctype_print( $this->body() );
}

/**
* Check if the response is a file download.
*/
public function is_file(): bool {
return ! empty( $this->response['filename'] ) && $this->is_blob();
}

/**
* Get the raw body of the response.
*
Expand Down
34 changes: 31 additions & 3 deletions src/mantle/testing/class-mock-http-response.php
Original file line number Diff line number Diff line change
Expand Up @@ -229,12 +229,17 @@ public function with_temporary_redirect( string $url ): Mock_Http_Response {
* @throws \InvalidArgumentException If the file is not readable.
*
* @param string $file File path.
* @param string $filename Optional. Filename to use in the Content-Disposition header.
*/
public function with_file( string $file ): Mock_Http_Response {
public function with_file( string $file, ?string $filename = null ): Mock_Http_Response {
if ( ! is_readable( $file ) ) {
throw new \InvalidArgumentException( "File '{$file}' is not readable." );
}

if ( ! $filename ) {
$filename = basename( $file );
}

// Determine the mime type.
$mime_type = wp_check_filetype( $file );

Expand All @@ -244,10 +249,33 @@ public function with_file( string $file ): Mock_Http_Response {
}

if ( ! empty( $mime_type['ext'] ) ) {
$this->with_header( 'Content-Disposition', "attachment; filename={$file}.{$mime_type['ext']}" );
$this->with_header(
'Content-Disposition',
sprintf(
'attachment; filename="%s.%s"',
pathinfo( $filename, PATHINFO_FILENAME ),
$mime_type['ext'],
),
);
}

return $this->with_body( file_get_contents( $file ) ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
return $this
->with_filename( $file )
->with_body( file_get_contents( $file ) ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
}

/**
* Create a response with an image file as the body.
*
* The image will be a JPEG file.
*
* @param string|null $filename Optional. Filename to use in the Content-Disposition header.
*/
public function with_image( ?string $filename = null ): Mock_Http_Response {
return $this->with_file(
__DIR__ . '/data/images/canola.jpg',
$filename,
);
}

/**
Expand Down
28 changes: 28 additions & 0 deletions tests/Testing/Concerns/InteractsWithExternalRequestsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,34 @@ public function test_streamed_response() {
$this->assertEquals( 'image/jpeg', $response->header( 'Content-Type' ) );
}

public function test_fake_request_with_file() {
$file = __DIR__ . '/../../../src/mantle/testing/data/images/wordpress-gsoc-flyer.pdf';

$this->fake_request( 'https://example.org/images/file.pdf' )->with_file( $file );

$response = Http::get( 'https://example.org/images/file.pdf' );

$this->assertTrue( $response->ok() );
$this->assertEquals( 'application/pdf', $response->header( 'Content-Type' ) );
$this->assertEquals(
'attachment; filename="wordpress-gsoc-flyer.pdf"',
$response->header( 'Content-Disposition' )
);
$this->assertEquals( file_get_contents( $file ), $response->body() );
}

public function test_fake_request_with_image() {
$this->fake_request( 'https://example.org/images/alley.jpg' )->with_image();

$response = Http::get( 'https://example.org/images/alley.jpg' );

$this->assertTrue( $response->ok() );
$this->assertEquals( 'image/jpeg', $response->header( 'Content-Type' ) );
$this->assertNotEmpty( $response->body() );
$this->assertTrue( $response->is_blob() );
$this->assertTrue( $response->is_file() );
}

public function test_unknown_file_as_response() {
$this->expectException( InvalidArgumentException::class );

Expand Down

0 comments on commit 9868347

Please sign in to comment.