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
6namespace Tests\Controllers\InterOp;
7
8use App\Models\Achievement;
9use App\Models\Country;
10use App\Models\User;
11use Tests\TestCase;
12
13class UsersControllerTest extends TestCase
14{
15 public function testAchievement()
16 {
17 $achievementName = 'Test Achievement';
18 $username = 'username1';
19 $user = User::factory()->create(['username' => $username]);
20 $achievement = Achievement::factory()->create(['name' => $achievementName]);
21
22 $this->expectCountChange(fn () => $user->userAchievements()->count(), 1);
23 $this->expectCountChange(fn () => $user->userNotifications()->count(), 1);
24 $this->expectCountChange(fn () => $user->events()->count(), 1);
25
26 $url = route('interop.users.achievement', [
27 'achievement' => $achievement->getKey(),
28 'timestamp' => time(),
29 'user' => $user->getKey(),
30 ]);
31
32 $this
33 ->withInterOpHeader($url)
34 ->post($url)
35 ->assertSuccessful();
36
37 $userUrl = route('users.show', ['user' => $user->getKey()], false);
38 $this->assertSame(
39 "<b><a href='{$userUrl}'>{$username}</a></b> unlocked the \"<b>{$achievementName}</b>\" medal!",
40 $user->events()->last()->text,
41 );
42 }
43
44 public function testAchievementDuplicate()
45 {
46 $achievementName = 'Test Achievement';
47 $username = 'username1';
48 $user = User::factory()->create(['username' => $username]);
49 $achievement = Achievement::factory()->create(['name' => $achievementName]);
50 $user->userAchievements()->create([
51 'achievement_id' => $achievement->getKey(),
52 ]);
53
54 $this->expectCountChange(fn () => $user->userAchievements()->count(), 0);
55 $this->expectCountChange(fn () => $user->userNotifications()->count(), 0);
56 $this->expectCountChange(fn () => $user->events()->count(), 0);
57
58 $url = route('interop.users.achievement', [
59 'achievement' => $achievement->getKey(),
60 'timestamp' => time(),
61 'user' => $user->getKey(),
62 ]);
63
64 $this
65 ->withInterOpHeader($url)
66 ->post($url)
67 ->assertStatus(422);
68 }
69
70 public function testStore()
71 {
72 $previousCount = User::count();
73 $country = Country::factory()->create();
74 $url = route('interop.users.store', ['timestamp' => time()]);
75
76 $this
77 ->withInterOpHeader($url)
78 ->json('POST', $url, [
79 'user' => [
80 'country_acronym' => $country->getKey(),
81 'password' => 'password',
82 'user_email' => 'test@user.com',
83 'username' => 'testuser',
84 ],
85 ])->assertJsonFragment([
86 'username' => 'testuser',
87 ]);
88
89 $this->assertSame($previousCount + 1, User::count());
90 }
91
92 public function testStoreUserCopy()
93 {
94 $country = Country::factory()->create();
95 $sourceUser = User::factory()->create(['country_acronym' => $country->getKey(), 'user_ip' => '127.0.0.1']);
96 $url = route('interop.users.store', ['timestamp' => time()]);
97 $username = 'userbot';
98 $group = 'bot';
99 $previousCount = User::count();
100
101 $this
102 ->withInterOpHeader($url)
103 ->json('POST', $url, [
104 'source_user_id' => $sourceUser->getKey(),
105 'user' => [
106 'username' => $username,
107 'group' => $group,
108 ],
109 ])->assertJsonFragment([
110 'username' => $username,
111 ]);
112
113 $this->assertSame($previousCount + 1, User::count());
114
115 $user = User::where(['username' => $username])->first();
116
117 foreach (['user_password', 'user_ip', 'country_acronym'] as $copiedAttribute) {
118 $this->assertSame($sourceUser->$copiedAttribute, $user->$copiedAttribute, $copiedAttribute);
119 }
120
121 $this->assertStringContainsString("+{$username}@", $user->user_email);
122 $this->assertTrue($user->isGroup(app('groups')->byIdentifier($group)));
123 }
124
125 public function testStoreUserCopyMissingUsername()
126 {
127 $country = Country::factory()->create();
128 $sourceUser = User::factory()->create(['country_acronym' => $country->getKey(), 'user_ip' => '127.0.0.1']);
129
130 $previousCount = User::count();
131 $url = route('interop.users.store', ['timestamp' => time()]);
132
133 $this
134 ->withInterOpHeader($url)
135 ->json('POST', $url, [
136 'source_user_id' => $sourceUser->getKey(),
137 ])->assertStatus(422);
138
139 $this->assertSame($previousCount, User::count());
140 }
141}