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;
7
8use App\Events\NewPrivateNotificationEvent;
9use App\Jobs\Notifications\BeatmapsetDisqualify;
10use App\Models\Beatmap;
11use App\Models\Beatmapset;
12use App\Models\Notification;
13use App\Models\User;
14use App\Models\UserNotificationOption;
15use Event;
16use Queue;
17
18class BeatmapsetDisqualifyNotificationsTest extends TestCase
19{
20 /** @var Beatmapset */
21 protected $beatmapset;
22
23 /** @var User */
24 protected $sender;
25
26 /** @var User */
27 protected $user;
28
29 #region notification tests
30 public function testDuplicateNotificationNotSent()
31 {
32 $this->beatmapset->watches()->create(['user_id' => $this->user->getKey()]);
33 $this->createNotificationOption();
34
35 $this->disqualify()->assertStatus(200);
36
37 Queue::assertPushed(BeatmapsetDisqualify::class);
38
39 $this->runFakeQueue();
40
41 $events = Event::dispatched(NewPrivateNotificationEvent::class, function (NewPrivateNotificationEvent $event) {
42 if ($event->notification->name === Notification::BEATMAPSET_DISQUALIFY) {
43 $this->assertSame(array_unique($event->getReceiverIds()), $event->getReceiverIds());
44
45 return true;
46 }
47
48 return false;
49 });
50
51 $this->assertSame(1, $events->count());
52 }
53
54 public function testNotificationSentIfWatching()
55 {
56 $this->beatmapset->watches()->create(['user_id' => $this->user->getKey()]);
57
58 $this->disqualify()->assertStatus(200);
59
60 Queue::assertPushed(BeatmapsetDisqualify::class);
61
62 $this->runFakeQueue();
63
64 Event::assertDispatched(NewPrivateNotificationEvent::class, function (NewPrivateNotificationEvent $event) {
65 return $event->notification->name === Notification::BEATMAPSET_DISQUALIFY
66 && $this->inReceivers($this->user, $event);
67 });
68 }
69
70 /**
71 * @dataProvider booleanDataProvider
72 */
73 public function testNotificationSentWithPushNotificationDeliveryOption($pushEnabled)
74 {
75 $this->beatmapset->watches()->create(['user_id' => $this->user->getKey()]);
76 $this->user->notificationOptions()->create([
77 'name' => UserNotificationOption::BEATMAPSET_MODDING,
78 ])->update(['details' => ['push' => $pushEnabled]]);
79
80 $this->disqualify()->assertStatus(200);
81
82 if ($pushEnabled) {
83 Queue::assertPushed(BeatmapsetDisqualify::class);
84
85 $this->runFakeQueue();
86
87 Event::assertDispatched(NewPrivateNotificationEvent::class, function (NewPrivateNotificationEvent $event) {
88 return $event->notification->name === Notification::BEATMAPSET_DISQUALIFY
89 && $this->inReceivers($this->user, $event);
90 });
91 } else {
92 // We want to assert the job was queued but because there should be no receivers, there won't be a notification generated.
93 Queue::assertPushed(BeatmapsetDisqualify::class);
94
95 $this->runFakeQueue();
96
97 Event::assertNotDispatched(NewPrivateNotificationEvent::class, function (NewPrivateNotificationEvent $event) {
98 return $event->notification->name === Notification::BEATMAPSET_DISQUALIFY;
99 });
100 }
101 }
102
103 public function testNotificationSentIfNotificationOptionsEnabled()
104 {
105 $this->createNotificationOption();
106
107 $this->disqualify()->assertStatus(200);
108
109 Queue::assertPushed(BeatmapsetDisqualify::class);
110
111 $this->runFakeQueue();
112
113 Event::assertDispatched(NewPrivateNotificationEvent::class, function (NewPrivateNotificationEvent $event) {
114 return $event->notification->name === Notification::BEATMAPSET_DISQUALIFY
115 && $this->inReceivers($this->user, $event);
116 });
117 }
118
119 public function testNotificationNotSentIfNotificationOptionsNotEnabled()
120 {
121 $this->disqualify()->assertStatus(200);
122
123 Queue::assertPushed(BeatmapsetDisqualify::class);
124
125 $this->runFakeQueue();
126
127 Event::assertNotDispatched(NewPrivateNotificationEvent::class);
128 }
129 #endregion
130
131 public static function booleanDataProvider()
132 {
133 return [
134 [true],
135 [false],
136 ];
137 }
138
139 protected function setUp(): void
140 {
141 parent::setUp();
142
143 Queue::fake();
144 Event::fake();
145
146 $this->beatmapset = Beatmapset::factory()->owner()->qualified()->withDiscussion()->create();
147 $this->sender = User::factory()->withGroup('bng')->create();
148 $this->user = User::factory()->create();
149 }
150
151 private function createNotificationOption()
152 {
153 $this->user->notificationOptions()->create([
154 'name' => Notification::BEATMAPSET_DISQUALIFY,
155 ])->update(['details' => ['modes' => array_keys(Beatmap::MODES)]]);
156 }
157
158 private function disqualify()
159 {
160 return $this
161 ->actingAsVerified($this->sender)
162 ->post(route('beatmapsets.discussions.posts.store'), [
163 'beatmapset_id' => $this->beatmapset->beatmapset_id,
164 'beatmap_discussion' => [
165 'message_type' => 'problem',
166 ],
167 'beatmap_discussion_post' => [
168 'message' => 'Hello',
169 ],
170 ]);
171 }
172}