Verify that there is no ongoing voice broadcast before starting a new one

This commit is contained in:
Florian Renaud 2022-10-04 17:50:35 +02:00
parent b9bb7d7892
commit e4e953acf9
3 changed files with 42 additions and 30 deletions

View File

@ -36,14 +36,17 @@ class StartVoiceBroadcastUseCase @Inject constructor(
Timber.d("## StartVoiceBroadcastUseCase: Start voice broadcast requested") Timber.d("## StartVoiceBroadcastUseCase: Start voice broadcast requested")
val lastVoiceBroadcastEvent = room.stateService().getStateEvent( val onGoingVoiceBroadcastEvents = room.stateService().getStateEvents(
STATE_ROOM_VOICE_BROADCAST_INFO, setOf(STATE_ROOM_VOICE_BROADCAST_INFO),
QueryStringValue.Equals(session.myUserId) QueryStringValue.IsNotEmpty
)?.asVoiceBroadcastEvent() )
when (val voiceBroadcastState = lastVoiceBroadcastEvent?.content?.voiceBroadcastState) { .mapNotNull { it.asVoiceBroadcastEvent() }
VoiceBroadcastState.STOPPED, .filter { it.content?.voiceBroadcastState != VoiceBroadcastState.STOPPED }
null -> startVoiceBroadcast(room)
else -> Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: currentState=$voiceBroadcastState") if (onGoingVoiceBroadcastEvents.isEmpty()) {
startVoiceBroadcast(room)
} else {
Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: currentVoiceBroadcastEvents=$onGoingVoiceBroadcastEvents")
} }
} }

View File

@ -30,6 +30,7 @@ import kotlinx.coroutines.test.runTest
import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldBeNull import org.amshove.kluent.shouldBeNull
import org.junit.Test import org.junit.Test
import org.matrix.android.sdk.api.query.QueryStringValue
import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.toContent import org.matrix.android.sdk.api.session.events.model.toContent
@ -37,6 +38,7 @@ import org.matrix.android.sdk.api.session.events.model.toModel
private const val A_ROOM_ID = "room_id" private const val A_ROOM_ID = "room_id"
private const val AN_EVENT_ID = "event_id" private const val AN_EVENT_ID = "event_id"
private const val A_USER_ID = "user_id"
class StartVoiceBroadcastUseCaseTest { class StartVoiceBroadcastUseCaseTest {
@ -45,30 +47,31 @@ class StartVoiceBroadcastUseCaseTest {
private val startVoiceBroadcastUseCase = StartVoiceBroadcastUseCase(fakeSession) private val startVoiceBroadcastUseCase = StartVoiceBroadcastUseCase(fakeSession)
@Test @Test
fun `given a room id with a potential existing voice broadcast state when calling execute then the voice broadcast is started or not`() = runTest { fun `given a room id with potential several existing voice broadcast states when calling execute then the voice broadcast is started or not`() = runTest {
val cases = listOf<VoiceBroadcastState?>(null).plus(VoiceBroadcastState.values()).map { val cases = VoiceBroadcastState.values()
when (it) { .flatMap { first ->
VoiceBroadcastState.STARTED, VoiceBroadcastState.values().map { second ->
VoiceBroadcastState.PAUSED, Case(
VoiceBroadcastState.RESUMED -> Case(it, false) voiceBroadcasts = listOf(VoiceBroadcast(fakeSession.myUserId, first), VoiceBroadcast(A_USER_ID, second)),
VoiceBroadcastState.STOPPED, canStartVoiceBroadcast = first == VoiceBroadcastState.STOPPED && second == VoiceBroadcastState.STOPPED
null -> Case(it, true) )
} }
} }
.plus(Case(emptyList(), true))
cases.forEach { case -> cases.forEach { case ->
if (case.canStartVoiceBroadcast) { if (case.canStartVoiceBroadcast) {
testVoiceBroadcastStarted(case.previousState) testVoiceBroadcastStarted(case.voiceBroadcasts)
} else { } else {
testVoiceBroadcastNotStarted(case.previousState) testVoiceBroadcastNotStarted(case.voiceBroadcasts)
} }
} }
} }
private suspend fun testVoiceBroadcastStarted(previousState: VoiceBroadcastState?) { private suspend fun testVoiceBroadcastStarted(voiceBroadcasts: List<VoiceBroadcast>) {
// Given // Given
clearAllMocks() clearAllMocks()
givenAVoiceBroadcastState(previousState) givenAVoiceBroadcasts(voiceBroadcasts)
val voiceBroadcastInfoContentInterceptor = slot<Content>() val voiceBroadcastInfoContentInterceptor = slot<Content>()
coEvery { fakeRoom.stateService().sendStateEvent(any(), any(), capture(voiceBroadcastInfoContentInterceptor)) } coAnswers { AN_EVENT_ID } coEvery { fakeRoom.stateService().sendStateEvent(any(), any(), capture(voiceBroadcastInfoContentInterceptor)) } coAnswers { AN_EVENT_ID }
@ -88,10 +91,10 @@ class StartVoiceBroadcastUseCaseTest {
voiceBroadcastInfoContent?.relatesTo.shouldBeNull() voiceBroadcastInfoContent?.relatesTo.shouldBeNull()
} }
private suspend fun testVoiceBroadcastNotStarted(previousState: VoiceBroadcastState?) { private suspend fun testVoiceBroadcastNotStarted(voiceBroadcasts: List<VoiceBroadcast>) {
// Given // Given
clearAllMocks() clearAllMocks()
givenAVoiceBroadcastState(previousState) givenAVoiceBroadcasts(voiceBroadcasts)
// When // When
startVoiceBroadcastUseCase.execute(A_ROOM_ID) startVoiceBroadcastUseCase.execute(A_ROOM_ID)
@ -100,18 +103,19 @@ class StartVoiceBroadcastUseCaseTest {
coVerify(exactly = 0) { fakeRoom.stateService().sendStateEvent(any(), any(), any()) } coVerify(exactly = 0) { fakeRoom.stateService().sendStateEvent(any(), any(), any()) }
} }
private fun givenAVoiceBroadcastState(state: VoiceBroadcastState?) { private fun givenAVoiceBroadcasts(voiceBroadcasts: List<VoiceBroadcast>) {
val event = state?.let { val events = voiceBroadcasts.map {
Event( Event(
type = STATE_ROOM_VOICE_BROADCAST_INFO, type = STATE_ROOM_VOICE_BROADCAST_INFO,
stateKey = fakeSession.myUserId, stateKey = it.userId,
content = MessageVoiceBroadcastInfoContent( content = MessageVoiceBroadcastInfoContent(
voiceBroadcastStateStr = state.value voiceBroadcastStateStr = it.state.value
).toContent() ).toContent()
) )
} }
fakeRoom.stateService().givenGetStateEvent(event) fakeRoom.stateService().givenGetStateEvents(QueryStringValue.IsNotEmpty, events)
} }
private data class Case(val previousState: VoiceBroadcastState?, val canStartVoiceBroadcast: Boolean) private data class VoiceBroadcast(val userId: String, val state: VoiceBroadcastState)
private data class Case(val voiceBroadcasts: List<VoiceBroadcast>, val canStartVoiceBroadcast: Boolean)
} }

View File

@ -18,11 +18,16 @@ package im.vector.app.test.fakes
import io.mockk.every import io.mockk.every
import io.mockk.mockk import io.mockk.mockk
import org.matrix.android.sdk.api.query.QueryStateEventValue
import org.matrix.android.sdk.api.session.events.model.Event import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.room.state.StateService import org.matrix.android.sdk.api.session.room.state.StateService
class FakeStateService : StateService by mockk(relaxed = true) { class FakeStateService : StateService by mockk(relaxed = true) {
fun givenGetStateEvents(stateKey: QueryStateEventValue, result: List<Event>) {
every { getStateEvents(any(), stateKey) } returns result
}
fun givenGetStateEvent(event: Event?) { fun givenGetStateEvent(event: Event?) {
every { getStateEvent(any(), any()) } returns event every { getStateEvent(any(), any()) } returns event
} }