| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- <?php
- namespace Tests\Unit;
- use App\Services\WorldCup\Repositories\WorldCupMatchRepositoryInterface;
- use App\Services\WorldCup\WorldCupMatchFavoriteService;
- use Carbon\Carbon;
- use Tests\TestCase;
- class WorldCupMatchFavoriteServiceTest extends TestCase
- {
- public function test_toggle_favorite_adds_and_removes_match()
- {
- $repository = new InMemoryWorldCupMatchRepository();
- $service = new WorldCupMatchFavoriteService($repository);
- $now = Carbon::parse('2026-06-05 12:00:00');
- $added = $service->toggleFavorite(1001, 10, $now);
- $removed = $service->toggleFavorite(1001, 10, $now);
- $this->assertTrue($added['success']);
- $this->assertTrue($added['is_favorite']);
- $this->assertTrue($removed['success']);
- $this->assertFalse($removed['is_favorite']);
- }
- public function test_match_list_marks_only_current_user_favorites()
- {
- $repository = new InMemoryWorldCupMatchRepository();
- $repository->addFavorite(1001, 10);
- $repository->addFavorite(2002, 11);
- $service = new WorldCupMatchFavoriteService($repository);
- $matches = $service->listMatches(1001, false, Carbon::parse('2026-06-05 12:00:00'));
- $this->assertTrue($matches[0]['is_favorite']);
- $this->assertFalse($matches[1]['is_favorite']);
- }
- public function test_match_list_keeps_schedule_metadata_for_frontend()
- {
- $repository = new InMemoryWorldCupMatchRepository();
- $service = new WorldCupMatchFavoriteService($repository);
- $matches = $service->listMatches(1001, false, Carbon::parse('2026-06-05 12:00:00'));
- $this->assertSame(1, $matches[0]['match_no']);
- $this->assertSame('group', $matches[0]['stage']);
- $this->assertSame('A', $matches[0]['group_name']);
- $this->assertSame('Mexico City Stadium', $matches[0]['venue']);
- }
- public function test_match_list_returns_closed_future_schedule_as_not_bettable()
- {
- $repository = new InMemoryWorldCupMatchRepository();
- $service = new WorldCupMatchFavoriteService($repository);
- $matches = $service->listMatches(1001, false, Carbon::parse('2026-06-05 12:00:00'));
- $this->assertSame(73, $matches[2]['match_no']);
- $this->assertSame('Winner 73 A', $matches[2]['home_team']);
- $this->assertFalse($matches[2]['is_bettable']);
- }
- public function test_favorite_filter_returns_only_favorites_and_keeps_cutoff_filter()
- {
- $repository = new InMemoryWorldCupMatchRepository();
- $repository->addFavorite(1001, 10);
- $repository->addFavorite(1001, 12);
- $service = new WorldCupMatchFavoriteService($repository);
- $matches = $service->listMatches(1001, true, Carbon::parse('2026-06-05 12:00:00'));
- $this->assertCount(1, $matches);
- $this->assertSame(10, $matches[0]['match_id']);
- $this->assertTrue($matches[0]['is_favorite']);
- }
- }
- class InMemoryWorldCupMatchRepository implements WorldCupMatchRepositoryInterface
- {
- private $favorites = [];
- private $matches = [
- [
- 'match_id' => 10,
- 'match_no' => 1,
- 'competition' => 'World Cup',
- 'stage' => 'group',
- 'group_name' => 'A',
- 'home_team' => 'Mexico',
- 'away_team' => 'South Africa',
- 'venue' => 'Mexico City Stadium',
- 'kickoff_at' => '2026-06-05 15:00:00',
- 'status' => 'scheduled',
- ],
- [
- 'match_id' => 11,
- 'match_no' => 2,
- 'competition' => 'World Cup',
- 'stage' => 'group',
- 'group_name' => 'A',
- 'home_team' => 'France',
- 'away_team' => 'Spain',
- 'venue' => 'Estadio Guadalajara',
- 'kickoff_at' => '2026-06-05 18:00:00',
- 'status' => 'scheduled',
- ],
- [
- 'match_id' => 12,
- 'match_no' => 3,
- 'competition' => 'World Cup',
- 'stage' => 'group',
- 'group_name' => 'B',
- 'home_team' => 'Germany',
- 'away_team' => 'Italy',
- 'venue' => 'Toronto Stadium',
- 'kickoff_at' => '2026-06-05 12:30:00',
- 'status' => 'scheduled',
- ],
- [
- 'match_id' => 73,
- 'match_no' => 73,
- 'competition' => 'World Cup',
- 'stage' => 'round_32',
- 'group_name' => null,
- 'home_team' => 'Winner 73 A',
- 'away_team' => 'Winner 73 B',
- 'venue' => 'Los Angeles Stadium',
- 'kickoff_at' => '2026-07-01 12:00:00',
- 'status' => 'closed',
- ],
- ];
- public function getScheduleMatches(Carbon $now): array
- {
- $cutoff = $now->copy()->addHour();
- return array_values(array_filter($this->matches, function (array $match) use ($cutoff) {
- return in_array($match['status'], ['scheduled', 'closed'], true)
- && Carbon::parse($match['kickoff_at'])->gt($cutoff);
- }));
- }
- public function getOpenMatches(Carbon $now): array
- {
- $cutoff = $now->copy()->addHour();
- return array_values(array_filter($this->matches, function (array $match) use ($cutoff) {
- return $match['status'] === 'scheduled'
- && Carbon::parse($match['kickoff_at'])->gt($cutoff);
- }));
- }
- public function isOpenMatch(int $matchId, Carbon $now): bool
- {
- foreach ($this->getOpenMatches($now) as $match) {
- if ((int)$match['match_id'] === $matchId) {
- return true;
- }
- }
- return false;
- }
- public function getFavoriteMatchIds(int $userId): array
- {
- return array_values($this->favorites[$userId] ?? []);
- }
- public function isFavorite(int $userId, int $matchId): bool
- {
- return in_array($matchId, $this->favorites[$userId] ?? [], true);
- }
- public function addFavorite(int $userId, int $matchId): void
- {
- if (!isset($this->favorites[$userId])) {
- $this->favorites[$userId] = [];
- }
- if (!$this->isFavorite($userId, $matchId)) {
- $this->favorites[$userId][] = $matchId;
- }
- }
- public function removeFavorite(int $userId, int $matchId): void
- {
- $this->favorites[$userId] = array_values(array_filter(
- $this->favorites[$userId] ?? [],
- function ($favoriteMatchId) use ($matchId) {
- return (int)$favoriteMatchId !== $matchId;
- }
- ));
- }
- }
|