Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix requests with files on php74 branch #67

Open
wants to merge 10 commits into
base: php74
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions depfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ ruleset:
- "PSR HTTP"
- "PSR HTTP Discovery"
- PHPUnit
- Guzzle
"HTTP Mock Util": ~
"HTTP Mock PSR Middleware":
- "PSR HTTP"
Expand Down
29 changes: 27 additions & 2 deletions src/Request/SerializableRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,35 @@
namespace InterNations\Component\HttpMock\Request;

use Serializable;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\FileBag;
use Symfony\Component\HttpFoundation\Request;

class SerializableRequest extends Request implements Serializable
{
public function serialize(): string
{
$this->getContent();
$files = [];

if ($this->files) {
foreach ($this->files as $key => $file) {
// Move the file in another directory
$path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . md5($file->getPathname());
$file->move(sys_get_temp_dir(), md5($file->getPathname()));
$files[$key] = [
'originalName' => $file->getClientOriginalName(),
'pathName' => $path,
];
}
}

return serialize([
'attributes' => $this->attributes,
'request' => $this->request,
'query' => $this->query,
'server' => $this->server,
'files' => $this->files,
'files' => $files,
'cookies' => $this->cookies,
'headers' => $this->headers,
'content' => $this->content,
Expand Down Expand Up @@ -43,7 +59,16 @@ public function unserialize($data): void // @codingStandardsIgnoreLine
$this->request = $attributes['request'];
$this->query = $attributes['query'];
$this->server = $attributes['server'];
$this->files = $attributes['files'];
$files = $attributes['files'];
$this->files = [];

if ($files) {
foreach($files as $key => $file) {
$this->files[$key] = new UploadedFile($file['pathName'], $file['originalName'], null, null, true);
}
}

$this->files = new FileBag($this->files);
$this->cookies = $attributes['cookies'];
$this->headers = $attributes['headers'];
$this->content = $attributes['content'];
Expand Down
117 changes: 117 additions & 0 deletions tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<?php
namespace InterNations\Component\HttpMock\Tests\PHPUnit;

use GuzzleHttp\Psr7\FnStream;
use GuzzleHttp\Psr7\MultipartStream;
use InterNations\Component\HttpMock\PHPUnit\HttpMock;
use InterNations\Component\HttpMock\Tests\TestCase;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use function http_build_query;
Expand Down Expand Up @@ -32,6 +35,15 @@ public function tearDown(): void
$this->tearDownHttpMock();
}

/**
* Get the content of the file.
* @param $file File The file from which get the content
* @return false|string The file content or false on error.
*/
private function getFileContent(File $file) {
return file_get_contents($file->getPathname());
}

/** @return array<array{0:string}> */
public static function getPaths(): array
{
Expand Down Expand Up @@ -272,6 +284,111 @@ public function testPostRequest(): void
self::assertSame('post-value', $this->http->requests->latest()->request->get('post-key'));
}

public function testPostRequestWithFile(): void
{
$this->http->mock
->when()
->methodIs('POST')
->then()
->body('BODY')
->statusCode(201)
->header('X-Foo', 'Bar')
->end();
$this->http->setUp();

$streamFactory = $this->getStreamFactory();

$f1 = FnStream::decorate($streamFactory->createStream('file-content'), [
'getMetadata' => static function () {
return '/foo/bar.txt';
},
]);

$multipartStream = new MultipartStream([
[
'name' => 'post-key',
'contents' => 'post-value',
],
[
'name' => 'foo',
'contents' => $f1,
],
]);
$boundary = $multipartStream->getBoundary();

$response = $this->http->client->sendRequest(
$this->getServerRequestFactory()
->createServerRequest('POST', '/')
->withHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary)
->withBody($multipartStream)
);

$latestRequest = $this->http->requests->latest();
self::assertSame('BODY', (string) $response->getBody());
self::assertSame(201, $response->getStatusCode());
self::assertSame('Bar', $response->getHeaderLine('X-Foo'));
self::assertSame('post-value', $latestRequest->request->get('post-key'));
self::assertSame('file-content', $this->getFileContent($latestRequest->files->get('foo')));
}

public function testPostRequestWithMultipleFiles(): void
{
$this->http->mock
->when()
->methodIs('POST')
->then()
->body('BODY')
->statusCode(201)
->header('X-Foo', 'Bar')
->end();
$this->http->setUp();

$streamFactory = $this->getStreamFactory();

$f1 = FnStream::decorate($streamFactory->createStream('first-file-content'), [
'getMetadata' => static function () {
return '/foo/bar.txt';
},
]);

$f2 = FnStream::decorate($streamFactory->createStream('second-file-content'), [
'getMetadata' => static function () {
return '/foo/baz.txt';
},
]);

$multipartStream = new MultipartStream([
[
'name' => 'post-key',
'contents' => 'post-value',
],
[
'name' => 'foo',
'contents' => $f1,
],
[
'name' => 'bar',
'contents' => $f2,
],
]);
$boundary = $multipartStream->getBoundary();

$response = $this->http->client->sendRequest(
$this->getServerRequestFactory()
->createServerRequest('POST', '/')
->withHeader('Content-Type', 'multipart/form-data; boundary=' . $boundary)
->withBody($multipartStream)
);

$latestRequest = $this->http->requests->latest();
self::assertSame('BODY', (string) $response->getBody());
self::assertSame(201, $response->getStatusCode());
self::assertSame('Bar', $response->getHeaderLine('X-Foo'));
self::assertSame('post-value', $latestRequest->request->get('post-key'));
self::assertSame('first-file-content', $this->getFileContent($latestRequest->files->get('foo')));
self::assertSame('second-file-content', $this->getFileContent($latestRequest->files->get('bar')));
}

public function testCountRequests(): void
{
$this->http->mock
Expand Down
6 changes: 6 additions & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use PHPUnit\Framework\TestCase as PhpUnitTestCase;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ServerRequestFactoryInterface;
use Psr\Http\Message\StreamFactoryInterface;

abstract class TestCase extends PhpUnitTestCase
Expand All @@ -23,4 +24,9 @@ public function getStreamFactory(): StreamFactoryInterface
{
return Psr17FactoryDiscovery::findStreamFactory();
}

public function getServerRequestFactory(): ServerRequestFactoryInterface
{
return Psr17FactoryDiscovery::findServerRequestFactory();
}
}