Skip to content

Commit

Permalink
Update Session Service Tests
Browse files Browse the repository at this point in the history
* Update existing tests now that the start() method of the SessionService takes on more responsibility and relies on knowing the foregrounded or backgrounded state of the application.
* Extract helper methods them into a helper class for reuse
* Add test "session created in start when application is in the foreground"
  • Loading branch information
nan-li committed Jun 7, 2024
1 parent f85743e commit 941e4a0
Showing 1 changed file with 98 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -1,120 +1,164 @@
package com.onesignal.session.internal.session

import com.onesignal.core.internal.application.IApplicationService
import com.onesignal.core.internal.application.impl.ApplicationService
import com.onesignal.mocks.MockHelper
import com.onesignal.session.internal.session.impl.SessionService
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.spyk
import io.mockk.verify

class SessionServiceTests : FunSpec({
// Mocks used by every test in this file
private class Mocks {
val currentTime = 1111L

private val mockSessionModelStore = MockHelper.sessionModelStore()

fun sessionModelStore(action: ((SessionModel) -> Unit)? = null): SessionModelStore {
if (action != null) action(mockSessionModelStore.model)
return mockSessionModelStore
}

private val mockApplicationService = mockk<ApplicationService>()

fun applicationService(inForeground: Boolean = false): IApplicationService =
run {
every { mockApplicationService.addApplicationLifecycleHandler(any()) } just Runs
every { mockApplicationService.removeApplicationLifecycleHandler(any()) } just Runs
every { mockApplicationService.isInForeground } returns inForeground
mockApplicationService
}

private var mockSessionService: SessionService? = null

fun sessionService(inForeground: Boolean = false): SessionService {
if (mockSessionService != null) return mockSessionService!!
mockSessionService = SessionService(applicationService(inForeground), MockHelper.configModelStore(), mockSessionModelStore, MockHelper.time(currentTime))
return mockSessionService!!
}

val spyCallback = spyk<ISessionLifecycleHandler>()
}

class SessionServiceTests : FunSpec({
test("session created on focus when current session invalid") {
// Given
val currentTime = 1111L

val configModelStoreMock = MockHelper.configModelStore()
val sessionModelStoreMock =
MockHelper.sessionModelStore {
it.isValid = false
}
val spyCallback = spyk<ISessionLifecycleHandler>()
val mocks = Mocks()
val sessionService = mocks.sessionService(false)

val sessionService =
SessionService(MockHelper.applicationService(), configModelStoreMock, sessionModelStoreMock, MockHelper.time(currentTime))
sessionService.start()
sessionService.subscribe(spyCallback)
val sessionModelStore = mocks.sessionModelStore { it.isValid = false }
sessionService.subscribe(mocks.spyCallback)

// When
sessionService.onFocus()

// Then
sessionModelStoreMock.model.isValid shouldBe true
sessionModelStoreMock.model.startTime shouldBe currentTime
sessionModelStoreMock.model.focusTime shouldBe currentTime
verify(exactly = 1) { spyCallback.onSessionStarted() }
sessionModelStore.model.isValid shouldBe true
sessionModelStore.model.startTime shouldBe mocks.currentTime
sessionModelStore.model.focusTime shouldBe mocks.currentTime
verify(exactly = 1) { mocks.spyCallback.onSessionStarted() }
}

test("session created in start when application is in the foreground") {
// Given
val mocks = Mocks()
val sessionService = mocks.sessionService(true)
val sessionModelStore = mocks.sessionModelStore()

// When
sessionService.start()
sessionService.subscribe(mocks.spyCallback)

// Then
sessionModelStore.model.isValid shouldBe true
sessionModelStore.model.startTime shouldBe mocks.currentTime
sessionModelStore.model.focusTime shouldBe mocks.currentTime
verify(exactly = 1) { mocks.spyCallback.onSessionStarted() }

// When
sessionService.onFocus() // Should not trigger a second session

// Then
verify(exactly = 1) { mocks.spyCallback.onSessionStarted() }
}

test("session focus time updated when current session valid") {
// Given
val currentTime = 1111L
val startTime = 555L
val mocks = Mocks()
val sessionService = mocks.sessionService(false)

val configModelStoreMock = MockHelper.configModelStore()
val sessionModelStoreMock =
MockHelper.sessionModelStore {
it.isValid = true
sessionService.start()
val sessionModelStore =
mocks.sessionModelStore {
it.startTime = startTime
it.isValid = true
}
val spyCallback = spyk<ISessionLifecycleHandler>()

val sessionService =
SessionService(MockHelper.applicationService(), configModelStoreMock, sessionModelStoreMock, MockHelper.time(currentTime))
sessionService.start()
sessionService.subscribe(spyCallback)
sessionService.subscribe(mocks.spyCallback)

// When
sessionService.onFocus()

// Then
sessionModelStoreMock.model.isValid shouldBe true
sessionModelStoreMock.model.startTime shouldBe startTime
sessionModelStoreMock.model.focusTime shouldBe currentTime
verify(exactly = 1) { spyCallback.onSessionActive() }
sessionModelStore.model.isValid shouldBe true
sessionModelStore.model.startTime shouldBe startTime
sessionModelStore.model.focusTime shouldBe mocks.currentTime
verify(exactly = 1) { mocks.spyCallback.onSessionActive() }
verify(exactly = 0) { mocks.spyCallback.onSessionStarted() }
}

test("session active duration updated when unfocused") {
// Given
val startTime = 555L
val focusTime = 666L
val startingDuration = 1000L
val currentTime = 1111L

val configModelStoreMock = MockHelper.configModelStore()
val sessionModelStoreMock =
MockHelper.sessionModelStore {
val mocks = Mocks()
val sessionService = mocks.sessionService(false)

sessionService.start()
val sessionModelStore =
mocks.sessionModelStore {
it.isValid = true
it.startTime = startTime
it.focusTime = focusTime
it.activeDuration = startingDuration
}

val sessionService =
SessionService(MockHelper.applicationService(), configModelStoreMock, sessionModelStoreMock, MockHelper.time(currentTime))
sessionService.start()

// When
sessionService.onUnfocused()

// Then
sessionModelStoreMock.model.isValid shouldBe true
sessionModelStoreMock.model.startTime shouldBe startTime
sessionModelStoreMock.model.activeDuration shouldBe startingDuration + (currentTime - focusTime)
sessionModelStore.model.isValid shouldBe true
sessionModelStore.model.startTime shouldBe startTime
sessionModelStore.model.activeDuration shouldBe startingDuration + (mocks.currentTime - focusTime)
}

test("session ended when background run") {
// Given
val activeDuration = 555L
val currentTime = 1111L
val mocks = Mocks()
val sessionService = mocks.sessionService(false)

val configModelStoreMock = MockHelper.configModelStore()
val sessionModelStoreMock =
MockHelper.sessionModelStore {
sessionService.start()
val sessionModelStore =
mocks.sessionModelStore {
it.isValid = true
it.activeDuration = activeDuration
}
val spyCallback = spyk<ISessionLifecycleHandler>()

val sessionService =
SessionService(MockHelper.applicationService(), configModelStoreMock, sessionModelStoreMock, MockHelper.time(currentTime))
sessionService.start()
sessionService.subscribe(spyCallback)
sessionService.subscribe(mocks.spyCallback)

// When
sessionService.backgroundRun()

// Then
sessionModelStoreMock.model.isValid shouldBe false
verify(exactly = 1) { spyCallback.onSessionEnded(activeDuration) }
sessionModelStore.model.isValid shouldBe false
verify(exactly = 1) { mocks.spyCallback.onSessionEnded(activeDuration) }
}
})

0 comments on commit 941e4a0

Please sign in to comment.