diff --git a/vector/src/main/java/im/vector/app/features/voicebroadcast/recording/usecase/StartVoiceBroadcastUseCase.kt b/vector/src/main/java/im/vector/app/features/voicebroadcast/recording/usecase/StartVoiceBroadcastUseCase.kt index 8a335eccac..85f72c09da 100644 --- a/vector/src/main/java/im/vector/app/features/voicebroadcast/recording/usecase/StartVoiceBroadcastUseCase.kt +++ b/vector/src/main/java/im/vector/app/features/voicebroadcast/recording/usecase/StartVoiceBroadcastUseCase.kt @@ -28,6 +28,7 @@ import im.vector.app.features.voicebroadcast.model.VoiceBroadcastState import im.vector.app.features.voicebroadcast.recording.VoiceBroadcastRecorder import im.vector.app.features.voicebroadcast.usecase.GetOngoingVoiceBroadcastsUseCase import im.vector.lib.multipicker.utils.toMultiPickerAudioType +import org.jetbrains.annotations.VisibleForTesting import org.matrix.android.sdk.api.query.QueryStringValue import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.events.model.EventType @@ -57,28 +58,8 @@ class StartVoiceBroadcastUseCase @Inject constructor( Timber.d("## StartVoiceBroadcastUseCase: Start voice broadcast requested") - val powerLevelsHelper = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty) - ?.content - ?.toModel() - ?.let { PowerLevelsHelper(it) } - - when { - powerLevelsHelper?.isUserAllowedToSend(session.myUserId, true, VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO) != true -> { - Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: no permission") - throw VoiceBroadcastFailure.RecordingError.NoPermission - } - voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Recording || voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Paused -> { - Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: another voice broadcast") - throw VoiceBroadcastFailure.RecordingError.UserAlreadyBroadcasting - } - getOngoingVoiceBroadcastsUseCase.execute(roomId).isNotEmpty() -> { - Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: user already broadcasting") - throw VoiceBroadcastFailure.RecordingError.BlockedBySomeoneElse - } - else -> { - startVoiceBroadcast(room) - } - } + assertCanStartVoiceBroadcast(room) + startVoiceBroadcast(room) } private suspend fun startVoiceBroadcast(room: Room) { @@ -124,4 +105,36 @@ class StartVoiceBroadcastUseCase @Inject constructor( ) ) } + + private fun assertCanStartVoiceBroadcast(room: Room) { + assertHasEnoughPowerLevels(room) + assertNoOngoingVoiceBroadcast(room) + } + + @VisibleForTesting + fun assertHasEnoughPowerLevels(room: Room) { + val powerLevelsHelper = room.getStateEvent(EventType.STATE_ROOM_POWER_LEVELS, QueryStringValue.IsEmpty) + ?.content + ?.toModel() + ?.let { PowerLevelsHelper(it) } + + if (powerLevelsHelper?.isUserAllowedToSend(session.myUserId, true, VoiceBroadcastConstants.STATE_ROOM_VOICE_BROADCAST_INFO) != true) { + Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: no permission") + throw VoiceBroadcastFailure.RecordingError.NoPermission + } + } + + @VisibleForTesting + fun assertNoOngoingVoiceBroadcast(room: Room) { + when { + voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Recording || voiceBroadcastRecorder?.state == VoiceBroadcastRecorder.State.Paused -> { + Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: another voice broadcast") + throw VoiceBroadcastFailure.RecordingError.UserAlreadyBroadcasting + } + getOngoingVoiceBroadcastsUseCase.execute(room.roomId).isNotEmpty() -> { + Timber.d("## StartVoiceBroadcastUseCase: Cannot start voice broadcast: user already broadcasting") + throw VoiceBroadcastFailure.RecordingError.BlockedBySomeoneElse + } + } + } } 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 59929ef0d7..ef78f1c80d 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 @@ -26,15 +26,17 @@ import im.vector.app.test.fakes.FakeContext import im.vector.app.test.fakes.FakeRoom import im.vector.app.test.fakes.FakeRoomService import im.vector.app.test.fakes.FakeSession -import io.mockk.clearAllMocks import io.mockk.coEvery import io.mockk.coVerify import io.mockk.every +import io.mockk.justRun import io.mockk.mockk import io.mockk.slot +import io.mockk.spyk import kotlinx.coroutines.test.runTest import org.amshove.kluent.shouldBe import org.amshove.kluent.shouldBeNull +import org.junit.Before import org.junit.Test import org.matrix.android.sdk.api.session.events.model.Content import org.matrix.android.sdk.api.session.events.model.Event @@ -51,14 +53,23 @@ class StartVoiceBroadcastUseCaseTest { private val fakeSession = FakeSession(fakeRoomService = FakeRoomService(fakeRoom)) private val fakeVoiceBroadcastRecorder = mockk(relaxed = true) private val fakeGetOngoingVoiceBroadcastsUseCase = mockk() - private val startVoiceBroadcastUseCase = StartVoiceBroadcastUseCase( - session = fakeSession, - voiceBroadcastRecorder = fakeVoiceBroadcastRecorder, - context = FakeContext().instance, - buildMeta = mockk(), - getOngoingVoiceBroadcastsUseCase = fakeGetOngoingVoiceBroadcastsUseCase, + private val startVoiceBroadcastUseCase = spyk( + StartVoiceBroadcastUseCase( + session = fakeSession, + voiceBroadcastRecorder = fakeVoiceBroadcastRecorder, + context = FakeContext().instance, + buildMeta = mockk(), + getOngoingVoiceBroadcastsUseCase = fakeGetOngoingVoiceBroadcastsUseCase, + ) ) + @Before + fun setup() { + every { fakeRoom.roomId } returns A_ROOM_ID + justRun { startVoiceBroadcastUseCase.assertHasEnoughPowerLevels(fakeRoom) } + every { fakeVoiceBroadcastRecorder.state } returns VoiceBroadcastRecorder.State.Idle + } + @Test 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() @@ -83,7 +94,7 @@ class StartVoiceBroadcastUseCaseTest { private suspend fun testVoiceBroadcastStarted(voiceBroadcasts: List) { // Given - clearAllMocks() + setup() givenVoiceBroadcasts(voiceBroadcasts) val voiceBroadcastInfoContentInterceptor = slot() coEvery { fakeRoom.stateService().sendStateEvent(any(), any(), capture(voiceBroadcastInfoContentInterceptor)) } coAnswers { AN_EVENT_ID } @@ -106,7 +117,7 @@ class StartVoiceBroadcastUseCaseTest { private suspend fun testVoiceBroadcastNotStarted(voiceBroadcasts: List) { // Given - clearAllMocks() + setup() givenVoiceBroadcasts(voiceBroadcasts) // When