diff --git a/README.md b/README.md index d5f511c..09c4945 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,11 @@ APIs will be available at `http://localhost:PHP_HOST_PORT`, where `PHP_HOST_PORT You can enable or disable XDebug using the `XDEBUG_MODE` environment variable. ## Test -Tests are under `/tests` folder, run it with `phpunit`. +Tests are under `/tests` folder, run it with `phpunit`: +```bash +docker-compose run --rm blog-lumen /var/www/html/vendor/bin/phpunit --coverage-html /tmp --colors=always -c /var/www/html/phpunit.xml --testsuite 'Application Test Suite' +``` + ## ToDo - [x] Upgrade to Lumen 8.x @@ -32,10 +36,10 @@ Tests are under `/tests` folder, run it with `phpunit`. - [x] Automated PHP-CS-Fixer - [x] Redis cache - [x] Clean up local Docker environment -- [X] Review CI Docker environment -- [X] Use Github workflow -- [X] Setup a simple production environment -- [X] Containerized infrastructure for server +- [x] Review CI Docker environment +- [x] Use Github workflow +- [x] Setup a simple production environment +- [x] Containerized infrastructure for server - [ ] Makefile - [ ] Pagination diff --git a/app/Classes/ParseInputStream.php b/app/Classes/ParseInputStream.php index e691315..a62c398 100644 --- a/app/Classes/ParseInputStream.php +++ b/app/Classes/ParseInputStream.php @@ -24,6 +24,10 @@ * Original Gist at: * https://gist.github.com/jas-/5c3fdc26fedd11cb9fb5#file-class-stream-php */ + +/** + * @codeCoverageIgnore + */ class ParseInputStream { /** diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 8725fb8..a86c82e 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,7 +2,6 @@ namespace App\Exceptions; -use ErrorException; use Exception; use Illuminate\Auth\Access\AuthorizationException; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -11,7 +10,6 @@ use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Throwable; -use UnexpectedValueException; class Handler extends ExceptionHandler { @@ -38,9 +36,12 @@ class Handler extends ExceptionHandler */ public function report(Throwable $e) { + // Ignoring this block because only applies on production environment + // @codeCoverageIgnoreStart if (app()->environment('production') && app()->bound('sentry') && $this->shouldReport($e)) { app('sentry')->captureException($e); } + // @codeCoverageIgnoreEnd parent::report($e); } @@ -61,19 +62,16 @@ public function render($request, Throwable $e) if ($e instanceof MethodNotAllowedHttpException) { return response('Method Not Allowed.', 405); } - if ($e instanceof UnexpectedValueException) { - return response('Unexpected value.', 422); - } if ($e instanceof ModelNotFoundException) { return response('The resource you are looking for is not available or does not belong to you.', 404); } - if ($e instanceof ErrorException) { - return response('Unprocessable. Please provide all inputs and retry.', 422); - } if ($e instanceof AuthorizationException) { return response($e->getMessage(), 401); } + // Ignoring this block because only applies if an error is not handled (like 500 server errors) + // @codeCoverageIgnoreStart return response($e->getMessage(), $e->getCode() ?: 500); + // @codeCoverageIgnoreEnd } } diff --git a/app/Http/Controllers/AuthController.php b/app/Http/Controllers/AuthController.php index 6a4f1a7..19e9919 100644 --- a/app/Http/Controllers/AuthController.php +++ b/app/Http/Controllers/AuthController.php @@ -9,14 +9,6 @@ class AuthController extends BaseController { - /** - * Create a new AuthController instance. - */ - public function __construct() - { - $this->middleware('auth:api', ['except' => ['login']]); - } - /** * Get a JWT via given credentials. * @@ -53,9 +45,11 @@ public function me() /** * Log the user out (Invalidate the token). * + * @param Request $request + * * @return JsonResponse */ - public function logout() + public function logout(Request $request) { Auth::logout(); diff --git a/composer.json b/composer.json index 188561f..43f90d6 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "laravel", "lumen" ], - "version": "1.1.0", + "version": "1.1.1", "license": "MIT", "type": "project", "require": { diff --git a/composer.lock b/composer.lock index 3a89f8f..83b89ac 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "403ada2e5348aef3aafa558e21c09cc8", + "content-hash": "1a7a99695c6e9c006e32526f32793281", "packages": [ { "name": "brick/math", @@ -933,16 +933,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.7.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3" + "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/53330f47520498c0ae1f61f7e2c90f55690c06a3", - "reference": "53330f47520498c0ae1f61f7e2c90f55690c06a3", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/35ea11d335fd638b5882ff1725228b3d35496ab1", + "reference": "35ea11d335fd638b5882ff1725228b3d35496ab1", "shasum": "" }, "require": { @@ -1002,9 +1002,9 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/1.7.0" + "source": "https://github.com/guzzle/psr7/tree/1.8.1" }, - "time": "2020-09-30T07:37:11+00:00" + "time": "2021-03-21T16:25:00+00:00" }, { "name": "http-interop/http-factory-guzzle", @@ -7542,16 +7542,16 @@ }, { "name": "friendsofphp/php-cs-fixer", - "version": "v2.18.3", + "version": "v2.18.4", "source": { "type": "git", "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", - "reference": "ab99202fccff2a9f97592fbe1b5c76dd06df3513" + "reference": "06f764e3cb6d60822d8f5135205f9d32b5508a31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/ab99202fccff2a9f97592fbe1b5c76dd06df3513", - "reference": "ab99202fccff2a9f97592fbe1b5c76dd06df3513", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/06f764e3cb6d60822d8f5135205f9d32b5508a31", + "reference": "06f764e3cb6d60822d8f5135205f9d32b5508a31", "shasum": "" }, "require": { @@ -7634,7 +7634,7 @@ "description": "A tool to automatically fix PHP code style", "support": { "issues": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/issues", - "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.18.3" + "source": "https://github.com/FriendsOfPHP/PHP-CS-Fixer/tree/v2.18.4" }, "funding": [ { @@ -7642,7 +7642,7 @@ "type": "github" } ], - "time": "2021-03-10T19:39:05+00:00" + "time": "2021-03-20T14:52:33+00:00" }, { "name": "hamcrest/hamcrest-php", diff --git a/routes/web.php b/routes/web.php index d6fab4e..e5c9ec6 100644 --- a/routes/web.php +++ b/routes/web.php @@ -12,16 +12,12 @@ }); $router->get('version', function () { - return response('1.1.0', 200); + return response('1.1.1', 200); }); $router->group(['prefix' => 'auth'], function () use ($router) { $router->post('register', UserController::class . '@new'); - $router->post('login', AuthController::class . '@login'); - $router->post('logout', AuthController::class . '@logout'); - $router->post('refresh', AuthController::class . '@refresh'); - $router->get('me', AuthController::class . '@me'); }); $router->group(['prefix' => 'users'], function () use ($router) { @@ -54,4 +50,10 @@ $router->group(['prefix' => 'users'], function () use ($router) { $router->put('{id}', UserController::class . '@update'); }); + + $router->group(['prefix' => 'auth'], function () use ($router) { + $router->post('logout', AuthController::class . '@logout'); + $router->post('refresh', AuthController::class . '@refresh'); + $router->get('me', AuthController::class . '@me'); + }); }); diff --git a/tests/AuthTest.php b/tests/AuthTest.php index f590a96..776f166 100644 --- a/tests/AuthTest.php +++ b/tests/AuthTest.php @@ -2,6 +2,7 @@ use App\Models\User; use Illuminate\Support\Facades\Hash; +use Tymon\JWTAuth\Facades\JWTAuth; /** * @internal @@ -26,4 +27,40 @@ public function testLogin() $this->post('auth/login', ['email' => 'wrong@email.com', 'password' => $password]) ->seeStatusCode(401); } + + public function testLogout() + { + $this->refreshApplication(); + + $user = User::factory()->create(); + // NOTE: in order to make logout() function working we have to pass the JWT token -> can't use standard actingAs function + $token = JWTAuth::fromUser($user); + + $this->post('auth/logout', [], ['Authorization' => 'Bearer ' . $token]) + ->seeStatusCode(200) + ->seeJson(['message' => 'Successfully logged out']); + } + + public function testRefresh() + { + $this->refreshApplication(); + + $user = User::factory()->create(); + // NOTE: in order to make logout() function working we have to pass the JWT token -> can't use standard actingAs function + $token = JWTAuth::fromUser($user); + + $this->post('auth/refresh', [], ['Authorization' => 'Bearer ' . $token]) + ->seeStatusCode(200) + ->seeJson(['token_type' => 'bearer']); + } + + public function testMe() + { + $user = User::factory()->create(); + $this->actingAs($user); + + $this->get('auth/me') + ->seeStatusCode(200) + ->seeJson(['id' => $user->id, 'email' => $user->email]); + } } diff --git a/tests/MultipartFormDataTest.php b/tests/MultipartFormDataTest.php new file mode 100644 index 0000000..dfefa50 --- /dev/null +++ b/tests/MultipartFormDataTest.php @@ -0,0 +1,25 @@ +create(); + $post = Post::factory()->create([ + 'user_id' => $user->id, + ]); + $newText = Str::random(300); + + $this->actingAs($user); + $this->put( + 'posts/' . $post->id, + ['text' => $newText], + ['Content-Type' => 'multipart/form-data'] + ) + ->seeStatusCode(200); + } +} diff --git a/tests/UserTest.php b/tests/UserTest.php index a32c74f..66251a6 100644 --- a/tests/UserTest.php +++ b/tests/UserTest.php @@ -47,7 +47,7 @@ public function testUserUpdate() // NOTE: in order to make logout() function working we have to pass the JWT token -> can't use standard actingAs function $token = JWTAuth::fromUser($user); - $this->put('users/' . $user->id . '?token=' . $token, ['email' => $email, 'password' => $password]) + $this->put('users/' . $user->id, ['email' => $email, 'password' => $password], ['Authorization' => 'Bearer ' . $token]) ->seeStatusCode(200); }