diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt index e423a35f26..2daf1a412d 100644 --- a/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCase.kt @@ -36,14 +36,17 @@ class StartVoiceBroadcastUseCase @Inject constructor( Timber.d("## StartVoiceBroadcastUseCase: Start voice broadcast requested") - val lastVoiceBroadcastEvent = room.stateService().getStateEvent( - STATE_ROOM_VOICE_BROADCAST_INFO, - QueryStringValue.Equals(session.myUserId) - )?.asVoiceBroadcastEvent() - when (val voiceBroadcastState = lastVoiceBroadcastEvent?.content?.voiceBroadcastState) { - VoiceBroadcastState.STOPPED, - null -> startVoiceBroadcast(room) - else -> Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: currentState=$voiceBroadcastState") + val onGoingVoiceBroadcastEvents = room.stateService().getStateEvents( + setOf(STATE_ROOM_VOICE_BROADCAST_INFO), + QueryStringValue.IsNotEmpty + ) + .mapNotNull { it.asVoiceBroadcastEvent() } + .filter { it.content?.voiceBroadcastState != VoiceBroadcastState.STOPPED } + + if (onGoingVoiceBroadcastEvents.isEmpty()) { + startVoiceBroadcast(room) + } else { + Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: currentVoiceBroadcastEvents=$onGoingVoiceBroadcastEvents") } } diff --git a/vector/src/test/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCaseTest.kt b/vector/src/test/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCaseTest.kt index 3bb04f3a7a..398d6fedf0 100644 --- a/vector/src/test/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCaseTest.kt +++ b/vector/src/test/java/im/vector/app/features/voicebroadcast/usecase/StartVoiceBroadcastUseCaseTest.kt @@ -30,6 +30,7 @@ import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeNull 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.Event 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 AN_EVENT_ID = "event_id" +private const val A_USER_ID = "user_id" class StartVoiceBroadcastUseCaseTest { @@ -45,30 +47,31 @@ class StartVoiceBroadcastUseCaseTest { private val startVoiceBroadcastUseCase = StartVoiceBroadcastUseCase(fakeSession) @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 { - val cases = listOf(null).plus(VoiceBroadcastState.values()).map { - when (it) { - VoiceBroadcastState.STARTED, - VoiceBroadcastState.PAUSED, - VoiceBroadcastState.RESUMED -> Case(it, false) - VoiceBroadcastState.STOPPED, - null -> Case(it, true) - } - } + 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 = VoiceBroadcastState.values() + .flatMap { first -> + VoiceBroadcastState.values().map { second -> + Case( + voiceBroadcasts = listOf(VoiceBroadcast(fakeSession.myUserId, first), VoiceBroadcast(A_USER_ID, second)), + canStartVoiceBroadcast = first == VoiceBroadcastState.STOPPED && second == VoiceBroadcastState.STOPPED + ) + } + } + .plus(Case(emptyList(), true)) cases.forEach { case -> if (case.canStartVoiceBroadcast) { - testVoiceBroadcastStarted(case.previousState) + testVoiceBroadcastStarted(case.voiceBroadcasts) } else { - testVoiceBroadcastNotStarted(case.previousState) + testVoiceBroadcastNotStarted(case.voiceBroadcasts) } } } - private suspend fun testVoiceBroadcastStarted(previousState: VoiceBroadcastState?) { + private suspend fun testVoiceBroadcastStarted(voiceBroadcasts: List) { // Given clearAllMocks() - givenAVoiceBroadcastState(previousState) + givenAVoiceBroadcasts(voiceBroadcasts) val voiceBroadcastInfoContentInterceptor = slot() coEvery { fakeRoom.stateService().sendStateEvent(any(), any(), capture(voiceBroadcastInfoContentInterceptor)) } coAnswers { AN_EVENT_ID } @@ -88,10 +91,10 @@ class StartVoiceBroadcastUseCaseTest { voiceBroadcastInfoContent?.relatesTo.shouldBeNull() } - private suspend fun testVoiceBroadcastNotStarted(previousState: VoiceBroadcastState?) { + private suspend fun testVoiceBroadcastNotStarted(voiceBroadcasts: List) { // Given clearAllMocks() - givenAVoiceBroadcastState(previousState) + givenAVoiceBroadcasts(voiceBroadcasts) // When startVoiceBroadcastUseCase.execute(A_ROOM_ID) @@ -100,18 +103,19 @@ class StartVoiceBroadcastUseCaseTest { coVerify(exactly = 0) { fakeRoom.stateService().sendStateEvent(any(), any(), any()) } } - private fun givenAVoiceBroadcastState(state: VoiceBroadcastState?) { - val event = state?.let { + private fun givenAVoiceBroadcasts(voiceBroadcasts: List) { + val events = voiceBroadcasts.map { Event( type = STATE_ROOM_VOICE_BROADCAST_INFO, - stateKey = fakeSession.myUserId, + stateKey = it.userId, content = MessageVoiceBroadcastInfoContent( - voiceBroadcastStateStr = state.value + voiceBroadcastStateStr = it.state.value ).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, val canStartVoiceBroadcast: Boolean) } diff --git a/vector/src/test/java/im/vector/app/test/fakes/FakeStateService.kt b/vector/src/test/java/im/vector/app/test/fakes/FakeStateService.kt index 03a0cf07d8..7c393c7a57 100644 --- a/vector/src/test/java/im/vector/app/test/fakes/FakeStateService.kt +++ b/vector/src/test/java/im/vector/app/test/fakes/FakeStateService.kt @@ -18,11 +18,16 @@ package im.vector.app.test.fakes import io.mockk.every 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.room.state.StateService class FakeStateService : StateService by mockk(relaxed = true) { + fun givenGetStateEvents(stateKey: QueryStateEventValue, result: List) { + every { getStateEvents(any(), stateKey) } returns result + } + fun givenGetStateEvent(event: Event?) { every { getStateEvent(any(), any()) } returns event }