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