private final MetricRegistry metricRegistry;
private final Translation translation;
- /** The “new Sone” notification. */
- private final ListNotification<Sone> newSoneNotification;
-
/** The “new post” notification. */
private final ListNotification<Post> newPostNotification;
templateContextFactory.addTemplateObject("formPassword", formPassword);
/* create notifications. */
- Template newSoneNotificationTemplate = loaders.loadTemplate("/templates/notify/newSoneNotification.html");
- newSoneNotification = new ListNotification<>("new-sone-notification", "sones", newSoneNotificationTemplate, false);
-
Template newPostNotificationTemplate = loaders.loadTemplate("/templates/notify/newPostNotification.html");
newPostNotification = new ListNotification<>("new-post-notification", "posts", newPostNotificationTemplate, false);
//
/**
- * Notifies the web interface that a new {@link Sone} was found.
- *
- * @param newSoneFoundEvent
- * The event
- */
- @Subscribe
- public void newSoneFound(NewSoneFoundEvent newSoneFoundEvent) {
- newSoneNotification.add(newSoneFoundEvent.getSone());
- if (!hasFirstStartNotification()) {
- notificationManager.addNotification(newSoneNotification);
- }
- }
-
- /**
* Notifies the web interface that a new {@link Post} was found.
*
* @param newPostFoundEvent
}
}
- /**
- * Notifies the web interface that a {@link Sone} was marked as known.
- *
- * @param markSoneKnownEvent
- * The event
- */
- @Subscribe
- public void markSoneKnown(MarkSoneKnownEvent markSoneKnownEvent) {
- newSoneNotification.remove(markSoneKnownEvent.getSone());
- }
-
@Subscribe
public void markPostKnown(MarkPostKnownEvent markPostKnownEvent) {
removePost(markPostKnownEvent.getPost());
}
@Subscribe
- public void soneRemoved(SoneRemovedEvent soneRemovedEvent) {
- newSoneNotification.remove(soneRemovedEvent.getSone());
- }
-
- @Subscribe
public void postRemoved(PostRemovedEvent postRemovedEvent) {
removePost(postRemovedEvent.getPost());
}
*/
class NewSoneHandler(private val notificationManager: NotificationManager, template: Template) {
- private val notification = ListNotification<Sone>("new-sone-notification", "", template)
+ private val notification = ListNotification<Sone>("new-sone-notification", "sones", template, dismissable = false)
@Subscribe
fun newSoneFound(newSoneFoundEvent: NewSoneFoundEvent) {
}
}
+ @Subscribe
+ fun markedSoneKnown(markSoneKnownEvent: MarkSoneKnownEvent) {
+ notification.remove(markSoneKnownEvent.sone)
+ }
+
+ @Subscribe
+ fun soneRemoved(soneRemovedEvent: SoneRemovedEvent) {
+ notification.remove(soneRemovedEvent.sone)
+ }
+
}
private fun NotificationManager.hasNotification(id: String) =
class NotificationHandler @Inject constructor(private val eventBus: EventBus, private val loaders: Loaders, private val notificationManager: NotificationManager) {
fun start() {
- SoneLockedOnStartupHandler(notificationManager, loaders.loadTemplate("/templates/notify/soneLockedOnStartupNotification.html"))
- .also(eventBus::register)
+ register { SoneLockedOnStartupHandler(it, loaders.loadTemplate("/templates/notify/soneLockedOnStartupNotification.html")) }
+ register { NewSoneHandler(it, loaders.loadTemplate("/templates/notify/newSoneNotification.html")) }
}
+ private fun register(handler: (NotificationManager) -> Any) =
+ handler(notificationManager).also(eventBus::register)
+
}
import net.pterodactylus.sone.utils.*
import net.pterodactylus.util.web.*
import org.hamcrest.*
+import org.hamcrest.Matchers
import org.hamcrest.Matchers.*
+/**
+ * Returns a [hamcrest matcher][Matcher] constructed from the given predicate.
+ */
+fun <T> matches(description: String? = null, predicate: (T) -> Boolean) = object : TypeSafeDiagnosingMatcher<T>() {
+
+ override fun matchesSafely(item: T, mismatchDescription: Description) =
+ predicate(item).onFalse {
+ mismatchDescription.appendValue(item).appendText(" did not match predicate")
+ }
+
+ override fun describeTo(description: Description) {
+ description.appendText("matches predicate ").appendValue(predicate)
+ }
+
+}.let { matcher ->
+ description?.let { describedAs(description, matcher) } ?: matcher
+}
+
fun hasHeader(name: String, value: String) = object : TypeSafeDiagnosingMatcher<Header>() {
override fun matchesSafely(item: Header, mismatchDescription: Description) =
compare(item.name, { it.equals(name, ignoreCase = true) }) { mismatchDescription.appendText("name is ").appendValue(it) }
import net.pterodactylus.sone.core.event.*
import net.pterodactylus.sone.data.impl.*
import net.pterodactylus.sone.notify.*
+import net.pterodactylus.sone.test.*
+import net.pterodactylus.sone.utils.*
import net.pterodactylus.util.notify.*
-import net.pterodactylus.util.template.*
import org.hamcrest.MatcherAssert.*
import org.hamcrest.Matchers.*
import java.io.*
@Suppress("UnstableApiUsage")
private val eventBus = EventBus()
private val notificationManager = NotificationManager()
- private val handler = NewSoneHandler(notificationManager, Template())
+ private val handler = NewSoneHandler(notificationManager, "<% sones>".asTemplate())
init {
eventBus.register(handler)
}
@Test
+ fun `handler sets correct key for sones`() {
+ eventBus.post(NewSoneFoundEvent(sone))
+ val notification = notificationManager.notifications.single() as ListNotification<*>
+ assertThat(notification.render(), equalTo(listOf(sone).toString()))
+ }
+
+ @Test
+ fun `handler creates non-dismissable notification`() {
+ eventBus.post(NewSoneFoundEvent(sone))
+ val notification = notificationManager.notifications.single() as ListNotification<*>
+ assertThat(notification, matches("is not dismissable") { !it.isDismissable })
+ }
+
+ @Test
fun `handler does not add notification on new sone event if first-start notification is present`() {
notificationManager.addNotification(object : AbstractNotification("first-start-notification") {
override fun render(writer: Writer) = Unit
assertThat(notification.id, equalTo("first-start-notification"))
}
+ @Test
+ fun `handler removes sone from notification if sone is marked as known`() {
+ eventBus.post(NewSoneFoundEvent(sone))
+ val notification = notificationManager.notifications.single() as ListNotification<*>
+ eventBus.post(MarkSoneKnownEvent(sone))
+ assertThat(notification.elements, emptyIterable())
+ }
+
+ @Test
+ fun `handler removes sone from notification if sone is removed`() {
+ eventBus.post(NewSoneFoundEvent(sone))
+ val notification = notificationManager.notifications.single() as ListNotification<*>
+ eventBus.post(SoneRemovedEvent(sone))
+ assertThat(notification.elements, emptyIterable())
+ }
+
}
private val sone = IdOnlySone("sone-id")
package net.pterodactylus.sone.web.notification
import com.google.common.eventbus.*
-import com.google.inject.*
import com.google.inject.Guice.*
import net.pterodactylus.sone.main.*
import net.pterodactylus.sone.test.*
@Test
fun `notification handler registers handler for sone-locked event`() {
handler.start()
- assertThat(eventBus.registeredObjects.any { it.javaClass == SoneLockedOnStartupHandler::class.java }, equalTo(true))
+ assertThat(eventBus.registeredObjects, hasItem<Any>(matches { it.javaClass == SoneLockedOnStartupHandler::class.java }))
}
@Test
fun `notification handler loads sone-locked notification template`() {
handler.start()
- assertThat(loaders.requestedTemplatePaths.any { it == "/templates/notify/soneLockedOnStartupNotification.html" }, equalTo(true))
+ assertThat(loaders.requestedTemplatePaths, hasItem("/templates/notify/soneLockedOnStartupNotification.html"))
+ }
+
+ @Test
+ fun `notification handler registers handler for new sone events`() {
+ handler.start()
+ assertThat(eventBus.registeredObjects, hasItem<Any>(matches { it.javaClass == NewSoneHandler::class.java }))
+ }
+
+ @Test
+ fun `notification handler loads new sone notification template`() {
+ handler.start()
+ assertThat(loaders.requestedTemplatePaths, hasItem("/templates/notify/newSoneNotification.html"))
}
}