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\Models;
7
8use App\Exceptions\ModelNotSavedException;
9use App\Models\Beatmap;
10use App\Models\BeatmapDiscussion;
11use App\Models\BeatmapDiscussionPost;
12use App\Models\Beatmapset;
13use App\Models\User;
14use Ds\Set;
15use Exception;
16use Tests\TestCase;
17
18class BeatmapDiscussionPostTest extends TestCase
19{
20 public function testMessageCharacterLimitGeneralAll()
21 {
22 $beatmapset = Beatmapset::factory()->create();
23 $beatmap = $beatmapset->beatmaps()->save(Beatmap::factory()->make());
24 $user = User::factory()->create();
25 $discussion = BeatmapDiscussion::create([
26 'beatmapset_id' => $beatmapset->getKey(),
27 'user_id' => $user->getKey(),
28 'message_type' => 'suggestion',
29 ]);
30
31 $post = $discussion->beatmapDiscussionPosts()->make([
32 'user_id' => $user->getKey(),
33 'message' => str_repeat('a', 2000),
34 ]);
35
36 $this->assertTrue($post->isValid());
37 }
38
39 public function testMessageCharacterLimitGeneral()
40 {
41 $beatmapset = Beatmapset::factory()->create();
42 $beatmap = $beatmapset->beatmaps()->save(Beatmap::factory()->make());
43 $user = User::factory()->create();
44 $discussion = BeatmapDiscussion::create([
45 'beatmapset_id' => $beatmapset->getKey(),
46 'beatmap_id' => $beatmap->getKey(),
47 'user_id' => $user->getKey(),
48 'message_type' => 'suggestion',
49 ]);
50
51 $post = $discussion->beatmapDiscussionPosts()->make([
52 'user_id' => $user->getKey(),
53 'message' => str_repeat('a', 2000),
54 ]);
55
56 $this->assertTrue($post->isValid());
57 }
58
59 public function testMessageCharacterLimitTimeline()
60 {
61 $beatmapset = Beatmapset::factory()->create();
62 $beatmap = $beatmapset->beatmaps()->save(Beatmap::factory()->make());
63 $user = User::factory()->create();
64 $discussion = BeatmapDiscussion::create([
65 'beatmapset_id' => $beatmapset->getKey(),
66 'beatmap_id' => $beatmap->getKey(),
67 'user_id' => $user->getKey(),
68 'message_type' => 'suggestion',
69 'timestamp' => 0,
70 ]);
71
72 $post = $discussion->beatmapDiscussionPosts()->make([
73 'user_id' => $user->getKey(),
74 'message' => str_repeat('a', 2000),
75 ]);
76
77 $this->assertFalse($post->isValid());
78
79 $post->message = str_repeat('b', BeatmapDiscussionPost::MESSAGE_LIMIT_TIMELINE);
80
81 $this->assertTrue($post->isValid());
82 }
83
84 public function testScopeOpenProblems()
85 {
86 $beatmapset = Beatmapset::factory()->create();
87 $beatmap = $beatmapset->beatmaps()->save(Beatmap::factory()->make());
88 $user = User::factory()->create();
89 $discussion = BeatmapDiscussion::create([
90 'beatmapset_id' => $beatmapset->getKey(),
91 'beatmap_id' => $beatmap->getKey(),
92 'user_id' => $user->getKey(),
93 'message_type' => 'problem',
94 ]);
95 $discussion->beatmapDiscussionPosts()->create([
96 'user_id' => $user->getKey(),
97 'message' => 'This is a problem',
98 ]);
99
100 $this->assertSame(1, $beatmapset->beatmapDiscussions()->openProblems()->count());
101
102 $beatmap->update(['deleted_at' => now()]);
103
104 $this->assertSame(0, $beatmapset->beatmapDiscussions()->openProblems()->count());
105 }
106
107 public function testScopeByTypes()
108 {
109 $beatmapset = Beatmapset::factory()->create();
110 $beatmap = $beatmapset->beatmaps()->save(Beatmap::factory()->make());
111 $user = User::factory()->create();
112 $discussion = BeatmapDiscussion::create([
113 'beatmapset_id' => $beatmapset->getKey(),
114 'beatmap_id' => $beatmap->getKey(),
115 'user_id' => $user->getKey(),
116 'message_type' => 'problem',
117 ]);
118 $posts = [
119 'first' => $discussion->beatmapDiscussionPosts()->create([
120 'user_id' => $user->getKey(),
121 'message' => 'This is a problem',
122 ]),
123 'reply' => $discussion->beatmapDiscussionPosts()->create([
124 'user_id' => $user->getKey(),
125 'message' => 'This is a reply',
126 ]),
127 'system' => BeatmapDiscussionPost::generateLogResolveChange($user, true),
128 ];
129 $posts['system']->fill(['beatmap_discussion_id' => $discussion->getKey()])->save();
130
131 $combinations = [];
132
133 foreach (array_keys($posts) as $key) {
134 $newCombinations = array_merge($combinations, [[$key]]);
135 foreach ($combinations as $combination) {
136 $newCombinations[] = array_merge($combination, [$key]);
137 }
138 $combinations = $newCombinations;
139 }
140
141 foreach ($combinations as $combination) {
142 $combinationString = implode(', ', $combination);
143 $queryResult = BeatmapDiscussionPost::byTypes(new Set($combination))->get();
144 $this->assertSame(count($combination), $queryResult->count(), 'count for '.$combinationString);
145 foreach ($combination as $type) {
146 $this->assertNotNull($queryResult->find($posts[$type]->getKey()), 'has '.$type.' for '.$combinationString);
147 }
148 }
149 }
150
151 public function testSoftDeleteOrExplode()
152 {
153 $beatmapset = Beatmapset::factory()->create();
154 $beatmap = $beatmapset->beatmaps()->save(Beatmap::factory()->make());
155 $user = User::factory()->create();
156 $discussion = BeatmapDiscussion::create([
157 'beatmapset_id' => $beatmapset->getKey(),
158 'beatmap_id' => $beatmap->getKey(),
159 'user_id' => $user->getKey(),
160 'message_type' => 'suggestion',
161 ]);
162 $startingPost = $discussion->beatmapDiscussionPosts()->create([
163 'user_id' => $user->getKey(),
164 'message' => 'Hello',
165 ]);
166 $post = $discussion->beatmapDiscussionPosts()->create([
167 'user_id' => $user->getKey(),
168 'message' => 'Hello',
169 ]);
170
171 $this->assertFalse($post->trashed());
172
173 // No soft delete starting post.
174 try {
175 $startingPost->softDeleteOrExplode($user);
176 } catch (Exception $e) {
177 $this->assertInstanceOf(ModelNotSavedException::class, $e);
178 }
179 $startingPost = $startingPost->fresh();
180 $this->assertFalse($startingPost->trashed());
181
182 // Soft delete.
183 $post->softDeleteOrExplode($user);
184 $post = $post->fresh();
185 $this->assertTrue($post->trashed());
186
187 // Restore.
188 $post->restore($user);
189 $post = $post->fresh();
190 $this->assertFalse($post->trashed());
191
192 // Soft delete with deleted discussion.
193 $discussion->softDeleteOrExplode($user);
194 $post->softDeleteOrExplode($user);
195 $post = $post->fresh();
196 $this->assertTrue($post->trashed());
197
198 // Restore with deleted discussion.
199 $post->restore($user);
200 $post = $post->fresh();
201 $this->assertFalse($post->trashed());
202 }
203}