| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- <?php
- namespace Tests\Unit;
- use App\Services\WorldCup\Repositories\WorldCupScheduleRepositoryInterface;
- use App\Services\WorldCup\WorldCupScheduleUpdateService;
- use Tests\TestCase;
- class WorldCupScheduleUpdateServiceTest extends TestCase
- {
- public function test_lists_all_matches_for_admin_form()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $matches = $service->allMatches();
- $this->assertCount(3, $matches);
- $this->assertSame(72, $matches[0]['match_no']);
- $this->assertSame(104, $matches[2]['match_no']);
- }
- public function test_updates_checked_form_rows_across_all_schedule()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $result = $service->updateMatches([
- [
- 'enabled' => '1',
- 'match_no' => 72,
- 'home_team' => 'Croatia Updated',
- 'away_team' => 'Ghana',
- 'venue' => 'Philadelphia',
- 'kickoff_at' => '2026-06-27 21:00:00',
- 'status' => 'scheduled',
- ],
- [
- 'enabled' => '0',
- 'match_no' => 104,
- 'home_team' => 'France',
- 'away_team' => 'Brazil',
- 'status' => 'closed',
- ],
- ], 'admin-01');
- $this->assertTrue($result['success']);
- $this->assertSame(1, $result['data']['updated']);
- $this->assertSame(1, $result['data']['skipped']);
- $this->assertSame('Croatia Updated', $repository->matches[72]['home_team']);
- $this->assertSame('Winner 104 A', $repository->matches[104]['home_team']);
- }
- public function test_updates_only_unresolved_matches_for_selected_date()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $result = $service->updateUnresolvedMatches('2026-07-19', [
- [
- 'match_no' => 104,
- 'home_team' => 'France',
- 'away_team' => 'Brazil',
- 'venue' => 'East Rutherford',
- ],
- [
- 'match_no' => 103,
- 'home_team' => 'Argentina',
- 'away_team' => 'England',
- ],
- [
- 'match_no' => 72,
- 'home_team' => 'Croatia',
- 'away_team' => 'Ghana',
- ],
- ], 'admin-01');
- $this->assertTrue($result['success']);
- $this->assertSame(1, $result['data']['updated']);
- $this->assertSame(2, $result['data']['skipped']);
- $this->assertSame('France', $repository->matches[104]['home_team']);
- $this->assertSame('Brazil', $repository->matches[104]['away_team']);
- $this->assertSame('closed', $repository->matches[104]['status']);
- $this->assertSame('Winner 103 A', $repository->matches[103]['home_team']);
- $this->assertSame('Croatia', $repository->matches[72]['home_team']);
- $this->assertSame('schedule_update', $repository->audits[0]['action']);
- }
- public function test_allows_operator_to_open_match_when_status_is_scheduled()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $result = $service->updateUnresolvedMatches('2026-07-19', [
- [
- 'match_no' => 104,
- 'home_team' => 'France',
- 'away_team' => 'Brazil',
- 'status' => 'scheduled',
- ],
- ], 'admin-01');
- $this->assertTrue($result['success']);
- $this->assertSame('scheduled', $repository->matches[104]['status']);
- }
- public function test_rejects_invalid_payload_rows()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $result = $service->updateUnresolvedMatches('2026-07-19', [
- ['match_no' => '', 'home_team' => 'France', 'away_team' => 'Brazil'],
- ['match_no' => 104, 'home_team' => '', 'away_team' => 'Brazil'],
- ['match_no' => 104, 'home_team' => 'France', 'away_team' => 'Brazil', 'status' => 'open'],
- ], 'admin-01');
- $this->assertFalse($result['success']);
- $this->assertSame(0, $result['data']['updated']);
- $this->assertCount(3, $result['data']['errors']);
- }
- public function test_rejects_invalid_schedule_date()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $result = $service->updateUnresolvedMatches('2026/07/19', [], 'admin-01');
- $this->assertFalse($result['success']);
- $this->assertSame('Invalid schedule date', $result['message']);
- }
- public function test_imports_existing_matches_from_csv_rows_by_match_id()
- {
- $repository = new InMemoryWorldCupScheduleRepository();
- $service = new WorldCupScheduleUpdateService($repository);
- $result = $service->importExistingMatches([
- [
- 'match_id' => '104',
- 'home_name' => 'France',
- 'away_name' => 'Brazil',
- ],
- [
- 'match_id' => '103',
- 'home_name' => 'Argentina',
- 'away_name' => 'England',
- ],
- [
- 'match_id' => '',
- 'home_name' => 'Spain',
- 'away_name' => 'Portugal',
- ],
- ], 'admin-01');
- $this->assertTrue($result['success']);
- $this->assertSame(2, $result['data']['updated']);
- $this->assertSame(0, $result['data']['skipped']);
- $this->assertCount(1, $result['data']['errors']);
- $this->assertSame('France', $repository->matches[104]['home_team']);
- $this->assertSame('Brazil', $repository->matches[104]['away_team']);
- $this->assertSame('schedule_import', $repository->audits[0]['action']);
- }
- }
- class InMemoryWorldCupScheduleRepository implements WorldCupScheduleRepositoryInterface
- {
- public $matches = [
- 72 => [
- 'match_no' => 72,
- 'home_team' => 'Croatia',
- 'away_team' => 'Ghana',
- 'venue' => 'Philadelphia',
- 'kickoff_at' => '2026-06-27 21:00:00',
- 'status' => 'scheduled',
- ],
- 103 => [
- 'match_no' => 103,
- 'home_team' => 'Winner 103 A',
- 'away_team' => 'Winner 103 B',
- 'venue' => 'Miami Gardens',
- 'kickoff_at' => '2026-07-18 21:00:00',
- 'status' => 'closed',
- ],
- 104 => [
- 'match_no' => 104,
- 'home_team' => 'Winner 104 A',
- 'away_team' => 'Winner 104 B',
- 'venue' => 'East Rutherford',
- 'kickoff_at' => '2026-07-19 19:00:00',
- 'status' => 'closed',
- ],
- ];
- public $audits = [];
- public function unresolvedMatchesByDate(string $scheduleDate): array
- {
- return array_values(array_filter($this->matches, function (array $match) use ($scheduleDate) {
- return substr($match['kickoff_at'], 0, 10) === $scheduleDate
- && $this->isUnresolved($match);
- }));
- }
- public function allMatches(): array
- {
- ksort($this->matches);
- return array_values($this->matches);
- }
- public function matchesByDate(string $scheduleDate): array
- {
- return array_values(array_filter($this->matches, function (array $match) use ($scheduleDate) {
- return substr($match['kickoff_at'], 0, 10) === $scheduleDate;
- }));
- }
- public function updateMatchByNoAndDate(
- int $matchNo,
- string $scheduleDate,
- array $attributes
- ): bool {
- if (!isset($this->matches[$matchNo])) {
- return false;
- }
- if (substr($this->matches[$matchNo]['kickoff_at'], 0, 10) !== $scheduleDate) {
- return false;
- }
- if (!$this->isUnresolved($this->matches[$matchNo])) {
- return false;
- }
- $this->matches[$matchNo] = array_merge($this->matches[$matchNo], $attributes);
- return true;
- }
- public function updateMatchByNo(int $matchNo, array $attributes): bool
- {
- if (!isset($this->matches[$matchNo])) {
- return false;
- }
- $this->matches[$matchNo] = array_merge($this->matches[$matchNo], $attributes);
- return true;
- }
- public function updateMatchById(int $matchId, array $attributes): bool
- {
- return $this->updateMatchByNo($matchId, $attributes);
- }
- public function writeScheduleAudit(string $actor, string $action, array $payload): void
- {
- $this->audits[] = compact('actor', 'action', 'payload');
- }
- private function isUnresolved(array $match): bool
- {
- return strpos($match['home_team'], 'Winner ') === 0
- || strpos($match['away_team'], 'Winner ') === 0;
- }
- }
|