1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6declare(strict_types=1);
7
8namespace Tests\Libraries\User;
9
10use App\Libraries\User\CountryChangeTarget;
11use App\Models\Country;
12use App\Models\Tournament;
13use App\Models\User;
14use Carbon\CarbonImmutable;
15use Database\Factories\UserFactory;
16use Tests\TestCase;
17
18class CountryChangeTargetTest extends TestCase
19{
20 public function testGetNoData(): void
21 {
22 $user = User::factory()->create();
23
24 $this->assertNull(CountryChangeTarget::get($user));
25 }
26
27 public function testGetNotEnoughMonths(): void
28 {
29 $user = User::factory()->create();
30 $targetCountry = Country::factory()->create()->getKey();
31 UserFactory::createRecentCountryHistory($user, $targetCountry, CountryChangeTarget::minMonths() - 1);
32
33 $this->assertNull(CountryChangeTarget::get($user));
34 }
35
36 public function testGetEnoughMonths(): void
37 {
38 $user = User::factory()->create();
39 $targetCountry = Country::factory()->create()->getKey();
40 UserFactory::createRecentCountryHistory($user, $targetCountry, null);
41
42 $this->assertSame($targetCountry, CountryChangeTarget::get($user));
43 }
44
45 public function testGetEnoughMonthsMixed(): void
46 {
47 $user = User::factory()->create();
48 $targetCountry = Country::factory()->create()->getKey();
49 UserFactory::createRecentCountryHistory($user, $targetCountry, null);
50 UserFactory::createRecentCountryHistory($user, null, CountryChangeTarget::maxMixedMonths());
51
52 $this->assertSame($targetCountry, CountryChangeTarget::get($user));
53 }
54
55 public function testGetEnoughMonthsMixedTooMany(): void
56 {
57 $user = User::factory()->create();
58 $targetCountry = Country::factory()->create()->getKey();
59 UserFactory::createRecentCountryHistory($user, $targetCountry, null);
60 UserFactory::createRecentCountryHistory($user, null, CountryChangeTarget::maxMixedMonths() + 1);
61
62 $this->assertNull(CountryChangeTarget::get($user));
63 }
64
65 public function testGetInRunningTournament(): void
66 {
67 $user = User::factory()->create();
68 $targetCountry = Country::factory()->create()->getKey();
69 UserFactory::createRecentCountryHistory($user, $targetCountry, null);
70 $tournament = Tournament::factory()->create();
71 $tournament->registrations()->create([
72 'user_id' => $user->getKey(),
73 ]);
74
75 $this->assertNull(CountryChangeTarget::get($user));
76 }
77
78 public function testGetInPastTournament(): void
79 {
80 $user = User::factory()->create();
81 $targetCountry = Country::factory()->create()->getKey();
82 UserFactory::createRecentCountryHistory($user, $targetCountry, null);
83 $tournament = Tournament::factory()->create(['end_date' => CarbonImmutable::now()->subMonths(1)]);
84 $tournament->registrations()->create([
85 'user_id' => $user->getKey(),
86 ]);
87
88 $this->assertSame($targetCountry, CountryChangeTarget::get($user));
89 }
90
91 public function testGetLastMonthDifferentCountry(): void
92 {
93 $user = User::factory()->create();
94 $targetCountry = Country::factory()->create()->getKey();
95 UserFactory::createRecentCountryHistory($user, $targetCountry, CountryChangeTarget::minMonths() + 1);
96
97 $user
98 ->userCountryHistory()
99 ->orderBy('year_month', 'DESC')
100 ->first()
101 ->fill(['country_acronym' => Country::factory()->create()->getKey()])
102 ->saveOrExplode();
103
104 $this->assertNull(CountryChangeTarget::get($user));
105 }
106
107 public function testGetWithBlankMonth(): void
108 {
109 $user = User::factory()->create();
110 $targetCountry = Country::factory()->create()->getKey();
111 $minMonths = CountryChangeTarget::minMonths();
112 UserFactory::createRecentCountryHistory($user, $targetCountry, $minMonths + 1);
113
114 $user
115 ->userCountryHistory()
116 ->where('year_month', '>', format_month_column(CountryChangeTarget::currentMonth()->subMonths($minMonths)))
117 ->inRandomOrder()
118 ->limit(1)
119 ->delete();
120
121 $this->assertSame($targetCountry, CountryChangeTarget::get($user));
122 }
123
124 public function testGetWithBlankMonths(): void
125 {
126 $user = User::factory()->create();
127 $targetCountry = Country::factory()->create()->getKey();
128 $minMonths = CountryChangeTarget::minMonths();
129 UserFactory::createRecentCountryHistory($user, $targetCountry, $minMonths + 3);
130
131 $user
132 ->userCountryHistory()
133 ->where('year_month', '>', format_month_column(CountryChangeTarget::currentMonth()->subMonths($minMonths)))
134 ->inRandomOrder()
135 ->limit(2)
136 ->delete();
137
138 $this->assertSame($targetCountry, CountryChangeTarget::get($user));
139 }
140}