00b0a19007dde63b973a6414d90c73f8868a8ce5
[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.database.*
29 import net.pterodactylus.sone.freenet.wot.*
30 import net.pterodactylus.sone.main.*
31 import net.pterodactylus.sone.notify.*
32 import net.pterodactylus.sone.test.*
33 import net.pterodactylus.sone.text.*
34 import net.pterodactylus.sone.utils.*
35 import net.pterodactylus.util.notify.*
36 import org.hamcrest.MatcherAssert.*
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                         PostReplyProvider::class.isProvidedByMock(),
63                         NotificationHandlerModule()
64         )
65
66         @Test
67         fun `notification handler is created as singleton`() {
68                 injector.verifySingletonInstance<NotificationHandler>()
69         }
70
71         @Test
72         fun `mark-post-known-during-first-start handler is created as singleton`() {
73                 injector.verifySingletonInstance<MarkPostKnownDuringFirstStartHandler>()
74         }
75
76         @Test
77         fun `mark-post-known-during-first-start handler is created with correct action`() {
78                 notificationManager.firstStart()
79                 val handler = injector.getInstance<MarkPostKnownDuringFirstStartHandler>()
80                 val post = mock<Post>()
81                 handler.newPostFound(NewPostFoundEvent(post))
82                 verify(core).markPostKnown(post)
83         }
84
85         @Test
86         fun `sone-locked-on-startup handler is created as singleton`() {
87                 injector.verifySingletonInstance<SoneLockedOnStartupHandler>()
88         }
89
90         @Test
91         fun `module can create sone-locked-on-startup notification with correct id`() {
92                 val notification = injector.getInstance<ListNotification<Sone>>(named("soneLockedOnStartup"))
93                 assertThat(notification.id, equalTo("sone-locked-on-startup"))
94         }
95
96         @Test
97         fun `sone-locked-on-startup notification is created as singleton`() {
98                 injector.verifySingletonInstance<ListNotification<Sone>>(named("soneLockedOnStartup"))
99         }
100
101         @Test
102         fun `module can create sone-locked-on-startup notification with correct template and key`() {
103                 loaders.templates += "/templates/notify/soneLockedOnStartupNotification.html" to "<% sones>".asTemplate()
104                 val notification = injector.getInstance<ListNotification<Sone>>(named("soneLockedOnStartup"))
105                 val sone1 = IdOnlySone("sone1")
106                 val sone2 = IdOnlySone("sone2")
107                 notification.add(sone1)
108                 notification.add(sone2)
109                 assertThat(notification.render(), equalTo(listOf(sone1, sone2).toString()))
110         }
111
112         @Test
113         fun `sone-locked-on-startup notification is dismissable`() {
114                 assertThat(injector.getInstance<ListNotification<Sone>>(named("soneLockedOnStartup")).isDismissable, equalTo(true))
115         }
116
117         @Test
118         fun `new-sone handler is created as singleton`() {
119                 injector.verifySingletonInstance<NewSoneHandler>()
120         }
121
122         @Test
123         fun `new-sone notification has correct ID`() {
124                 assertThat(injector.getInstance<ListNotification<Sone>>(named("newSone")).id, equalTo("new-sone-notification"))
125         }
126
127         @Test
128         fun `new-sone notification has correct key and template`() {
129                 loaders.templates += "/templates/notify/newSoneNotification.html" to "<% sones>".asTemplate()
130                 val notification = injector.getInstance<ListNotification<Sone>>(named("newSone"))
131                 val sones = listOf(IdOnlySone("sone1"), IdOnlySone("sone2"))
132                 sones.forEach(notification::add)
133                 assertThat(notification.render(), equalTo(sones.toString()))
134         }
135
136         @Test
137         fun `new-sone notification is not dismissable`() {
138                 assertThat(injector.getInstance<ListNotification<Sone>>(named("newSone")).isDismissable, equalTo(false))
139         }
140
141         @Test
142         fun `new-remote-post handler is created as singleton`() {
143                 injector.verifySingletonInstance<NewRemotePostHandler>()
144         }
145
146         @Test
147         fun `new-remote-post notification is created as singleton`() {
148                 injector.verifySingletonInstance<ListNotification<Post>>(named("newRemotePost"))
149         }
150
151         @Test
152         fun `new-remote-post notification has correct ID`() {
153                 assertThat(injector.getInstance<ListNotification<Post>>(named("newRemotePost")).id, equalTo("new-post-notification"))
154         }
155
156         @Test
157         fun `new-remote-post notification is not dismissable`() {
158                 assertThat(injector.getInstance<ListNotification<Post>>(named("newRemotePost")).isDismissable, equalTo(false))
159         }
160
161         @Test
162         fun `new-remote-post notification has correct key and template`() {
163                 loaders.templates += "/templates/notify/newPostNotification.html" to "<% posts>".asTemplate()
164                 val notification = injector.getInstance<ListNotification<Post>>(named("newRemotePost"))
165                 val posts = listOf(EmptyPost("post1"), EmptyPost("post2"))
166                 posts.forEach(notification::add)
167                 assertThat(notification.render(), equalTo(posts.toString()))
168         }
169
170         @Test
171         fun `sone-locked notification is created as singleton`() {
172                 injector.verifySingletonInstance<ListNotification<Sone>>(named("soneLocked"))
173         }
174
175         @Test
176         fun `sone-locked notification is dismissable`() {
177                 assertThat(injector.getInstance<ListNotification<Sone>>(named("soneLocked")).isDismissable, equalTo(true))
178         }
179
180         @Test
181         fun `sone-locked notification has correct ID`() {
182                 assertThat(injector.getInstance<ListNotification<Sone>>(named("soneLocked")).id, equalTo("sones-locked-notification"))
183         }
184
185         @Test
186         fun `sone-locked notification has correct key and template`() {
187                 loaders.templates += "/templates/notify/lockedSonesNotification.html" to "<% sones>".asTemplate()
188                 val notification = injector.getInstance<ListNotification<Sone>>(named("soneLocked"))
189                 val sones = listOf(IdOnlySone("sone1"), IdOnlySone("sone2"))
190                 sones.forEach(notification::add)
191                 assertThat(notification.render(), equalTo(sones.toString()))
192         }
193
194         @Test
195         fun `sone-locked handler is created as singleton`() {
196                 injector.verifySingletonInstance<SoneLockedHandler>()
197         }
198
199         @Test
200         fun `local-post notification is not dismissable`() {
201                 assertThat(injector.getInstance<ListNotification<Post>>(named("localPost")).isDismissable, equalTo(false))
202         }
203
204         @Test
205         fun `local-post notification has correct ID`() {
206                 assertThat(injector.getInstance<ListNotification<Post>>(named("localPost")).id, equalTo("local-post-notification"))
207         }
208
209         @Test
210         fun `local-post notification has correct key and template`() {
211                 loaders.templates += "/templates/notify/newPostNotification.html" to "<% posts>".asTemplate()
212                 val notification = injector.getInstance<ListNotification<Post>>(named("localPost"))
213                 val posts = listOf(EmptyPost("post1"), EmptyPost("post2"))
214                 posts.forEach(notification::add)
215                 assertThat(notification.render(), equalTo(posts.toString()))
216         }
217
218         @Test
219         fun `local-post notification is created as singleton`() {
220                 injector.verifySingletonInstance<ListNotification<Post>>(named("localPost"))
221         }
222
223         @Test
224         fun `local-post handler is created as singleton`() {
225                 injector.verifySingletonInstance<LocalPostHandler>()
226         }
227
228         @Test
229         fun `new-version notification is created as singleton`() {
230                 injector.verifySingletonInstance<TemplateNotification>(named("newVersion"))
231         }
232
233         @Test
234         fun `new-version notification has correct ID`() {
235                 assertThat(injector.getInstance<TemplateNotification>(named("newVersion")).id, equalTo("new-version-notification"))
236         }
237
238         @Test
239         fun `new-version notification is dismissable`() {
240                 assertThat(injector.getInstance<TemplateNotification>(named("newVersion")).isDismissable, equalTo(true))
241         }
242
243         @Test
244         fun `new-version notification loads correct template`() {
245                 loaders.templates += "/templates/notify/newVersionNotification.html" to "1".asTemplate()
246                 val notification = injector.getInstance<TemplateNotification>(named("newVersion"))
247                 assertThat(notification.render(), equalTo("1"))
248         }
249
250         @Test
251         fun `new-version handler is created as singleton`() {
252                 injector.verifySingletonInstance<NewVersionHandler>()
253         }
254
255         @Test
256         fun `inserting-image notification is created as singleton`() {
257                 injector.verifySingletonInstance<ListNotification<Image>>(named("imageInserting"))
258         }
259
260         @Test
261         fun `inserting-image notification has correct ID`() {
262                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserting")).id, equalTo("inserting-images-notification"))
263         }
264
265         @Test
266         fun `inserting-image notification is dismissable`() {
267                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserting")).isDismissable, equalTo(true))
268         }
269
270         @Test
271         fun `inserting-image notification loads correct template`() {
272                 loaders.templates += "/templates/notify/inserting-images-notification.html" to "<% images>".asTemplate()
273                 val notification = injector.getInstance<ListNotification<Image>>(named("imageInserting"))
274                 val images = listOf(ImageImpl(), ImageImpl()).onEach(notification::add)
275                 assertThat(notification.render(), equalTo(images.toString()))
276         }
277
278         @Test
279         fun `inserting-image-failed notification is created as singleton`() {
280                 injector.verifySingletonInstance<ListNotification<Image>>(named("imageFailed"))
281         }
282
283         @Test
284         fun `inserting-image-failed notification has correct ID`() {
285                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageFailed")).id, equalTo("image-insert-failed-notification"))
286         }
287
288         @Test
289         fun `inserting-image-failed notification is dismissable`() {
290                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageFailed")).isDismissable, equalTo(true))
291         }
292
293         @Test
294         fun `inserting-image-failed notification loads correct template`() {
295                 loaders.templates += "/templates/notify/image-insert-failed-notification.html" to "<% images>".asTemplate()
296                 val notification = injector.getInstance<ListNotification<Image>>(named("imageFailed"))
297                 val images = listOf(ImageImpl(), ImageImpl()).onEach(notification::add)
298                 assertThat(notification.render(), equalTo(images.toString()))
299         }
300
301         @Test
302         fun `inserted-image notification is created as singleton`() {
303                 injector.verifySingletonInstance<ListNotification<Image>>(named("imageInserted"))
304         }
305
306         @Test
307         fun `inserted-image notification has correct ID`() {
308                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserted")).id, equalTo("inserted-images-notification"))
309         }
310
311         @Test
312         fun `inserted-image notification is dismissable`() {
313                 assertThat(injector.getInstance<ListNotification<Image>>(named("imageInserted")).isDismissable, equalTo(true))
314         }
315
316         @Test
317         fun `inserted-image notification loads correct template`() {
318                 loaders.templates += "/templates/notify/inserted-images-notification.html" to "<% images>".asTemplate()
319                 val notification = injector.getInstance<ListNotification<Image>>(named("imageInserted"))
320                 val images = listOf(ImageImpl(), ImageImpl()).onEach(notification::add)
321                 assertThat(notification.render(), equalTo(images.toString()))
322         }
323
324         @Test
325         fun `image insert handler is created as singleton`() {
326                 injector.verifySingletonInstance<ImageInsertHandler>()
327         }
328
329         @Test
330         fun `first-start notification is created as singleton`() {
331                 injector.verifySingletonInstance<TemplateNotification>(named("firstStart"))
332         }
333
334         @Test
335         fun `first-start notification has correct ID`() {
336                 assertThat(injector.getInstance<TemplateNotification>(named("firstStart")).id, equalTo("first-start-notification"))
337         }
338
339         @Test
340         fun `first-start notification is dismissable`() {
341                 assertThat(injector.getInstance<TemplateNotification>(named("firstStart")).isDismissable, equalTo(true))
342         }
343
344         @Test
345         fun `first-start notification loads correct template`() {
346                 loaders.templates += "/templates/notify/firstStartNotification.html" to "1".asTemplate()
347                 val notification = injector.getInstance<TemplateNotification>(named("firstStart"))
348                 assertThat(notification.render(), equalTo("1"))
349         }
350
351         @Test
352         fun `first-start handler is created as singleton`() {
353                 injector.verifySingletonInstance<FirstStartHandler>()
354         }
355
356         @Test
357         fun `config-not-read notification is created as singleton`() {
358                 injector.verifySingletonInstance<TemplateNotification>(named("configNotRead"))
359         }
360
361         @Test
362         fun `config-not-read notification has correct ID `() {
363                 assertThat(injector.getInstance<TemplateNotification>(named("configNotRead")).id, equalTo("config-not-read-notification"))
364         }
365
366         @Test
367         fun `config-not-read notification is dismissable`() {
368                 assertThat(injector.getInstance<TemplateNotification>(named("configNotRead")).isDismissable, equalTo(true))
369         }
370
371         @Test
372         fun `config-not-read notification loads correct template`() {
373                 loaders.templates += "/templates/notify/configNotReadNotification.html" to "1".asTemplate()
374                 val notification = injector.getInstance<TemplateNotification>(named("configNotRead"))
375                 assertThat(notification.render(), equalTo("1"))
376         }
377
378         @Test
379         fun `config-not-read handler is created as singleton`() {
380                 injector.verifySingletonInstance<ConfigNotReadHandler>()
381         }
382
383         @Test
384         fun `startup notification can be created`() {
385                 injector.verifySingletonInstance<TemplateNotification>(named("startup"))
386         }
387
388         @Test
389         fun `startup notification has correct ID`() {
390                 assertThat(injector.getInstance<TemplateNotification>(named("startup")).id, equalTo("startup-notification"))
391         }
392
393         @Test
394         fun `startup notification is dismissable`() {
395                 assertThat(injector.getInstance<TemplateNotification>(named("startup")).isDismissable, equalTo(true))
396         }
397
398         @Test
399         fun `startup notification loads correct template`() {
400                 loaders.templates += "/templates/notify/startupNotification.html" to "1".asTemplate()
401                 val notification = injector.getInstance<TemplateNotification>(named("startup"))
402                 assertThat(notification.render(), equalTo("1"))
403         }
404
405         @Test
406         fun `startup handler is created as singleton`() {
407                 injector.verifySingletonInstance<StartupHandler>()
408         }
409
410         @Test
411         fun `web-of-trust notification is created as singleton`() {
412                 injector.verifySingletonInstance<TemplateNotification>(named("webOfTrust"))
413         }
414
415         @Test
416         fun `web-of-trust notification has correct ID`() {
417                 assertThat(injector.getInstance<TemplateNotification>(named("webOfTrust")).id, equalTo("wot-missing-notification"))
418         }
419
420         @Test
421         fun `web-of-trust notification is dismissable`() {
422                 assertThat(injector.getInstance<TemplateNotification>(named("webOfTrust")).isDismissable, equalTo(true))
423         }
424
425         @Test
426         fun `web-of-trust notification loads correct template`() {
427                 loaders.templates += "/templates/notify/wotMissingNotification.html" to "1".asTemplate()
428                 val notification = injector.getInstance<TemplateNotification>(named("webOfTrust"))
429                 assertThat(notification.render(), equalTo("1"))
430         }
431
432         @Test
433         fun `web-of-trust handler is created as singleton`() {
434                 injector.verifySingletonInstance<TemplateNotification>(named("webOfTrust"))
435         }
436
437         @Test
438         fun `web-of-trust reacher is created as singleton`() {
439                 injector.verifySingletonInstance<Runnable>(named("webOfTrustReacher"))
440         }
441
442         @Test
443         fun `web-of-trust reacher access the wot connector`() {
444                 injector.getInstance<Runnable>(named("webOfTrustReacher")).run()
445                 verify(webOfTrustConnector).ping()
446         }
447
448         @Test
449         fun `web-of-trust reschedule is created as singleton`() {
450                 injector.verifySingletonInstance<Consumer<Runnable>>(named("webOfTrustReschedule"))
451         }
452
453         @Test
454         fun `web-of-trust reschedule schedules at the correct delay`() {
455                 val webOfTrustPinger = injector.getInstance<WebOfTrustPinger>()
456                 injector.getInstance<Consumer<Runnable>>(named("webOfTrustReschedule"))(webOfTrustPinger)
457                 verify(ticker).schedule(ArgumentMatchers.eq(webOfTrustPinger), ArgumentMatchers.eq(15L), ArgumentMatchers.eq(SECONDS))
458         }
459
460         @Test
461         fun `sone mention detector is created as singleton`() {
462                 assertThat(injector.getInstance<SoneMentionDetector>(), notNullValue())
463         }
464
465         @Test
466         fun `sone-mentioned notification is created as singleton`() {
467                 injector.verifySingletonInstance<ListNotification<Post>>(named("soneMentioned"))
468         }
469
470         @Test
471         fun `sone-mentioned notification has correct ID`() {
472                 assertThat(injector.getInstance<ListNotification<Post>>(named("soneMentioned")).id, equalTo("mention-notification"))
473         }
474
475         @Test
476         fun `sone-mentioned notification is not dismissable`() {
477                 assertThat(injector.getInstance<ListNotification<Post>>(named("soneMentioned")).isDismissable, equalTo(false))
478         }
479
480         @Test
481         fun `sone-mentioned notification loads correct template`() {
482                 loaders.templates += "/templates/notify/mentionNotification.html" to "<% posts>".asTemplate()
483                 val notification = injector.getInstance<ListNotification<Post>>(named("soneMentioned"))
484                 val posts = listOf(EmptyPost("1"), EmptyPost("2")).onEach(notification::add)
485                 assertThat(notification.render(), equalTo(posts.toString()))
486         }
487
488         @Test
489         fun `sone-mentioned handler is created as singleton`() {
490                 injector.verifySingletonInstance<SoneMentionedHandler>()
491         }
492
493 }