🎨 Add helper for simulating first start
[Sone.git] / src / test / kotlin / net / pterodactylus / sone / web / notification / NotificationHandlerModuleTest.kt
1 /**
2  * Sone - NotificationHandlerModuleTest.kt - Copyright Â© 2019 David â€˜Bombe’ Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 package net.pterodactylus.sone.web.notification
19
20 import com.google.inject.*
21 import com.google.inject.Guice.*
22 import com.google.inject.name.Names.*
23 import net.pterodactylus.sone.core.*
24 import net.pterodactylus.sone.core.event.*
25 import net.pterodactylus.sone.data.*
26 import net.pterodactylus.sone.data.Post.*
27 import net.pterodactylus.sone.data.impl.*
28 import net.pterodactylus.sone.freenet.wot.*
29 import net.pterodactylus.sone.main.*
30 import net.pterodactylus.sone.notify.*
31 import net.pterodactylus.sone.test.*
32 import net.pterodactylus.sone.text.*
33 import net.pterodactylus.sone.utils.*
34 import net.pterodactylus.util.notify.*
35 import org.hamcrest.MatcherAssert.*
36 import org.hamcrest.Matchers
37 import org.hamcrest.Matchers.*
38 import org.mockito.*
39 import org.mockito.Mockito.*
40 import java.util.concurrent.*
41 import java.util.concurrent.TimeUnit.*
42 import java.util.function.*
43 import kotlin.test.*
44
45 /**
46  * Unit test for [NotificationHandlerModule].
47  */
48 class NotificationHandlerModuleTest {
49
50         private val core = mock<Core>()
51         private val webOfTrustConnector = mock<WebOfTrustConnector>()
52         private val ticker = mock<ScheduledExecutorService>()
53         private val notificationManager = NotificationManager()
54         private val loaders = TestLoaders()
55         private val injector: Injector = createInjector(
56                         Core::class.isProvidedBy(core),
57                         NotificationManager::class.isProvidedBy(notificationManager),
58                         Loaders::class.isProvidedBy(loaders),
59                         WebOfTrustConnector::class.isProvidedBy(webOfTrustConnector),
60                         ScheduledExecutorService::class.withNameIsProvidedBy(ticker, "notification"),
61                         SoneTextParser::class.isProvidedByMock(),
62                         NotificationHandlerModule()
63         )
64
65         @Test
66         fun `notification handler is created as singleton`() {
67                 injector.verifySingletonInstance<NotificationHandler>()
68         }
69
70         @Test
71         fun `mark-post-known-during-first-start handler is created as singleton`() {
72                 injector.verifySingletonInstance<MarkPostKnownDuringFirstStartHandler>()
73         }
74
75         @Test
76         fun `mark-post-known-during-first-start handler is created with correct action`() {
77                 notificationManager.firstStart()
78                 val handler = injector.getInstance<MarkPostKnownDuringFirstStartHandler>()
79                 val post = mock<Post>()
80                 handler.newPostFound(NewPostFoundEvent(post))
81                 verify(core).markPostKnown(post)
82         }
83
84         @Test
85         fun `sone-locked-on-startup handler is created as singleton`() {
86                 injector.verifySingletonInstance<SoneLockedOnStartupHandler>()
87         }
88
89         @Test
90         fun `module can create sone-locked-on-startup notification with correct id`() {
91                 val notification = injector.getInstance<ListNotification<Sone>>(named("soneLockedOnStartup"))
92                 assertThat(notification.id, equalTo("sone-locked-on-startup"))
93         }
94
95         @Test
96         fun `sone-locked-on-startup notification is created as singleton`() {
97                 injector.verifySingletonInstance<ListNotification<Sone>>(named("soneLockedOnStartup"))
98         }
99
100         @Test
101         fun `module can create sone-locked-on-startup notification with correct template and key`() {
102                 loaders.templates += "/templates/notify/soneLockedOnStartupNotification.html" to "<% sones>".asTemplate()
103                 val notification = injector.getInstance<ListNotification<Sone>>(named("soneLockedOnStartup"))
104                 val sone1 = IdOnlySone("sone1")
105                 val sone2 = IdOnlySone("sone2")
106                 notification.add(sone1)
107                 notification.add(sone2)
108                 assertThat(notification.render(), equalTo(listOf(sone1, sone2).toString()))
109         }
110
111         @Test
112         fun `sone-locked-on-startup notification is dismissable`() {
113                 assertThat(injector.getInstance<ListNotification<Sone>>(named("soneLockedOnStartup")).isDismissable, equalTo(true))
114         }
115
116         @Test
117         fun `new-sone handler is created as singleton`() {
118                 injector.verifySingletonInstance<NewSoneHandler>()
119         }
120
121         @Test
122         fun `new-sone notification has correct ID`() {
123                 assertThat(injector.getInstance<ListNotification<Sone>>(named("newSone")).id, equalTo("new-sone-notification"))
124         }
125
126         @Test
127         fun `new-sone notification has correct key and template`() {
128                 loaders.templates += "/templates/notify/newSoneNotification.html" to "<% sones>".asTemplate()
129                 val notification = injector.getInstance<ListNotification<Sone>>(named("newSone"))
130                 val sones = listOf(IdOnlySone("sone1"), IdOnlySone("sone2"))
131                 sones.forEach(notification::add)
132                 assertThat(notification.render(), equalTo(sones.toString()))
133         }
134
135         @Test
136         fun `new-sone notification is not dismissable`() {
137                 assertThat(injector.getInstance<ListNotification<Sone>>(named("newSone")).isDismissable, equalTo(false))
138         }
139
140         @Test
141         fun `new-remote-post handler is created as singleton`() {
142                 injector.verifySingletonInstance<NewRemotePostHandler>()
143         }
144
145         @Test
146         fun `new-remote-post notification is created as singleton`() {
147                 injector.verifySingletonInstance<ListNotification<Post>>(named("newRemotePost"))
148         }
149
150         @Test
151         fun `new-remote-post notification has correct ID`() {
152                 assertThat(injector.getInstance<ListNotification<Post>>(named("newRemotePost")).id, equalTo("new-post-notification"))
153         }
154
155         @Test
156         fun `new-remote-post notification is not dismissable`() {
157                 assertThat(injector.getInstance<ListNotification<Post>>(named("newRemotePost")).isDismissable, equalTo(false))
158         }
159
160         @Test
161         fun `new-remote-post notification has correct key and template`() {
162                 loaders.templates += "/templates/notify/newPostNotification.html" to "<% posts>".asTemplate()
163                 val notification = injector.getInstance<ListNotification<Post>>(named("newRemotePost"))
164                 val posts = listOf(EmptyPost("post1"), EmptyPost("post2"))
165                 posts.forEach(notification::add)
166                 assertThat(notification.render(), equalTo(posts.toString()))
167         }
168
169         @Test
170         fun `sone-locked notification is created as singleton`() {
171                 injector.verifySingletonInstance<ListNotification<Sone>>(named("soneLocked"))
172         }
173
174         @Test
175         fun `sone-locked notification is dismissable`() {
176                 assertThat(injector.getInstance<ListNotification<Sone>>(named("soneLocked")).isDismissable, equalTo(true))
177         }
178
179         @Test
180         fun `sone-locked notification has correct ID`() {
181                 assertThat(injector.getInstance<ListNotification<Sone>>(named("soneLocked")).id, equalTo("sones-locked-notification"))
182         }
183
184         @Test
185         fun `sone-locked notification has correct key and template`() {
186                 loaders.templates += "/templates/notify/lockedSonesNotification.html" to "<% sones>".asTemplate()
187                 val notification = injector.getInstance<ListNotification<Sone>>(named("soneLocked"))
188                 val sones = listOf(IdOnlySone("sone1"), IdOnlySone("sone2"))
189                 sones.forEach(notification::add)
190                 assertThat(notification.render(), equalTo(sones.toString()))
191         }
192
193         @Test
194         fun `sone-locked handler is created as singleton`() {
195                 injector.verifySingletonInstance<SoneLockedHandler>()
196         }
197
198         @Test
199         fun `local-post notification is not dismissable`() {
200                 assertThat(injector.getInstance<ListNotification<Post>>(named("localPost")).isDismissable, equalTo(false))
201         }
202
203         @Test
204         fun `local-post notification has correct ID`() {
205                 assertThat(injector.getInstance<ListNotification<Post>>(named("localPost")).id, equalTo("local-post-notification"))
206         }
207
208         @Test
209         fun `local-post notification has correct key and template`() {
210                 loaders.templates += "/templates/notify/newPostNotification.html" to "<% posts>".asTemplate()
211                 val notification = injector.getInstance<ListNotification<Post>>(named("localPost"))
212                 val posts = listOf(EmptyPost("post1"), EmptyPost("post2"))
213                 posts.forEach(notification::add)
214                 assertThat(notification.render(), equalTo(posts.toString()))
215         }
216
217         @Test
218         fun `local-post notification is created as singleton`() {
219                 injector.verifySingletonInstance<ListNotification<Post>>(named("localPost"))
220         }
221
222         @Test
223         fun `local-post handler is created as singleton`() {
224                 injector.verifySingletonInstance<LocalPostHandler>()
225         }
226
227         @Test
228         fun `new-version notification is created as singleton`() {
229                 injector.verifySingletonInstance<TemplateNotification>(named("newVersion"))
230         }
231
232         @Test
233         fun `new-version notification has correct ID`() {
234                 assertThat(injector.getInstance<TemplateNotification>(named("newVersion")).id, equalTo("new-version-notification"))
235         }
236
237         @Test
238         fun `new-version notification is dismissable`() {
239                 assertThat(injector.getInstance<TemplateNotification>(named("newVersion")).isDismissable, equalTo(true))
240         }
241
242         @Test
243         fun `new-version notification loads correct template`() {
244                 loaders.templates += "/templates/notify/newVersionNotification.html" to "1".asTemplate()
245                 val notification = injector.getInstance<TemplateNotification>(named("newVersion"))
246                 assertThat(notification.render(), equalTo("1"))
247         }
248
249         @Test
250         fun `new-version handler is created as singleton`() {
251                 injector.verifySingletonInstance<NewVersionHandler>()
252         }
253
254         @Test
255         fun `inserting-image notification is created as singleton`() {
256                 injector.verifySingletonInstance<ListNotification<Image>>(named("imageInserting"))
257         }
258
259         @Test
260         fun `inserting-image notification has correct ID`() {
261                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserting")).id, equalTo("inserting-images-notification"))
262         }
263
264         @Test
265         fun `inserting-image notification is dismissable`() {
266                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserting")).isDismissable, equalTo(true))
267         }
268
269         @Test
270         fun `inserting-image notification loads correct template`() {
271                 loaders.templates += "/templates/notify/inserting-images-notification.html" to "<% images>".asTemplate()
272                 val notification = injector.getInstance<ListNotification<Image>>(named("imageInserting"))
273                 val images = listOf(ImageImpl(), ImageImpl()).onEach(notification::add)
274                 assertThat(notification.render(), equalTo(images.toString()))
275         }
276
277         @Test
278         fun `inserting-image-failed notification is created as singleton`() {
279                 injector.verifySingletonInstance<ListNotification<Image>>(named("imageFailed"))
280         }
281
282         @Test
283         fun `inserting-image-failed notification has correct ID`() {
284                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageFailed")).id, equalTo("image-insert-failed-notification"))
285         }
286
287         @Test
288         fun `inserting-image-failed notification is dismissable`() {
289                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageFailed")).isDismissable, equalTo(true))
290         }
291
292         @Test
293         fun `inserting-image-failed notification loads correct template`() {
294                 loaders.templates += "/templates/notify/image-insert-failed-notification.html" to "<% images>".asTemplate()
295                 val notification = injector.getInstance<ListNotification<Image>>(named("imageFailed"))
296                 val images = listOf(ImageImpl(), ImageImpl()).onEach(notification::add)
297                 assertThat(notification.render(), equalTo(images.toString()))
298         }
299
300         @Test
301         fun `inserted-image notification is created as singleton`() {
302                 injector.verifySingletonInstance<ListNotification<Image>>(named("imageInserted"))
303         }
304
305         @Test
306         fun `inserted-image notification has correct ID`() {
307                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserted")).id, equalTo("inserted-images-notification"))
308         }
309
310         @Test
311         fun `inserted-image notification is dismissable`() {
312                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserted")).isDismissable, equalTo(true))
313         }
314
315         @Test
316         fun `inserted-image notification loads correct template`() {
317                 loaders.templates += "/templates/notify/inserted-images-notification.html" to "<% images>".asTemplate()
318                 val notification = injector.getInstance<ListNotification<Image>>(named("imageInserted"))
319                 val images = listOf(ImageImpl(), ImageImpl()).onEach(notification::add)
320                 assertThat(notification.render(), equalTo(images.toString()))
321         }
322
323         @Test
324         fun `image insert handler is created as singleton`() {
325                 injector.verifySingletonInstance<ImageInsertHandler>()
326         }
327
328         @Test
329         fun `first-start notification is created as singleton`() {
330                 injector.verifySingletonInstance<TemplateNotification>(named("firstStart"))
331         }
332
333         @Test
334         fun `first-start notification has correct ID`() {
335                 assertThat(injector.getInstance<TemplateNotification>(named("firstStart")).id, equalTo("first-start-notification"))
336         }
337
338         @Test
339         fun `first-start notification is dismissable`() {
340                 assertThat(injector.getInstance<TemplateNotification>(named("firstStart")).isDismissable, equalTo(true))
341         }
342
343         @Test
344         fun `first-start notification loads correct template`() {
345                 loaders.templates += "/templates/notify/firstStartNotification.html" to "1".asTemplate()
346                 val notification = injector.getInstance<TemplateNotification>(named("firstStart"))
347                 assertThat(notification.render(), equalTo("1"))
348         }
349
350         @Test
351         fun `first-start handler is created as singleton`() {
352                 injector.verifySingletonInstance<FirstStartHandler>()
353         }
354
355         @Test
356         fun `config-not-read notification is created as singleton`() {
357                 injector.verifySingletonInstance<TemplateNotification>(named("configNotRead"))
358         }
359
360         @Test
361         fun `config-not-read notification has correct ID `() {
362                 assertThat(injector.getInstance<TemplateNotification>(named("configNotRead")).id, equalTo("config-not-read-notification"))
363         }
364
365         @Test
366         fun `config-not-read notification is dismissable`() {
367                 assertThat(injector.getInstance<TemplateNotification>(named("configNotRead")).isDismissable, equalTo(true))
368         }
369
370         @Test
371         fun `config-not-read notification loads correct template`() {
372                 loaders.templates += "/templates/notify/configNotReadNotification.html" to "1".asTemplate()
373                 val notification = injector.getInstance<TemplateNotification>(named("configNotRead"))
374                 assertThat(notification.render(), equalTo("1"))
375         }
376
377         @Test
378         fun `config-not-read handler is created as singleton`() {
379                 injector.verifySingletonInstance<ConfigNotReadHandler>()
380         }
381
382         @Test
383         fun `startup notification can be created`() {
384                 injector.verifySingletonInstance<TemplateNotification>(named("startup"))
385         }
386
387         @Test
388         fun `startup notification has correct ID`() {
389                 assertThat(injector.getInstance<TemplateNotification>(named("startup")).id, equalTo("startup-notification"))
390         }
391
392         @Test
393         fun `startup notification is dismissable`() {
394                 assertThat(injector.getInstance<TemplateNotification>(named("startup")).isDismissable, equalTo(true))
395         }
396
397         @Test
398         fun `startup notification loads correct template`() {
399                 loaders.templates += "/templates/notify/startupNotification.html" to "1".asTemplate()
400                 val notification = injector.getInstance<TemplateNotification>(named("startup"))
401                 assertThat(notification.render(), equalTo("1"))
402         }
403
404         @Test
405         fun `startup handler is created as singleton`() {
406                 injector.verifySingletonInstance<StartupHandler>()
407         }
408
409         @Test
410         fun `web-of-trust notification is created as singleton`() {
411                 injector.verifySingletonInstance<TemplateNotification>(named("webOfTrust"))
412         }
413
414         @Test
415         fun `web-of-trust notification has correct ID`() {
416                 assertThat(injector.getInstance<TemplateNotification>(named("webOfTrust")).id, equalTo("wot-missing-notification"))
417         }
418
419         @Test
420         fun `web-of-trust notification is dismissable`() {
421                 assertThat(injector.getInstance<TemplateNotification>(named("webOfTrust")).isDismissable, equalTo(true))
422         }
423
424         @Test
425         fun `web-of-trust notification loads correct template`() {
426                 loaders.templates += "/templates/notify/wotMissingNotification.html" to "1".asTemplate()
427                 val notification = injector.getInstance<TemplateNotification>(named("webOfTrust"))
428                 assertThat(notification.render(), equalTo("1"))
429         }
430
431         @Test
432         fun `web-of-trust handler is created as singleton`() {
433                 injector.verifySingletonInstance<TemplateNotification>(named("webOfTrust"))
434         }
435
436         @Test
437         fun `web-of-trust reacher is created as singleton`() {
438                 injector.verifySingletonInstance<Runnable>(named("webOfTrustReacher"))
439         }
440
441         @Test
442         fun `web-of-trust reacher access the wot connector`() {
443                 injector.getInstance<Runnable>(named("webOfTrustReacher")).run()
444                 verify(webOfTrustConnector).ping()
445         }
446
447         @Test
448         fun `web-of-trust reschedule is created as singleton`() {
449                 injector.verifySingletonInstance<Consumer<Runnable>>(named("webOfTrustReschedule"))
450         }
451
452         @Test
453         fun `web-of-trust reschedule schedules at the correct delay`() {
454                 val webOfTrustPinger = injector.getInstance<WebOfTrustPinger>()
455                 injector.getInstance<Consumer<Runnable>>(named("webOfTrustReschedule"))(webOfTrustPinger)
456                 verify(ticker).schedule(ArgumentMatchers.eq(webOfTrustPinger), ArgumentMatchers.eq(15L), ArgumentMatchers.eq(SECONDS))
457         }
458
459         @Test
460         fun `sone mention detector is created as singleton`() {
461                 assertThat(injector.getInstance<SoneMentionDetector>(), notNullValue())
462         }
463
464 }