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\Libraries\Notification\BatchIdentities;
9use App\Models\Notification;
10use App\Models\User;
11use App\Models\UserNotification;
12use Tests\TestCase;
13
14class UserNotificationTest extends TestCase
15{
16 public function testBatchDestroyByIds()
17 {
18 $user = User::factory()->create();
19
20 $notificationA = Notification::factory()->create();
21 $notificationB = Notification::factory()->create();
22
23 $userNotificationA = UserNotification::factory()->create([
24 'notification_id' => $notificationA,
25 'user_id' => $user,
26 ]);
27
28 $userNotificationB = UserNotification::factory()->create([
29 'notification_id' => $notificationB,
30 'user_id' => $user,
31 ]);
32
33 $initialUserNotificationCount = UserNotification::count();
34
35 UserNotification::batchDestroy($user->getKey(), BatchIdentities::fromParams([
36 'notifications' => [
37 ['id' => $notificationA->getKey()],
38 ],
39 ]));
40
41 $this->assertSame(UserNotification::count(), $initialUserNotificationCount - 1);
42 $this->assertNull(UserNotification::find($userNotificationA->getKey()));
43 $this->assertTrue(UserNotification::where('id', $userNotificationB->getKey())->exists());
44 }
45
46 public function testBatchDestroyByNotificationIdentyByStack()
47 {
48 $user = User::factory()->create();
49
50 $notificationA = Notification::factory()->create([
51 'name' => Notification::BEATMAPSET_DISCUSSION_LOCK,
52 'notifiable_id' => 1,
53 'notifiable_type' => 'beatmapset',
54 ]);
55 $notificationB = Notification::factory()->create([
56 'name' => $notificationA->name,
57 'notifiable_id' => $notificationA->notifiable_id,
58 'notifiable_type' => $notificationA->notifiable_type,
59 ]);
60 $notificationC = Notification::factory()->create([
61 'name' => $notificationA->name,
62 'notifiable_id' => 2,
63 'notifiable_type' => $notificationA->notifiable_type,
64 ]);
65
66 $userNotificationA = UserNotification::factory()->create([
67 'notification_id' => $notificationA,
68 'user_id' => $user,
69 ]);
70
71 $userNotificationB = UserNotification::factory()->create([
72 'notification_id' => $notificationB,
73 'user_id' => $user,
74 ]);
75
76 $userNotificationC = UserNotification::factory()->create([
77 'notification_id' => $notificationC,
78 'user_id' => $user,
79 ]);
80
81 $initialUserNotificationCount = UserNotification::count();
82
83 UserNotification::batchDestroy($user->getKey(), BatchIdentities::fromParams([
84 'identities' => [
85 [
86 'category' => $notificationA->category,
87 'object_type' => $notificationA->notifiable_type,
88 'object_id' => $notificationA->notifiable_id,
89 ],
90 ],
91 ]));
92
93 $this->assertSame(UserNotification::count(), $initialUserNotificationCount - 2);
94 $this->assertNull(UserNotification::find($userNotificationA->getKey()));
95 $this->assertNull(UserNotification::find($userNotificationB->getKey()));
96 $this->assertTrue(UserNotification::where('id', $userNotificationC->getKey())->exists());
97 }
98
99 public function testBatchDestroyByNotificationIdentityByObjectType()
100 {
101 $user = User::factory()->create();
102
103 $notificationA = Notification::factory()->create([
104 'name' => Notification::BEATMAPSET_DISCUSSION_LOCK,
105 'notifiable_type' => 'beatmapset',
106 ]);
107 $notificationB = Notification::factory()->create([
108 'name' => $notificationA->name,
109 'notifiable_type' => 'beatmapset',
110 ]);
111 $notificationC = Notification::factory()->create([
112 'name' => Notification::COMMENT_NEW,
113 'notifiable_type' => 'news_post',
114 ]);
115
116 $userNotificationA = UserNotification::factory()->create([
117 'notification_id' => $notificationA,
118 'user_id' => $user,
119 ]);
120
121 $userNotificationB = UserNotification::factory()->create([
122 'notification_id' => $notificationB,
123 'user_id' => $user,
124 ]);
125
126 $userNotificationC = UserNotification::factory()->create([
127 'notification_id' => $notificationC,
128 'user_id' => $user,
129 ]);
130
131 $initialUserNotificationCount = UserNotification::count();
132
133 UserNotification::batchDestroy($user->getKey(), BatchIdentities::fromParams([
134 'identities' => [
135 ['object_type' => $notificationA->notifiable_type],
136 ],
137 ]));
138
139 $this->assertSame(UserNotification::count(), $initialUserNotificationCount - 2);
140 $this->assertNull(UserNotification::find($userNotificationA->getKey()));
141 $this->assertNull(UserNotification::find($userNotificationB->getKey()));
142 $this->assertTrue(UserNotification::where('id', $userNotificationC->getKey())->exists());
143 }
144
145 /**
146 * Didn't accidentally break masks sanity test.
147 *
148 * @dataProvider deliveryMaskDataProvider
149 */
150 public function testDeliveryMasks($mask, $type, $result)
151 {
152 $userNotification = new UserNotification(['delivery' => $mask]);
153 $this->assertSame($result, $userNotification->isDelivery($type));
154 }
155
156 /**
157 * Didn't accidentally break scope sanity test
158 */
159 public function testScopeHasMailDelivery()
160 {
161 $values = array_values(UserNotification::DELIVERY_OFFSETS);
162 rsort($values);
163 $max = 2 ** ($values[0] + 1);
164
165 for ($i = 0; $i < $max; $i++) {
166 UserNotification::create([
167 'delivery' => $i,
168 'notification_id' => 1,
169 'user_id' => $i,
170 ]);
171 }
172
173 $userNotifications = UserNotification::hasMailDelivery()->get();
174 $this->assertTrue(
175 $userNotifications->reduce(function ($carry, $userNotification) {
176 return $carry && $userNotification->isMail();
177 }, true)
178 );
179 }
180
181 public static function deliveryMaskDataProvider()
182 {
183 return [
184 [0, 'mail', false],
185 [0, 'push', false],
186
187 [1, 'mail', false],
188 [1, 'push', true],
189
190 [2, 'mail', true],
191 [2, 'push', false],
192
193 [3, 'mail', true],
194 [3, 'push', true],
195 ];
196 }
197}