From 5683ca3823345d24957828417c69d777da6a9cd2 Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Wed, 13 Oct 2021 15:28:13 +0200 Subject: [PATCH 01/10] Add tests with files --- .../HttpMockPHPUnitIntegrationTest.php | 104 ++++++++++++++++++ tests/TestCase.php | 6 + 2 files changed, 110 insertions(+) diff --git a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php index f8b5db9..0fa5603 100644 --- a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php +++ b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php @@ -1,6 +1,9 @@ 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(); + + $f1 = FnStream::decorate(Utils::streamFor('file-content'), [ + 'getMetadata' => 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', $latestRequest->files->get('foo')->getContent()); + } + + public function testPostRequestWithMultipleFiles(): void + { + $this->http->mock + ->when() + ->methodIs('POST') + ->then() + ->body('BODY') + ->statusCode(201) + ->header('X-Foo', 'Bar') + ->end(); + $this->http->setUp(); + + $f1 = FnStream::decorate(Utils::streamFor('first-file-content'), [ + 'getMetadata' => function () { + return '/foo/bar.txt'; + } + ]); + + $f2 = FnStream::decorate(Utils::streamFor('second-file-content'), [ + 'getMetadata' => 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', $latestRequest->files->get('foo')->getContent()); + self::assertSame('second-file-content', $latestRequest->files->get('bar')->getContent()); + } + public function testCountRequests(): void { $this->http->mock diff --git a/tests/TestCase.php b/tests/TestCase.php index 91eec83..c81d653 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -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 @@ -23,4 +24,9 @@ public function getStreamFactory(): StreamFactoryInterface { return Psr17FactoryDiscovery::findStreamFactory(); } + + public function getServerRequestFactory(): ServerRequestFactoryInterface + { + return Psr17FactoryDiscovery::findServerRequestFactory(); + } } From 3d371deb66043831221563714496b2c8b63f20b9 Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Wed, 13 Oct 2021 15:29:25 +0200 Subject: [PATCH 02/10] Handle uploaded files and serialize them in a different way --- src/File/SerializableUploadedFile.php | 15 ++++++++++++++ src/Request/SerializableRequest.php | 29 +++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/File/SerializableUploadedFile.php diff --git a/src/File/SerializableUploadedFile.php b/src/File/SerializableUploadedFile.php new file mode 100644 index 0000000..63923a9 --- /dev/null +++ b/src/File/SerializableUploadedFile.php @@ -0,0 +1,15 @@ +getContent(); + $files = []; + + if ($this->files) { + foreach ($this->files as $key => $file) { + // Move the file in another directory + $path = sys_get_temp_dir() . '/' . 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, @@ -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 SerializableUploadedFile($file['pathName'], $file['originalName']); + } + } + + $this->files = new FileBag($this->files); $this->cookies = $attributes['cookies']; $this->headers = $attributes['headers']; $this->content = $attributes['content']; From db4ddc55c63b3bc38d766730f4ebf6ec994f82d7 Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 10:44:03 +0200 Subject: [PATCH 03/10] Use DIRECTORY_SEPARATOR instead of hardcoded '/' --- src/Request/SerializableRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Request/SerializableRequest.php b/src/Request/SerializableRequest.php index 3c4432e..ed86a1a 100644 --- a/src/Request/SerializableRequest.php +++ b/src/Request/SerializableRequest.php @@ -16,7 +16,7 @@ public function serialize(): string if ($this->files) { foreach ($this->files as $key => $file) { // Move the file in another directory - $path = sys_get_temp_dir() . '/' . md5($file->getPathname()); + $path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . md5($file->getPathname()); $file->move(sys_get_temp_dir(), md5($file->getPathname())); $files[$key] = [ 'originalName' => $file->getClientOriginalName(), From 12defb90fb6dac5b72a5c0fe0c75bb0ca9383fe8 Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 10:52:01 +0200 Subject: [PATCH 04/10] Remove SerializableUploadedFile and its usage --- src/File/SerializableUploadedFile.php | 15 --------------- src/Request/SerializableRequest.php | 4 ++-- 2 files changed, 2 insertions(+), 17 deletions(-) delete mode 100644 src/File/SerializableUploadedFile.php diff --git a/src/File/SerializableUploadedFile.php b/src/File/SerializableUploadedFile.php deleted file mode 100644 index 63923a9..0000000 --- a/src/File/SerializableUploadedFile.php +++ /dev/null @@ -1,15 +0,0 @@ - $file) { - $this->files[$key] = new SerializableUploadedFile($file['pathName'], $file['originalName']); + $this->files[$key] = new UploadedFile($file['pathName'], $file['originalName'], null, null, true); } } From 83979a7f2cc347f84bfd33526460d078ded0a6b7 Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 11:22:39 +0200 Subject: [PATCH 05/10] Fix code style --- src/Request/SerializableRequest.php | 2 +- .../HttpMockPHPUnitIntegrationTest.php | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Request/SerializableRequest.php b/src/Request/SerializableRequest.php index bf3c3ca..f3fdcf4 100644 --- a/src/Request/SerializableRequest.php +++ b/src/Request/SerializableRequest.php @@ -20,7 +20,7 @@ public function serialize(): string $file->move(sys_get_temp_dir(), md5($file->getPathname())); $files[$key] = [ 'originalName' => $file->getClientOriginalName(), - 'pathName' => $path + 'pathName' => $path, ]; } } diff --git a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php index 0fa5603..92e48b3 100644 --- a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php +++ b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php @@ -288,20 +288,20 @@ public function testPostRequestWithFile(): void $this->http->setUp(); $f1 = FnStream::decorate(Utils::streamFor('file-content'), [ - 'getMetadata' => function () { + 'getMetadata' => static function () { return '/foo/bar.txt'; - } + }, ]); $multipartStream = new MultipartStream([ [ 'name' => 'post-key', - 'contents' => 'post-value' + 'contents' => 'post-value', ], [ 'name' => 'foo', - 'contents' => $f1 - ] + 'contents' => $f1, + ], ]); $boundary = $multipartStream->getBoundary(); @@ -333,30 +333,30 @@ public function testPostRequestWithMultipleFiles(): void $this->http->setUp(); $f1 = FnStream::decorate(Utils::streamFor('first-file-content'), [ - 'getMetadata' => function () { + 'getMetadata' => static function () { return '/foo/bar.txt'; - } + }, ]); $f2 = FnStream::decorate(Utils::streamFor('second-file-content'), [ - 'getMetadata' => function () { + 'getMetadata' => static function () { return '/foo/baz.txt'; - } + }, ]); $multipartStream = new MultipartStream([ [ 'name' => 'post-key', - 'contents' => 'post-value' + 'contents' => 'post-value', ], [ 'name' => 'foo', - 'contents' => $f1 + 'contents' => $f1, ], [ 'name' => 'bar', - 'contents' => $f2 - ] + 'contents' => $f2, + ], ]); $boundary = $multipartStream->getBoundary(); From 0b146b8bc5eb6881ae59a6d560967e55a37182c7 Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 11:41:48 +0200 Subject: [PATCH 06/10] Remove GuzzleHttp\Psr7\Utils usages --- tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php index 92e48b3..9aa3e3b 100644 --- a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php +++ b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php @@ -3,7 +3,6 @@ use GuzzleHttp\Psr7\FnStream; use GuzzleHttp\Psr7\MultipartStream; -use GuzzleHttp\Psr7\Utils; use InterNations\Component\HttpMock\PHPUnit\HttpMock; use InterNations\Component\HttpMock\Tests\TestCase; use Symfony\Component\HttpFoundation\Request; @@ -287,7 +286,9 @@ public function testPostRequestWithFile(): void ->end(); $this->http->setUp(); - $f1 = FnStream::decorate(Utils::streamFor('file-content'), [ + $streamFactory = $this->getStreamFactory(); + + $f1 = FnStream::decorate($streamFactory->createStream('file-content'), [ 'getMetadata' => static function () { return '/foo/bar.txt'; }, @@ -332,13 +333,15 @@ public function testPostRequestWithMultipleFiles(): void ->end(); $this->http->setUp(); - $f1 = FnStream::decorate(Utils::streamFor('first-file-content'), [ + $streamFactory = $this->getStreamFactory(); + + $f1 = FnStream::decorate($streamFactory->createStream('first-file-content'), [ 'getMetadata' => static function () { return '/foo/bar.txt'; }, ]); - $f2 = FnStream::decorate(Utils::streamFor('second-file-content'), [ + $f2 = FnStream::decorate($streamFactory->createStream('second-file-content'), [ 'getMetadata' => static function () { return '/foo/baz.txt'; }, From 710b041ca7dbd0e04ac3e897028d8dc99edcbc4b Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 11:53:28 +0200 Subject: [PATCH 07/10] Add Guzzle Stream as a new layer in depfile.yaml --- depfile.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/depfile.yaml b/depfile.yaml index 43446a1..af32365 100644 --- a/depfile.yaml +++ b/depfile.yaml @@ -48,6 +48,10 @@ layers: collectors: - type: className regex: ^GuzzleHttp\\.* + - name: "Guzzle Stream" + collectors: + - type: className + regex: ^(GuzzleHttp\\Psr7\\FnStream|GuzzleHttp\\Psr7\\MultipartStream) - name: PHPUnit collectors: - type: className @@ -115,6 +119,7 @@ ruleset: - "PSR HTTP" - "PSR HTTP Discovery" - PHPUnit + - "Guzzle Stream" "HTTP Mock Util": ~ "HTTP Mock PSR Middleware": - "PSR HTTP" From 3a2caabf632c9d5177ccb00d52fc0d060d2cbbce Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 11:56:21 +0200 Subject: [PATCH 08/10] Fix depfile.yaml --- depfile.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/depfile.yaml b/depfile.yaml index af32365..2e36341 100644 --- a/depfile.yaml +++ b/depfile.yaml @@ -49,9 +49,9 @@ layers: - type: className regex: ^GuzzleHttp\\.* - name: "Guzzle Stream" - collectors: - - type: className - regex: ^(GuzzleHttp\\Psr7\\FnStream|GuzzleHttp\\Psr7\\MultipartStream) + collectors: + - type: className + regex: ^(GuzzleHttp\\Psr7\\FnStream|GuzzleHttp\\Psr7\\MultipartStream) - name: PHPUnit collectors: - type: className From 7f230088498315e01f12ecde840cd69bc9862bec Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 11:58:53 +0200 Subject: [PATCH 09/10] Fix depfile.yaml --- depfile.yaml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/depfile.yaml b/depfile.yaml index 2e36341..66a3c52 100644 --- a/depfile.yaml +++ b/depfile.yaml @@ -48,10 +48,6 @@ layers: collectors: - type: className regex: ^GuzzleHttp\\.* - - name: "Guzzle Stream" - collectors: - - type: className - regex: ^(GuzzleHttp\\Psr7\\FnStream|GuzzleHttp\\Psr7\\MultipartStream) - name: PHPUnit collectors: - type: className @@ -119,7 +115,7 @@ ruleset: - "PSR HTTP" - "PSR HTTP Discovery" - PHPUnit - - "Guzzle Stream" + - Guzzle "HTTP Mock Util": ~ "HTTP Mock PSR Middleware": - "PSR HTTP" From 7febcf1aa538b4d675d4faa2fb074c3ece5c637a Mon Sep 17 00:00:00 2001 From: Davide Pastore Date: Thu, 14 Oct 2021 12:06:09 +0200 Subject: [PATCH 10/10] Use a separated method to read the file content (backwards compatibility) --- tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php index 9aa3e3b..64b7e86 100644 --- a/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php +++ b/tests/PHPUnit/HttpMockPHPUnitIntegrationTest.php @@ -5,6 +5,7 @@ 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; @@ -34,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 */ public static function getPaths(): array { @@ -318,7 +328,7 @@ public function testPostRequestWithFile(): void 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', $latestRequest->files->get('foo')->getContent()); + self::assertSame('file-content', $this->getFileContent($latestRequest->files->get('foo'))); } public function testPostRequestWithMultipleFiles(): void @@ -375,8 +385,8 @@ public function testPostRequestWithMultipleFiles(): void 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', $latestRequest->files->get('foo')->getContent()); - self::assertSame('second-file-content', $latestRequest->files->get('bar')->getContent()); + 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