diff --git a/.travis.yml b/.travis.yml index 9e284ba..b77a6ba 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ jobs: # dependencies for phpstan - composer require --dev "symfony/symfony" "laravel/framework" "drupal/drupal" script: + # Unit test + - ./vendor/bin/phpunit # Static analyzer check - ./vendor/bin/phpstan analyze -c .phpstan.neon --level=4 --no-progress Bootstraps Bridges Laravel || true # Check the code style diff --git a/composer.json b/composer.json index 90577c6..4d922c5 100644 --- a/composer.json +++ b/composer.json @@ -7,9 +7,13 @@ "symfony/http-kernel": "^2.6|^3.0|^4", "ringcentral/psr7": "^1.2" }, + "require-dev": { + "phpunit/phpunit": "^5.7" + }, "autoload": { "psr-4": { - "PHPPM\\": "" + "PHPPM\\": "", + "PHPPM\\Tests\\": "tests" } } } diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 0000000..6bb5742 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,19 @@ + + + + + + tests/ + + + + \ No newline at end of file diff --git a/tests/HttpKernelTest.php b/tests/HttpKernelTest.php new file mode 100644 index 0000000..468f134 --- /dev/null +++ b/tests/HttpKernelTest.php @@ -0,0 +1,24 @@ +getMockBuilder(ServerRequestInterface::class) + ->getMock(); + $response = $bridge->handle($request); + $this->assertEquals(500, $response->getStatusCode()); + $this->assertEquals('Application not configured during bootstrap', (string)$response->getBody()); + } +} diff --git a/tests/SymfonyBootstrapTest.php b/tests/SymfonyBootstrapTest.php new file mode 100644 index 0000000..ef5ad13 --- /dev/null +++ b/tests/SymfonyBootstrapTest.php @@ -0,0 +1,86 @@ +bootstrap('Symfony', 'test', true); + + $request = $this->getMockBuilder(ServerRequestInterface::class)->getMock(); + $request->method('getHeader')->with('Cookie')->willReturn([]); + $request->method('getQueryParams')->willReturn([]); + $request->method('getUploadedFiles')->willReturn([]); + $request->method('getMethod')->willReturn('GET'); + + $response = $bridge->handle($request); + $this->assertEquals(200, $response->getStatusCode()); + $this->assertEquals('Success', (string)$response->getBody()); + } + + /** + * @runInSeparateProcess + */ + public function testFileUpload() + { + putenv('APP_KERNEL_NAMESPACE=PHPPM\\Tests\\SymfonyMocks\\'); + $bridge = new HttpKernel(); + $bridge->bootstrap('Symfony', 'test', true); + + $fileOK = $this->getMockBuilder(UploadedFileInterface::class)->getMock(); + $fileOK->method('getClientFilename')->willReturn('testOK.pdf'); + $fileOK->method('getClientMediaType')->willReturn('pdf'); + $fileOK->method('getSize')->willReturn(1000); + $fileOK->method('getError')->willReturn(UPLOAD_ERR_OK); + + $fileErr = $this->getMockBuilder(UploadedFileInterface::class)->getMock(); + $fileErr->method('getClientFilename')->willReturn('testErr.pdf'); + $fileErr->method('getClientMediaType')->willReturn('pdf'); + $fileErr->method('getSize')->willReturn(0); + $fileErr->method('getError')->willReturn(UPLOAD_ERR_NO_FILE); + + $request = $this->getMockBuilder(ServerRequestInterface::class)->getMock(); + $request->method('getHeader')->with('Cookie')->willReturn([]); + $request->method('getQueryParams')->willReturn([]); + $request->method('getUploadedFiles')->willReturn([$fileOK, $fileErr]); + $request->method('getMethod')->willReturn('POST'); + + $response = $bridge->handle($request); + $this->assertEquals(201, $response->getStatusCode()); + $this->assertEquals('Uploaded files: testOK.pdf,NULL', (string)$response->getBody()); + } + + /** + * @runInSeparateProcess + */ + public function testPostJSON() + { + putenv('APP_KERNEL_NAMESPACE=PHPPM\\Tests\\SymfonyMocks\\'); + $bridge = new HttpKernel(); + $bridge->bootstrap('Symfony', 'test', true); + + $_SERVER["CONTENT_TYPE"] = 'application/json'; + $request = $this->getMockBuilder(ServerRequestInterface::class)->getMock(); + $request->method('getHeader')->with('Cookie')->willReturn([]); + $request->method('getQueryParams')->willReturn([]); + $request->method('getUploadedFiles')->willReturn([]); + $request->method('getBody')->willReturn('{"some_json_array":[{"map1":"value1"},{"map2":"value2"}]}'); + $request->method('getMethod')->willReturn('POST'); + + $response = $bridge->handle($request); + $this->assertEquals(201, $response->getStatusCode()); + $this->assertEquals('Received JSON: {"some_json_array":[{"map1":"value1"},{"map2":"value2"}]}', (string)$response->getBody()); + } +} diff --git a/tests/SymfonyMocks/Container.php b/tests/SymfonyMocks/Container.php new file mode 100644 index 0000000..9f27388 --- /dev/null +++ b/tests/SymfonyMocks/Container.php @@ -0,0 +1,11 @@ +bundlesInitialized = true; + } + + public function initializeContainer() + { + $this->containerInitialized = true; + } + + public function getBundles() + { + if (!$this->bundlesInitialized) { + throw new \Exception('Bundles not initialized'); + } + + return []; + } + + public function getContainer() + { + if (!$this->containerInitialized) { + throw new \Exception('Container not initialized'); + } + + return new Container(); + } + + public function handle(Request $request) + { + if (!$this->bundlesInitialized) { + throw new \Exception('Bundles not initialized'); + } + if (!$this->containerInitialized) { + throw new \Exception('Container not initialized'); + } + + if ($request->getMethod() == 'POST') { + if (count($request->files->all()) > 0) { + $mappedFileNames = array_map(function ($f) { + if (!isset($f)) { + return 'NULL'; + } + return $f->getClientOriginalName(); + }, $request->files->all()); + return new Response('Uploaded files: '.implode(',', $mappedFileNames), 201); + } + if ($request->getContentType() == 'json') { + $body = json_decode($request->getContent(), true); + if ($request->getContent() == null || !$body) { + throw new \Exception('Invalid JSON body'); + } + return new Response('Received JSON: '.$request->getContent(), 201); + } + } elseif ($request->getMethod() == 'GET') { + // Simple get request + return new Response('Success', 200); + } + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php new file mode 100644 index 0000000..0ec8857 --- /dev/null +++ b/tests/bootstrap.php @@ -0,0 +1,3 @@ +