[Refactor] increase unit test cases coverage (#359)
This commit is contained in:
Родитель
632a6c3fbe
Коммит
40e056fe3d
|
@ -8,13 +8,19 @@ import com.azure.android.communication.ui.calling.configuration.CallCompositeCon
|
|||
import com.azure.android.communication.ui.calling.error.ErrorHandler
|
||||
import com.azure.android.communication.ui.calling.handlers.RemoteParticipantHandler
|
||||
import com.azure.android.communication.ui.calling.logger.DefaultLogger
|
||||
import com.azure.android.communication.ui.calling.presentation.VideoStreamRendererFactory
|
||||
import com.azure.android.communication.ui.calling.presentation.VideoViewManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.AccessibilityAnnouncementManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.AudioFocusManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.AudioSessionManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.AvatarViewManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.CameraStatusHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.LifecycleManagerImpl
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.MeetingJoinedHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.MicStatusHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.ParticipantAddedOrRemovedHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.PermissionManager
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.SwitchCameraStatusHook
|
||||
|
||||
import com.azure.android.communication.ui.calling.presentation.navigation.NavigationRouterImpl
|
||||
import com.azure.android.communication.ui.calling.redux.AppStore
|
||||
|
@ -65,7 +71,7 @@ internal class DependencyInjectionContainerImpl(
|
|||
}
|
||||
|
||||
override val videoViewManager by lazy {
|
||||
VideoViewManager(callingSDKWrapper, applicationContext)
|
||||
VideoViewManager(callingSDKWrapper, applicationContext, VideoStreamRendererFactory())
|
||||
}
|
||||
|
||||
override val permissionManager by lazy {
|
||||
|
@ -97,7 +103,14 @@ internal class DependencyInjectionContainerImpl(
|
|||
|
||||
override val accessibilityManager by lazy {
|
||||
AccessibilityAnnouncementManager(
|
||||
appStore
|
||||
appStore,
|
||||
listOf(
|
||||
MeetingJoinedHook(),
|
||||
CameraStatusHook(),
|
||||
ParticipantAddedOrRemovedHook(),
|
||||
MicStatusHook(),
|
||||
SwitchCameraStatusHook(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.content.Context
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.azure.android.communication.calling.RemoteVideoStream
|
||||
import com.azure.android.communication.calling.LocalVideoStream
|
||||
import com.azure.android.communication.calling.VideoStreamRenderer
|
||||
import com.azure.android.communication.calling.VideoStreamRendererView
|
||||
import com.azure.android.communication.calling.MediaStreamType
|
||||
|
@ -17,6 +18,7 @@ import com.azure.android.communication.ui.calling.service.sdk.CallingSDKWrapper
|
|||
internal class VideoViewManager(
|
||||
private val callingSDKWrapper: CallingSDKWrapper,
|
||||
private val context: Context,
|
||||
private val videoStreamRendererFactory: VideoStreamRendererFactory,
|
||||
) {
|
||||
private val remoteParticipantVideoRendererMap: HashMap<String, VideoRenderer> = HashMap()
|
||||
private val localParticipantVideoRendererMap: HashMap<String, VideoRenderer> = HashMap()
|
||||
|
@ -60,7 +62,10 @@ internal class VideoViewManager(
|
|||
if (!localParticipantVideoRendererMap.containsKey(videoStreamID)) {
|
||||
val videoStream = callingSDKWrapper.getLocalVideoStream().get()
|
||||
val videoStreamRenderer =
|
||||
VideoStreamRenderer(videoStream, context)
|
||||
videoStreamRendererFactory.getLocalParticipantVideoStreamRenderer(
|
||||
videoStream,
|
||||
context
|
||||
)
|
||||
val rendererView = videoStreamRenderer.createView()
|
||||
localParticipantVideoRendererMap[videoStreamID] =
|
||||
VideoRenderer(rendererView, videoStreamRenderer, videoStreamID, false)
|
||||
|
@ -123,14 +128,19 @@ internal class VideoViewManager(
|
|||
|
||||
if (stream != null) {
|
||||
val isScreenShare = stream!!.mediaStreamType == MediaStreamType.SCREEN_SHARING
|
||||
val videoStreamRenderer = VideoStreamRenderer(stream, context)
|
||||
|
||||
val viewOption =
|
||||
if (isScreenShare) CreateViewOptions(ScalingMode.FIT) else CreateViewOptions(
|
||||
ScalingMode.CROP
|
||||
val videoStreamRenderer =
|
||||
videoStreamRendererFactory.getRemoteParticipantVideoStreamRenderer(
|
||||
stream,
|
||||
context
|
||||
)
|
||||
|
||||
val rendererView = videoStreamRenderer.createView(viewOption)
|
||||
val rendererView =
|
||||
if (isScreenShare) videoStreamRenderer.createView(
|
||||
CreateViewOptions(
|
||||
ScalingMode.FIT
|
||||
)
|
||||
) else videoStreamRenderer.createView()
|
||||
|
||||
remoteParticipantVideoRendererMap[uniqueID] =
|
||||
VideoRenderer(
|
||||
rendererView,
|
||||
|
@ -198,3 +208,15 @@ internal class VideoViewManager(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal class VideoStreamRendererFactory {
|
||||
fun getRemoteParticipantVideoStreamRenderer(
|
||||
stream: RemoteVideoStream?,
|
||||
context: Context,
|
||||
) = VideoStreamRenderer(stream, context)
|
||||
|
||||
fun getLocalParticipantVideoStreamRenderer(
|
||||
stream: LocalVideoStream?,
|
||||
context: Context,
|
||||
) = VideoStreamRenderer(stream, context)
|
||||
}
|
||||
|
|
|
@ -21,8 +21,8 @@ import kotlinx.coroutines.flow.collect
|
|||
// These hooks make announcements based on Redux State changes
|
||||
internal class AccessibilityAnnouncementManager(
|
||||
private val store: Store<ReduxState>,
|
||||
private val accessibilityHooks: List<AccessibilityHook>
|
||||
) {
|
||||
|
||||
private lateinit var lastState: ReduxState
|
||||
|
||||
suspend fun start(activity: Activity) {
|
||||
|
@ -52,7 +52,6 @@ internal class AccessibilityAnnouncementManager(
|
|||
}
|
||||
|
||||
// Accessibility Hook
|
||||
//
|
||||
// shouldTrigger -> detect if we should announce something
|
||||
// message -> get the text tp read
|
||||
internal abstract class AccessibilityHook {
|
||||
|
@ -60,9 +59,8 @@ internal abstract class AccessibilityHook {
|
|||
abstract fun message(lastState: ReduxState, newState: ReduxState, context: Context): String
|
||||
}
|
||||
|
||||
// Hook to announce when participants join/leave a meeting
|
||||
internal class ParticipantAddedOrRemovedHook : AccessibilityHook() {
|
||||
var callJoinTime = System.currentTimeMillis()
|
||||
private var callJoinTime = System.currentTimeMillis()
|
||||
override fun shouldTrigger(lastState: ReduxState, newState: ReduxState): Boolean {
|
||||
if (lastState.callState.callingStatus != CallingStatus.CONNECTED && newState.callState.callingStatus == CallingStatus.CONNECTED) {
|
||||
callJoinTime = System.currentTimeMillis()
|
||||
|
@ -94,7 +92,6 @@ internal class ParticipantAddedOrRemovedHook : AccessibilityHook() {
|
|||
}
|
||||
}
|
||||
|
||||
// Hook to announce the meeting was successfully joined
|
||||
internal class MeetingJoinedHook : AccessibilityHook() {
|
||||
override fun shouldTrigger(lastState: ReduxState, newState: ReduxState) =
|
||||
(lastState.callState.callingStatus != CallingStatus.CONNECTED && newState.callState.callingStatus == CallingStatus.CONNECTED)
|
||||
|
@ -141,12 +138,3 @@ internal class CameraStatusHook : AccessibilityHook() {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// List of all hooks
|
||||
internal val accessibilityHooks = listOf(
|
||||
MeetingJoinedHook(),
|
||||
CameraStatusHook(),
|
||||
ParticipantAddedOrRemovedHook(),
|
||||
MicStatusHook(),
|
||||
SwitchCameraStatusHook(),
|
||||
)
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.presentation
|
||||
|
||||
import android.content.Context
|
||||
import com.azure.android.communication.calling.LocalVideoStream
|
||||
import com.azure.android.communication.calling.RemoteParticipant
|
||||
import com.azure.android.communication.calling.RemoteVideoStream
|
||||
import com.azure.android.communication.calling.VideoStreamRenderer
|
||||
import com.azure.android.communication.calling.VideoStreamRendererView
|
||||
import com.azure.android.communication.calling.MediaStreamType
|
||||
import com.azure.android.communication.ui.calling.presentation.VideoStreamRendererFactory
|
||||
import com.azure.android.communication.ui.calling.presentation.VideoViewManager
|
||||
import com.azure.android.communication.ui.calling.service.sdk.CallingSDKWrapper
|
||||
import java9.util.concurrent.CompletableFuture
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.mock
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
internal class VideoViewManagerUnitTest {
|
||||
|
||||
@Test
|
||||
fun videoViewManager_destroy_then_clearLocalAndRemoteParticipantVideoRendererMap() {
|
||||
// arrange
|
||||
val mockVideoStream = mock<RemoteVideoStream> {
|
||||
on { id } doAnswer { 111 }
|
||||
on { mediaStreamType } doAnswer { MediaStreamType.VIDEO }
|
||||
}
|
||||
val mockRemoteParticipant = mock<RemoteParticipant> {
|
||||
on { videoStreams } doAnswer { listOf(mockVideoStream) }
|
||||
}
|
||||
|
||||
val remoteParticipantMap: MutableMap<String, RemoteParticipant> = mutableMapOf()
|
||||
remoteParticipantMap["user"] = mockRemoteParticipant
|
||||
|
||||
val mockLocalVideoStream = mock<LocalVideoStream> { }
|
||||
|
||||
val localVideoStreamCompletableFuture =
|
||||
CompletableFuture<LocalVideoStream>()
|
||||
localVideoStreamCompletableFuture.complete(mockLocalVideoStream)
|
||||
|
||||
val mockCallingSDKWrapper = mock<CallingSDKWrapper> {
|
||||
on { getRemoteParticipantsMap() } doAnswer { remoteParticipantMap }
|
||||
on { getLocalVideoStream() } doAnswer { localVideoStreamCompletableFuture }
|
||||
}
|
||||
|
||||
val mockContext = mock<Context> {}
|
||||
|
||||
val mockVideoStreamRendererView = mock<VideoStreamRendererView> {}
|
||||
|
||||
val mockVideoStreamRenderer = mock<VideoStreamRenderer> {
|
||||
on { createView() } doAnswer { mockVideoStreamRendererView }
|
||||
}
|
||||
|
||||
val mockVideoStreamRendererHelper = mock<VideoStreamRendererFactory> {
|
||||
on {
|
||||
getRemoteParticipantVideoStreamRenderer(
|
||||
any(),
|
||||
any()
|
||||
)
|
||||
} doAnswer { mockVideoStreamRenderer }
|
||||
on {
|
||||
getLocalParticipantVideoStreamRenderer(
|
||||
any(),
|
||||
any()
|
||||
)
|
||||
} doAnswer { mockVideoStreamRenderer }
|
||||
}
|
||||
|
||||
val videoViewManager =
|
||||
VideoViewManager(mockCallingSDKWrapper, mockContext, mockVideoStreamRendererHelper)
|
||||
|
||||
val remoteVideoView =
|
||||
videoViewManager.getRemoteVideoStreamRenderer("user", "111")
|
||||
videoViewManager.updateLocalVideoRenderer("345")
|
||||
val localVideoView = videoViewManager.getLocalVideoRenderer("345")
|
||||
|
||||
// act
|
||||
videoViewManager.destroy()
|
||||
remoteParticipantMap.clear()
|
||||
val remoteVideoViewAfterDelete =
|
||||
videoViewManager.getRemoteVideoStreamRenderer("user", "111")
|
||||
val localVideoViewAfterDelete = videoViewManager.getLocalVideoRenderer("345")
|
||||
|
||||
// assert
|
||||
Assert.assertNotNull(remoteVideoView)
|
||||
Assert.assertNotNull(localVideoView)
|
||||
Assert.assertEquals(remoteVideoViewAfterDelete, null)
|
||||
Assert.assertEquals(localVideoViewAfterDelete, null)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun videoViewManager_updateLocalVideoRenderer_when_calledWithValidID_then_insertLocalVideoViewInMap() {
|
||||
// arrange
|
||||
val mockLocalVideoStream = mock<LocalVideoStream> { }
|
||||
|
||||
val localVideoStreamCompletableFuture =
|
||||
CompletableFuture<LocalVideoStream>()
|
||||
localVideoStreamCompletableFuture.complete(mockLocalVideoStream)
|
||||
|
||||
val mockCallingSDKWrapper = mock<CallingSDKWrapper> {
|
||||
on { getLocalVideoStream() } doAnswer { localVideoStreamCompletableFuture }
|
||||
}
|
||||
|
||||
val mockContext = mock<Context> {}
|
||||
|
||||
val mockVideoStreamRendererView = mock<VideoStreamRendererView> {}
|
||||
|
||||
val mockVideoStreamRenderer = mock<VideoStreamRenderer> {
|
||||
on { createView() } doAnswer { mockVideoStreamRendererView }
|
||||
}
|
||||
|
||||
val mockVideoStreamRendererHelper = mock<VideoStreamRendererFactory> {
|
||||
on {
|
||||
getLocalParticipantVideoStreamRenderer(
|
||||
any(),
|
||||
any()
|
||||
)
|
||||
} doAnswer { mockVideoStreamRenderer }
|
||||
}
|
||||
|
||||
val videoViewManager =
|
||||
VideoViewManager(mockCallingSDKWrapper, mockContext, mockVideoStreamRendererHelper)
|
||||
|
||||
// act
|
||||
videoViewManager.updateLocalVideoRenderer("345")
|
||||
val localVideoView = videoViewManager.getLocalVideoRenderer("345")
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(localVideoView, mockVideoStreamRendererView)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun videoViewManager_getRemoteVideoStreamRenderer_when_calledWithValidIDs_then_returnView() {
|
||||
// arrange
|
||||
val mockVideoStream = mock<RemoteVideoStream> {
|
||||
on { id } doAnswer { 111 }
|
||||
on { mediaStreamType } doAnswer { MediaStreamType.VIDEO }
|
||||
}
|
||||
val mockRemoteParticipant = mock<RemoteParticipant> {
|
||||
on { videoStreams } doAnswer { listOf(mockVideoStream) }
|
||||
}
|
||||
|
||||
val remoteParticipantMap: MutableMap<String, RemoteParticipant> = mutableMapOf()
|
||||
remoteParticipantMap["user"] = mockRemoteParticipant
|
||||
|
||||
val mockCallingSDKWrapper = mock<CallingSDKWrapper> {
|
||||
on { getRemoteParticipantsMap() } doAnswer { remoteParticipantMap }
|
||||
}
|
||||
|
||||
val mockContext = mock<Context> {}
|
||||
|
||||
val mockVideoStreamRendererView = mock<VideoStreamRendererView> {}
|
||||
|
||||
val mockVideoStreamRenderer = mock<VideoStreamRenderer> {
|
||||
on { createView() } doAnswer { mockVideoStreamRendererView }
|
||||
}
|
||||
|
||||
val mockVideoStreamRendererHelper = mock<VideoStreamRendererFactory> {
|
||||
on {
|
||||
getRemoteParticipantVideoStreamRenderer(
|
||||
any(),
|
||||
any()
|
||||
)
|
||||
} doAnswer { mockVideoStreamRenderer }
|
||||
}
|
||||
|
||||
val videoViewManager =
|
||||
VideoViewManager(mockCallingSDKWrapper, mockContext, mockVideoStreamRendererHelper)
|
||||
|
||||
// act
|
||||
val remoteVideoView =
|
||||
videoViewManager.getRemoteVideoStreamRenderer("user", "111")
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(remoteVideoView, mockVideoStreamRendererView)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun videoViewManager_getRemoteVideoStreamRenderer_when_calledWithInValidIDs_then_returnNullView() {
|
||||
// arrange
|
||||
val mockRemoteParticipant = mock<RemoteParticipant> {}
|
||||
|
||||
val remoteParticipantMap: MutableMap<String, RemoteParticipant> = mutableMapOf()
|
||||
remoteParticipantMap["user"] = mockRemoteParticipant
|
||||
|
||||
val mockCallingSDKWrapper = mock<CallingSDKWrapper> {
|
||||
on { getRemoteParticipantsMap() } doAnswer { remoteParticipantMap }
|
||||
}
|
||||
|
||||
val mockContext = mock<Context> {}
|
||||
|
||||
val mockVideoStreamRendererHelper = mock<VideoStreamRendererFactory> {}
|
||||
|
||||
val videoViewManager =
|
||||
VideoViewManager(mockCallingSDKWrapper, mockContext, mockVideoStreamRendererHelper)
|
||||
|
||||
// act
|
||||
val remoteVideoView =
|
||||
videoViewManager.getRemoteVideoStreamRenderer("user1", "111")
|
||||
|
||||
// assert
|
||||
Assert.assertEquals(remoteVideoView, null)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,538 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.presentation.manager
|
||||
|
||||
import android.content.Context
|
||||
import com.azure.android.communication.ui.ACSBaseTestCoroutine
|
||||
import com.azure.android.communication.ui.R
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.CameraStatusHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.MeetingJoinedHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.MicStatusHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.ParticipantAddedOrRemovedHook
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.SwitchCameraStatusHook
|
||||
import com.azure.android.communication.ui.calling.redux.state.AppReduxState
|
||||
import com.azure.android.communication.ui.calling.redux.state.AudioDeviceSelectionStatus
|
||||
import com.azure.android.communication.ui.calling.redux.state.AudioOperationalStatus
|
||||
import com.azure.android.communication.ui.calling.redux.state.AudioState
|
||||
import com.azure.android.communication.ui.calling.redux.state.BluetoothState
|
||||
import com.azure.android.communication.ui.calling.redux.state.CallingState
|
||||
import com.azure.android.communication.ui.calling.redux.state.CallingStatus
|
||||
import com.azure.android.communication.ui.calling.redux.state.CameraDeviceSelectionStatus
|
||||
import com.azure.android.communication.ui.calling.redux.state.CameraOperationalStatus
|
||||
import com.azure.android.communication.ui.calling.redux.state.LocalUserState
|
||||
import com.azure.android.communication.ui.calling.redux.state.CameraState
|
||||
import com.azure.android.communication.ui.calling.redux.state.CameraTransmissionStatus
|
||||
import com.azure.android.communication.ui.calling.redux.state.RemoteParticipantsState
|
||||
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import org.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.mock
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
internal class AccessibilityAnnouncementManagerUnitTests : ACSBaseTestCoroutine() {
|
||||
@Test
|
||||
fun cameraStatusHook_message_reduxStateOn_then_returnVideoOn() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val cameraStatusHook = CameraStatusHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_setup_view_button_video_on) } doAnswer { "Video on" }
|
||||
}
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.ON,
|
||||
CameraDeviceSelectionStatus.BACK,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = cameraStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "Video on")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cameraStatusHook_message_reduxStateOff_then_returnVideoOff() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val cameraStatusHook = CameraStatusHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_setup_view_button_video_off) } doAnswer { "Video off" }
|
||||
}
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.OFF,
|
||||
CameraDeviceSelectionStatus.BACK,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = cameraStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "Video off")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cameraStatusHook_message_reduxStateOthers_then_returnEmpty() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val cameraStatusHook = CameraStatusHook()
|
||||
val mockContext = mock<Context> { }
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState =
|
||||
LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.PAUSED,
|
||||
CameraDeviceSelectionStatus.BACK,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = cameraStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cameraStatusHook_shouldTrigger_reduxStateDiffer_then_returnTrue() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState =
|
||||
LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.PAUSED,
|
||||
CameraDeviceSelectionStatus.BACK,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
val cameraStatusHook = CameraStatusHook()
|
||||
|
||||
// Act
|
||||
val result = cameraStatusHook.shouldTrigger(AppReduxState(""), reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun cameraStatusHook_shouldTrigger_reduxStateSame_then_returnFalse() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState =
|
||||
LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.PAUSED,
|
||||
CameraDeviceSelectionStatus.BACK,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
val cameraStatusHook = CameraStatusHook()
|
||||
|
||||
// Act
|
||||
val result = cameraStatusHook.shouldTrigger(reduxState, reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun micStatusHook_message_reduxStateOn_then_returnMicOn() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val micStatusHook = MicStatusHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_setup_view_button_mic_on) } doAnswer { "Mic on" }
|
||||
}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
mock {},
|
||||
AudioState(
|
||||
AudioOperationalStatus.ON,
|
||||
AudioDeviceSelectionStatus.BLUETOOTH_SCO_REQUESTED,
|
||||
BluetoothState(true, "")
|
||||
),
|
||||
"",
|
||||
""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = micStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "Mic on")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun micStatusHook_message_reduxStateOff_then_returnVideoOff() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val micStatusHook = MicStatusHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_setup_view_button_mic_off) } doAnswer { "Mic off" }
|
||||
}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
mock {},
|
||||
AudioState(
|
||||
AudioOperationalStatus.OFF,
|
||||
AudioDeviceSelectionStatus.BLUETOOTH_SCO_REQUESTED,
|
||||
BluetoothState(true, "")
|
||||
),
|
||||
"",
|
||||
""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = micStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "Mic off")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun micStatusHook_message_reduxStateOthers_then_returnEmpty() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val micStatusHook = MicStatusHook()
|
||||
val mockContext = mock<Context> { }
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
mock {},
|
||||
AudioState(
|
||||
AudioOperationalStatus.PENDING,
|
||||
AudioDeviceSelectionStatus.BLUETOOTH_SCO_REQUESTED,
|
||||
BluetoothState(true, "")
|
||||
),
|
||||
"",
|
||||
""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = micStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun micStatusHook_shouldTrigger_reduxStateDiffer_then_returnTrue() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val micStatusHook = MicStatusHook()
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
mock {},
|
||||
AudioState(
|
||||
AudioOperationalStatus.PENDING,
|
||||
AudioDeviceSelectionStatus.BLUETOOTH_SCO_REQUESTED,
|
||||
BluetoothState(true, "")
|
||||
),
|
||||
"",
|
||||
""
|
||||
)
|
||||
|
||||
// Act
|
||||
val result = micStatusHook.shouldTrigger(AppReduxState(""), reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun micStatusHook_shouldTrigger_reduxStateSame_then_returnFalse() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val micStatusHook = MicStatusHook()
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
mock {},
|
||||
AudioState(
|
||||
AudioOperationalStatus.PENDING,
|
||||
AudioDeviceSelectionStatus.BLUETOOTH_SCO_REQUESTED,
|
||||
BluetoothState(true, "")
|
||||
),
|
||||
"",
|
||||
""
|
||||
)
|
||||
|
||||
// Act
|
||||
val result = micStatusHook.shouldTrigger(reduxState, reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun switchCameraStatusHook_message_reduxStateFront_then_returnFrontCamera() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val switchCameraStatusHook = SwitchCameraStatusHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_switch_camera_button_front) } doAnswer { "Switch to Front Camera" }
|
||||
}
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.ON,
|
||||
CameraDeviceSelectionStatus.FRONT,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = switchCameraStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "Switch to Front Camera")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun switchCameraStatusHook_message_reduxStateBack_then_returnBackCamera() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val switchCameraStatusHook = SwitchCameraStatusHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_switch_camera_button_back) } doAnswer { "Switch to Back Camera" }
|
||||
}
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.ON,
|
||||
CameraDeviceSelectionStatus.BACK,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = switchCameraStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "Switch to Back Camera")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun switchCameraStatusHook_message_reduxStateOthers_then_returnEmpty() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val switchCameraStatusHook = SwitchCameraStatusHook()
|
||||
val mockContext = mock<Context> { }
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.ON,
|
||||
CameraDeviceSelectionStatus.SWITCHING,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val message = switchCameraStatusHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun switchCameraStatusHook_shouldTrigger_reduxStateSame_then_returnFalse() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val switchCameraStatusHook = SwitchCameraStatusHook()
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.ON,
|
||||
CameraDeviceSelectionStatus.SWITCHING,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val result = switchCameraStatusHook.shouldTrigger(reduxState, reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun switchCameraStatusHook_shouldTrigger_reduxStateDiffer_then_returnTrue() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val switchCameraStatusHook = SwitchCameraStatusHook()
|
||||
val mockAudioState = mock<AudioState> {}
|
||||
reduxState.localParticipantState = LocalUserState(
|
||||
CameraState(
|
||||
CameraOperationalStatus.ON,
|
||||
CameraDeviceSelectionStatus.SWITCHING,
|
||||
CameraTransmissionStatus.LOCAL
|
||||
),
|
||||
mockAudioState, "", ""
|
||||
)
|
||||
|
||||
// Act
|
||||
val result = switchCameraStatusHook.shouldTrigger(AppReduxState(""), reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun meetingJoinedHook_shouldTrigger_reduxStateDiffer_then_returnTrue() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val meetingJoinedHook = MeetingJoinedHook()
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
|
||||
// Act
|
||||
val result = meetingJoinedHook.shouldTrigger(AppReduxState(""), reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun meetingJoinedHook_shouldTrigger_reduxStateSame_then_returnFalse() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val meetingJoinedHook = MeetingJoinedHook()
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
|
||||
// Act
|
||||
val result = meetingJoinedHook.shouldTrigger(reduxState, reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun meetingJoinedHook_message_reduxStateAny_then_returnJoined() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val meetingJoinedHook = MeetingJoinedHook()
|
||||
val mockContext = mock<Context> {
|
||||
on { getString(R.string.azure_communication_ui_calling_accessibility_meeting_connected) } doAnswer { "You have joined the call" }
|
||||
}
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
|
||||
// Act
|
||||
val message = meetingJoinedHook.message(reduxState, reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "You have joined the call")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun participantAddedOrRemovedHook_shouldTrigger_reduxStateDiffer_then_returnTrue() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val meetingJoinedHook = MeetingJoinedHook()
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
reduxState.remoteParticipantState =
|
||||
RemoteParticipantsState(mapOf(Pair("a", mock { })), 5000)
|
||||
// Act
|
||||
val result = meetingJoinedHook.shouldTrigger(AppReduxState(""), reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun participantAddedOrRemovedHook_shouldTrigger_reduxStateSame_then_returnFalse() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val meetingJoinedHook = MeetingJoinedHook()
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
reduxState.remoteParticipantState =
|
||||
RemoteParticipantsState(mapOf(Pair("a", mock { })), 5000)
|
||||
// Act
|
||||
val result = meetingJoinedHook.shouldTrigger(reduxState, reduxState)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(result, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun participantAddedOrRemovedHook_message_reduxStateHasParticipants_then_returnJoinedMessage() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val participantAddedOrRemovedHook = ParticipantAddedOrRemovedHook()
|
||||
val mockContext = mock<Context> {
|
||||
on {
|
||||
getString(
|
||||
R.string.azure_communication_ui_calling_accessibility_user_added,
|
||||
"user"
|
||||
)
|
||||
} doAnswer { "user has joined the meeting" }
|
||||
}
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
reduxState.remoteParticipantState = RemoteParticipantsState(
|
||||
mapOf(
|
||||
Pair(
|
||||
"a",
|
||||
mock {
|
||||
on { displayName } doAnswer { "user" }
|
||||
}
|
||||
)
|
||||
),
|
||||
5000
|
||||
)
|
||||
|
||||
// Act
|
||||
val message =
|
||||
participantAddedOrRemovedHook.message(AppReduxState(""), reduxState, mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "user has joined the meeting")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun participantAddedOrRemovedHook_message_reduxStateHasRemovedParticipants_then_returnLeftMessage() {
|
||||
// Arrange
|
||||
val reduxState = AppReduxState("")
|
||||
val participantAddedOrRemovedHook = ParticipantAddedOrRemovedHook()
|
||||
val mockContext = mock<Context> {
|
||||
on {
|
||||
getString(
|
||||
R.string.azure_communication_ui_calling_accessibility_user_left,
|
||||
"user"
|
||||
)
|
||||
} doAnswer { "user has left the meeting" }
|
||||
}
|
||||
reduxState.callState = CallingState(CallingStatus.CONNECTED)
|
||||
reduxState.remoteParticipantState = RemoteParticipantsState(
|
||||
mapOf(
|
||||
Pair(
|
||||
"a",
|
||||
mock {
|
||||
on { displayName } doAnswer { "user" }
|
||||
}
|
||||
)
|
||||
),
|
||||
5000
|
||||
)
|
||||
|
||||
// Act
|
||||
val message =
|
||||
participantAddedOrRemovedHook.message(reduxState, AppReduxState(""), mockContext)
|
||||
|
||||
// Assert
|
||||
Assert.assertEquals(message, "user has left the meeting")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
package com.azure.android.communication.ui.presentation.manager
|
||||
|
||||
import com.azure.android.communication.ui.calling.presentation.manager.LifecycleManagerImpl
|
||||
import com.azure.android.communication.ui.calling.redux.AppStore
|
||||
import com.azure.android.communication.ui.calling.redux.action.LifecycleAction
|
||||
import com.azure.android.communication.ui.calling.redux.state.ReduxState
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.argThat
|
||||
import org.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
|
||||
@RunWith(MockitoJUnitRunner::class)
|
||||
internal class LifeCycleManagerUnitTests {
|
||||
@Test
|
||||
fun lifecycleManager_pause_then_sendEnterBackgroundTriggered() {
|
||||
// Arrange
|
||||
val mockAppStore = mock<AppStore<ReduxState>> {
|
||||
on { dispatch(any()) } doAnswer { }
|
||||
}
|
||||
val lifecycleManagerImpl = LifecycleManagerImpl(mockAppStore)
|
||||
|
||||
// Act
|
||||
lifecycleManagerImpl.pause()
|
||||
|
||||
// Assert
|
||||
verify(mockAppStore, times(1)).dispatch(
|
||||
argThat { action ->
|
||||
action is LifecycleAction.EnterBackgroundTriggered
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun lifecycleManager_resume_then_sendEnterForegroundTriggered() {
|
||||
// Arrange
|
||||
val mockAppStore = mock<AppStore<ReduxState>> {
|
||||
on { dispatch(any()) } doAnswer { }
|
||||
}
|
||||
val lifecycleManagerImpl = LifecycleManagerImpl(mockAppStore)
|
||||
|
||||
// Act
|
||||
lifecycleManagerImpl.resume()
|
||||
|
||||
// Assert
|
||||
verify(mockAppStore, times(1)).dispatch(
|
||||
argThat { action ->
|
||||
action is LifecycleAction.EnterForegroundTriggered
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче