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\Models\Solo;
9
10use App\Libraries\Search\ScoreSearch;
11use App\Models\Beatmap;
12use App\Models\Beatmapset;
13use App\Models\Country;
14use App\Models\Genre;
15use App\Models\Group;
16use App\Models\Language;
17use App\Models\Solo\Score;
18use App\Models\User;
19use App\Models\UserGroup;
20use App\Models\UserGroupEvent;
21use App\Models\UserRelation;
22use Tests\TestCase;
23
24/**
25 * @group RequiresScoreIndexer
26 */
27class ScoreEsIndexTest extends TestCase
28{
29 private static Beatmap $beatmap;
30 private static array $scores;
31 private static User $user;
32
33 protected $connectionsToTransact = [];
34
35 public static function setUpBeforeClass(): void
36 {
37 static::withDbAccess(function () {
38 static::$user = User::factory()->create(['osu_subscriber' => true]);
39 $otherUser = User::factory()->create(['country_acronym' => Country::factory()]);
40 static::$beatmap = Beatmap::factory()->qualified()->create();
41
42 $scoreFactory = Score::factory()->state(['preserve' => true]);
43
44 $mods = [
45 ['acronym' => 'DT', 'settings' => []],
46 ['acronym' => 'HD', 'settings' => []],
47 ];
48 $unrelatedMods = [
49 ['acronym' => 'NC', 'settings' => []],
50 ];
51
52 static::$scores = [
53 'otherUser' => $scoreFactory->withData([
54 'mods' => $unrelatedMods,
55 ])->create([
56 'beatmap_id' => static::$beatmap,
57 'total_score' => 1150,
58 'user_id' => $otherUser,
59 ]),
60 'otherUserMods' => $scoreFactory->withData([
61 'mods' => $mods,
62 ])->create([
63 'beatmap_id' => static::$beatmap,
64 'total_score' => 1140,
65 'user_id' => $otherUser,
66 ]),
67 'otherUser2' => $scoreFactory->withData([
68 'mods' => $mods,
69 ])->create([
70 'beatmap_id' => static::$beatmap,
71 'total_score' => 1150,
72 'user_id' => User::factory()->state(['country_acronym' => Country::factory()]),
73 ]),
74 'otherUser3SameCountry' => $scoreFactory->withData([
75 'mods' => $unrelatedMods,
76 ])->create([
77 'beatmap_id' => static::$beatmap,
78 'total_score' => 1130,
79 'user_id' => User::factory()->state(['country_acronym' => static::$user->country_acronym]),
80 ]),
81 'user' => $scoreFactory->create([
82 'beatmap_id' => static::$beatmap,
83 'total_score' => 1100,
84 'user_id' => static::$user,
85 ]),
86 'userMods' => $scoreFactory->withData([
87 'mods' => $mods,
88 ])->create([
89 'beatmap_id' => static::$beatmap,
90 'total_score' => 1050,
91 'user_id' => static::$user,
92 ]),
93 ];
94
95 static::reindexScores();
96 });
97 }
98
99 public static function tearDownAfterClass(): void
100 {
101 parent::tearDownAfterClass();
102
103 static::withDbAccess(function () {
104 Beatmap::truncate();
105 Beatmapset::truncate();
106 Country::truncate();
107 Genre::truncate();
108 Language::truncate();
109 Score::select()->delete(); // TODO: revert to truncate after the table is actually renamed
110 User::truncate();
111 UserGroup::truncate();
112 UserGroupEvent::truncate();
113 UserRelation::truncate();
114 (new ScoreSearch())->deleteAll();
115 });
116 }
117
118 /**
119 * @dataProvider dataProviderForTestUserRank
120 */
121 public function testUserRank(string $key, ?array $params, int $rank): void
122 {
123 $score = static::$scores[$key]->fresh();
124
125 $this->assertSame($rank, $score->userRank($params));
126 }
127
128 public static function dataProviderForTestUserRank(): array
129 {
130 return [
131 ['user', null, 4],
132 ['user', ['type' => 'country'], 2],
133 ['userMods', ['mods' => ['DT', 'HD']], 3],
134 ];
135 }
136}