diff --git a/src/app/Packages/Features/Controller/UserController.php b/src/app/Packages/Features/Controller/UserController.php index eec537f..9917562 100644 --- a/src/app/Packages/Features/Controller/UserController.php +++ b/src/app/Packages/Features/Controller/UserController.php @@ -5,7 +5,9 @@ use App\Http\Controllers\Controller; use App\Packages\Features\QueryUseCases\Factory\ViewModel\UserViewModelFactory; use App\Packages\Features\CommandUseCases\UseCase\User\CreateUserUseCase; +use App\Packages\Features\CommandUseCases\UseCase\User\UpdateUserUseCase; use App\Packages\Features\CommandUseCases\UseCommand\User\CreateUserCommand; +use App\Packages\Features\CommandUseCases\UseCommand\User\UpdateUserCommand; use App\Packages\Features\QueryUseCases\UseCase\User\GetUserByIdUseCase; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -44,6 +46,41 @@ public function getUserById( } } + public function updateUser( + Request $request, + UpdateUserUseCase $useCase, + ): JsonResponse { + try { + $command = UpdateUserCommand::fromArray(array_merge( + $request->all(), + ['id' => $request->route('id')], + )); + $dto = $useCase->handle($command); + + return response()->json([ + 'status' => 'success', + 'data' => UserViewModelFactory::build($dto)->toArray(), + ], 200); + } catch (\Exception $exception) { + if ($exception->getMessage() === 'User not found.') { + return response()->json([ + 'status' => 'error', + 'message' => 'User not found.', + ], 404); + } + + Log::error('Failed to update user', [ + 'message' => $exception->getMessage(), + 'trace' => $exception->getTraceAsString(), + ]); + + return response()->json([ + 'status' => 'error', + 'message' => 'Internal Server Error', + ], 500); + } + } + public function createUser( Request $request, CreateUserUseCase $useCase, diff --git a/src/app/Packages/Features/Tests/UpdateUserTest.php b/src/app/Packages/Features/Tests/UpdateUserTest.php new file mode 100644 index 0000000..b375ab5 --- /dev/null +++ b/src/app/Packages/Features/Tests/UpdateUserTest.php @@ -0,0 +1,109 @@ +truncate(); + } + + protected function tearDown(): void + { + $this->truncate(); + parent::tearDown(); + } + + private function truncate(): void + { + if (env('APP_ENV') === 'testing') { + DB::connection('mysql')->statement('SET FOREIGN_KEY_CHECKS=0;'); + User::truncate(); + DB::connection('mysql')->statement('SET FOREIGN_KEY_CHECKS=1;'); + } + } + + private function seedUser(array $overrides = []): User + { + $faker = FakerFactory::create(); + + return User::create(array_merge([ + 'first_name' => $faker->firstName(), + 'last_name' => $faker->lastName(), + 'email' => $faker->unique()->safeEmail(), + 'password' => bcrypt('password'), + 'age_range' => 'teens', + 'subscription_tier' => 'free', + 'subscription_expires_at' => null, + ], $overrides)); + } + + private function validPayload(array $overrides = []): array + { + $faker = FakerFactory::create(); + + return array_merge([ + 'first_name' => $faker->firstName(), + 'last_name' => $faker->lastName(), + 'email' => $faker->unique()->safeEmail(), + 'age_range' => '30s', + 'subscription_tier' => 'premium', + ], $overrides); + } + + public function test_update_user_returns_200_with_updated_data(): void + { + $user = $this->seedUser(); + + $payload = $this->validPayload(['email' => 'updated@example.com']); + $response = $this->patchJson("/api/v1/users/{$user->id}", $payload); + + $response->assertStatus(200) + ->assertJsonStructure([ + 'status', + 'data' => [ + 'id', + 'first_name', + 'last_name', + 'email', + 'age_range', + 'subscription_tier', + 'subscription_expires_at', + ], + ]) + ->assertJsonFragment([ + 'status' => 'success', + 'email' => 'updated@example.com', + ]); + } + + public function test_update_user_returns_404_when_user_not_found(): void + { + $response = $this->patchJson('/api/v1/users/999999', $this->validPayload()); + + $response->assertStatus(404) + ->assertJsonFragment([ + 'status' => 'error', + 'message' => 'User not found.', + ]); + } + + public function test_update_user_returns_500_when_required_key_is_missing(): void + { + $user = $this->seedUser(); + $payload = $this->validPayload(); + unset($payload['email']); + + $response = $this->patchJson("/api/v1/users/{$user->id}", $payload); + + $response->assertStatus(500) + ->assertJsonFragment(['status' => 'error']); + } +} diff --git a/src/routes/api.php b/src/routes/api.php index 7f5dcb8..a3d59bd 100644 --- a/src/routes/api.php +++ b/src/routes/api.php @@ -11,5 +11,6 @@ Route::get('/heritages/{id}', [WorldHeritageController::class, 'getWorldHeritageById']); Route::get('/users/{id}', [UserController::class, 'getUserById']); + Route::patch('/users/{id}', [UserController::class, 'updateUser']); Route::post('/user/create', [UserController::class, 'createUser']); }); \ No newline at end of file