adding tests around the notification usecase entry point

This commit is contained in:
Adam Brown 2022-06-08 19:21:20 +01:00
parent 8743052899
commit bb47fcd9d6
11 changed files with 125 additions and 18 deletions

View File

@ -1,6 +1,8 @@
package test
import io.mockk.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf
inline fun <T : Any, reified R> T.expect(crossinline block: suspend MockKMatcherScope.(T) -> R) {
coEvery { block(this@expect) } returns mockk(relaxed = true)
@ -16,11 +18,22 @@ fun <T, B> MockKStubScope<T, B>.delegateReturn() = object : Returns<T> {
}
}
fun <T, B> MockKStubScope<Flow<T>, B>.delegateEmit() = object : Emits<T> {
override fun emits(vararg values: T) {
answers(ConstantAnswer(flowOf(*values)))
}
}
fun <T> returns(block: (T) -> Unit) = object : Returns<T> {
override fun returns(value: T) = block(value)
override fun throws(value: Throwable) = throw value
}
interface Emits<T> {
fun emits(vararg values: T)
}
interface Returns<T> {
fun returns(value: T)
fun throws(value: Throwable)

View File

@ -31,7 +31,7 @@ class NotificationsModule(
fun credentialProvider() = credentialsStore
fun firebasePushTokenUseCase() = firebasePushTokenUseCase
fun roomStore() = roomStore
fun notificationsUseCase() = NotificationsUseCase(
fun notificationsUseCase() = RenderNotificationsUseCase(
NotificationRenderer(notificationManager(), NotificationFactory(iconLoader, context, intentFactory), dispatchers),
ObserveUnreadNotificationsUseCaseImpl(roomStore),
NotificationChannels(notificationManager()),

View File

@ -7,7 +7,7 @@ import app.dapk.st.matrix.sync.RoomOverview
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.onEach
class NotificationsUseCase(
class RenderNotificationsUseCase(
private val notificationRenderer: NotificationRenderer,
private val observeRenderableUnreadEventsUseCase: ObserveUnreadNotificationsUseCase,
notificationChannels: NotificationChannels,

View File

@ -1,6 +1,6 @@
package app.dapk.st.notifications
import app.dapk.st.notifications.NotificationFixtures.aNotifications
import fixture.NotificationFixtures.aNotifications
import fake.FakeNotificationFactory
import fake.FakeNotificationManager
import fake.aFakeNotification

View File

@ -1,14 +1,10 @@
package app.dapk.st.notifications
import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.matrix.sync.RoomEvent
import app.dapk.st.matrix.sync.RoomOverview
import fake.FakeRoomStore
import fixture.aRoomId
import fixture.aRoomMessageEvent
import fixture.aRoomOverview
import fixture.anEventId
import fixture.*
import fixture.NotificationDiffFixtures.aNotificationDiff
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
@ -21,7 +17,7 @@ val A_MESSAGE_2 = aRoomMessageEvent(eventId = anEventId("2"), content = "world")
val A_ROOM_OVERVIEW = aRoomOverview(roomId = aRoomId("1"))
val A_ROOM_OVERVIEW_2 = aRoomOverview(roomId = aRoomId("2"))
class ObserveUnreadNotificationsUseCaseTest {
class ObserveUnreadRenderNotificationsUseCaseTest {
private val fakeRoomStore = FakeRoomStore()
@ -94,12 +90,5 @@ class ObserveUnreadNotificationsUseCaseTest {
private fun givenNoInitialUnreads(vararg unreads: Map<RoomOverview, List<RoomEvent>>) = fakeRoomStore.givenUnreadEvents(flowOf(NO_UNREADS, *unreads))
}
private fun aNotificationDiff(
unchanged: Map<RoomId, List<EventId>> = emptyMap(),
changedOrNew: Map<RoomId, List<EventId>> = emptyMap(),
removed: Map<RoomId, List<EventId>> = emptyMap(),
newRooms: Set<RoomId> = emptySet(),
) = NotificationDiff(unchanged, changedOrNew, removed, newRooms)
private fun RoomOverview.withUnreads(vararg events: RoomEvent) = mapOf(this to events.toList())
private fun RoomOverview.toDiff(vararg events: RoomEvent) = mapOf(this.roomId to events.map { it.eventId })

View File

@ -0,0 +1,41 @@
package app.dapk.st.notifications
import fake.FakeNotificationChannels
import fake.FakeNotificationRenderer
import fake.FakeObserveUnreadNotificationsUseCase
import fixture.NotificationDiffFixtures.aNotificationDiff
import kotlinx.coroutines.test.runTest
import org.junit.Test
import test.expect
private val AN_UNREAD_NOTIFICATIONS = UnreadNotifications(emptyMap(), aNotificationDiff())
class RenderNotificationsUseCaseTest {
private val fakeNotificationRenderer = FakeNotificationRenderer()
private val fakeObserveUnreadNotificationsUseCase = FakeObserveUnreadNotificationsUseCase()
private val fakeNotificationChannels = FakeNotificationChannels().also {
it.instance.expect { it.initChannels() }
}
private val renderNotificationsUseCase = RenderNotificationsUseCase(
fakeNotificationRenderer.instance,
fakeObserveUnreadNotificationsUseCase,
fakeNotificationChannels.instance,
)
@Test
fun `when creating use case instance, then initiates channels`() {
fakeNotificationChannels.verifyInitiated()
}
@Test
fun `given renderable unread events, when listening for changes, then renders change`() = runTest {
fakeNotificationRenderer.instance.expect { it.render(any(), any(), any(), any()) }
fakeObserveUnreadNotificationsUseCase.given().emits(AN_UNREAD_NOTIFICATIONS)
renderNotificationsUseCase.listenForNotificationChanges()
fakeNotificationRenderer.verifyRenders(AN_UNREAD_NOTIFICATIONS)
}
}

View File

@ -0,0 +1,13 @@
package fake
import app.dapk.st.notifications.NotificationChannels
import io.mockk.mockk
import io.mockk.verify
class FakeNotificationChannels {
val instance = mockk<NotificationChannels>()
fun verifyInitiated() {
verify { instance.initChannels() }
}
}

View File

@ -0,0 +1,23 @@
package fake
import app.dapk.st.notifications.NotificationRenderer
import app.dapk.st.notifications.UnreadNotifications
import io.mockk.coVerify
import io.mockk.mockk
class FakeNotificationRenderer {
val instance = mockk<NotificationRenderer>()
fun verifyRenders(vararg unreadNotifications: UnreadNotifications) {
unreadNotifications.forEach { unread ->
coVerify {
instance.render(
allUnread = unread.first,
removedRooms = unread.second.removed.keys,
roomsWithNewEvents = unread.second.changedOrNew.keys,
newRooms = unread.second.newRooms,
)
}
}
}
}

View File

@ -0,0 +1,10 @@
package fake
import app.dapk.st.notifications.ObserveUnreadNotificationsUseCase
import io.mockk.coEvery
import io.mockk.mockk
import test.delegateEmit
class FakeObserveUnreadNotificationsUseCase : ObserveUnreadNotificationsUseCase by mockk() {
fun given() = coEvery { this@FakeObserveUnreadNotificationsUseCase.invoke() }.delegateEmit()
}

View File

@ -0,0 +1,16 @@
package fixture
import app.dapk.st.matrix.common.EventId
import app.dapk.st.matrix.common.RoomId
import app.dapk.st.notifications.NotificationDiff
object NotificationDiffFixtures {
fun aNotificationDiff(
unchanged: Map<RoomId, List<EventId>> = emptyMap(),
changedOrNew: Map<RoomId, List<EventId>> = emptyMap(),
removed: Map<RoomId, List<EventId>> = emptyMap(),
newRooms: Set<RoomId> = emptySet(),
) = NotificationDiff(unchanged, changedOrNew, removed, newRooms)
}

View File

@ -1,6 +1,8 @@
package app.dapk.st.notifications
package fixture
import android.app.Notification
import app.dapk.st.notifications.NotificationDelegate
import app.dapk.st.notifications.Notifications
object NotificationFixtures {