diff --git a/src/app/Models/User.php b/src/app/Models/User.php index 741315d8..62c8754c 100644 --- a/src/app/Models/User.php +++ b/src/app/Models/User.php @@ -2,6 +2,7 @@ namespace App\Models; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Foundation\Auth\User as Authenticatable; use Laravel\Sanctum\HasApiTokens; @@ -33,4 +34,14 @@ protected function casts(): array 'email_verified_at' => 'datetime', ]; } + + public function favorites(): BelongsToMany + { + return $this->belongsToMany( + WorldHeritage::class, + 'user_favorite', + 'user_id', + 'world_heritage_site_id' + ); + } } \ No newline at end of file diff --git a/src/app/Packages/Domains/Favorite/FavoriteRepository.php b/src/app/Packages/Domains/Favorite/FavoriteRepository.php new file mode 100644 index 00000000..6fa2205d --- /dev/null +++ b/src/app/Packages/Domains/Favorite/FavoriteRepository.php @@ -0,0 +1,25 @@ +userModel->find($userId); + + if ($user === null) { + throw new Exception('User not found.'); + } + + $user->favorites()->attach($worldHeritageSiteId); + } +} diff --git a/src/app/Packages/Domains/Favorite/Interface/FavoriteRepositoryInterface.php b/src/app/Packages/Domains/Favorite/Interface/FavoriteRepositoryInterface.php new file mode 100644 index 00000000..7b1291ac --- /dev/null +++ b/src/app/Packages/Domains/Favorite/Interface/FavoriteRepositoryInterface.php @@ -0,0 +1,8 @@ +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;'); + DB::connection('mysql')->table('user_favorite')->truncate(); + WorldHeritage::truncate(); + User::truncate(); + DB::connection('mysql')->statement('SET FOREIGN_KEY_CHECKS=1;'); + } + } + + private function repository(): FavoriteRepository + { + return new FavoriteRepository(new User()); + } + + private function seedUser(): User + { + $faker = FakerFactory::create(); + + return User::create([ + '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, + ]); + } + + private function seedWorldHeritage(int $id): WorldHeritage + { + return WorldHeritage::create([ + 'id' => $id, + 'official_name' => 'Example Site', + 'name' => 'Example Site', + 'region' => 'Asia', + 'category' => 'Cultural', + 'criteria' => ['i'], + 'year_inscribed' => 2000, + ]); + } + + public function test_addFavorite_attaches_world_heritage_site_to_user(): void + { + $user = $this->seedUser(); + $worldHeritage = $this->seedWorldHeritage(1); + + $this->repository()->addFavorite($user->id, $worldHeritage->id); + + $this->assertDatabaseHas('user_favorite', [ + 'user_id' => $user->id, + 'world_heritage_site_id' => $worldHeritage->id, + ]); + } + + public function test_addFavorite_throws_exception_when_user_not_found(): void + { + $worldHeritage = $this->seedWorldHeritage(1); + + $this->expectException(Exception::class); + $this->expectExceptionMessage('User not found.'); + + $this->repository()->addFavorite(999999, $worldHeritage->id); + } +} diff --git a/src/app/Providers/RepositoryProvider.php b/src/app/Providers/RepositoryProvider.php index cbba05bf..50348344 100644 --- a/src/app/Providers/RepositoryProvider.php +++ b/src/app/Providers/RepositoryProvider.php @@ -2,6 +2,8 @@ namespace App\Providers; +use App\Packages\Domains\Favorite\FavoriteRepository; +use App\Packages\Domains\Favorite\Interface\FavoriteRepositoryInterface; use App\Packages\Domains\User\Interface\UserRepositroyInterface; use App\Packages\Domains\User\UserRepository; use App\Packages\Domains\WorldHeritageRepository; @@ -21,6 +23,11 @@ public function register(): void UserRepositroyInterface::class, UserRepository::class ); + + $this->app->bind( + FavoriteRepositoryInterface::class, + FavoriteRepository::class + ); } public function boot(): void