diff --git a/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt b/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt index 4911ab50b5..fc8f2c175b 100644 --- a/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt +++ b/appnav/src/main/kotlin/io/element/android/appnav/di/RoomComponentFactory.kt @@ -9,6 +9,6 @@ package io.element.android.appnav.di import io.element.android.libraries.matrix.api.room.JoinedRoom -interface RoomComponentFactory { +fun interface RoomComponentFactory { fun create(room: JoinedRoom): Any } diff --git a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt index 404bae44d1..37a78fd727 100644 --- a/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt +++ b/features/analytics/api/src/main/kotlin/io/element/android/features/analytics/api/AnalyticsEntryPoint.kt @@ -9,4 +9,4 @@ package io.element.android.features.analytics.api import io.element.android.libraries.architecture.SimpleFeatureEntryPoint -interface AnalyticsEntryPoint : SimpleFeatureEntryPoint +fun interface AnalyticsEntryPoint : SimpleFeatureEntryPoint diff --git a/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt b/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt index 0175cdf247..b6f7680b38 100644 --- a/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt +++ b/features/changeroommemberroles/api/src/main/kotlin/io/element/android/features/changeroommemberroes/api/ChangeRoomMemberRolesEntryPoint.kt @@ -14,7 +14,7 @@ import io.element.android.libraries.architecture.NodeInputs import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.JoinedRoom -interface ChangeRoomMemberRolesEntryPoint : FeatureEntryPoint { +fun interface ChangeRoomMemberRolesEntryPoint : FeatureEntryPoint { fun builder(parentNode: Node, buildContext: BuildContext): Builder interface Builder { diff --git a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt index a6d0ed6a51..cf43874b10 100644 --- a/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt +++ b/features/changeroommemberroles/impl/src/main/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenter.kt @@ -55,7 +55,7 @@ class ChangeRolesPresenter( private val analyticsService: AnalyticsService, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(role: RoomMember.Role): ChangeRolesPresenter } diff --git a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt index a5b2da566c..e5e22b8846 100644 --- a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt +++ b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/ChangeRolesPresenterTest.kt @@ -37,7 +37,6 @@ import kotlinx.collections.immutable.toPersistentMap import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import kotlin.collections.plus class ChangeRolesPresenterTest { @Test @@ -556,18 +555,18 @@ class ChangeRolesPresenterTest { users = pairs.associate { (userId, role) -> userId to role.powerLevel }.toPersistentMap() ) } - - private fun TestScope.createChangeRolesPresenter( - role: RoomMember.Role = RoomMember.Role.Admin, - room: FakeJoinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {})), - dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), - analyticsService: FakeAnalyticsService = FakeAnalyticsService(), - ): ChangeRolesPresenter { - return ChangeRolesPresenter( - role = role, - room = room, - dispatchers = dispatchers, - analyticsService = analyticsService, - ) - } +} + +internal fun TestScope.createChangeRolesPresenter( + role: RoomMember.Role = RoomMember.Role.Admin, + room: FakeJoinedRoom = FakeJoinedRoom(baseRoom = FakeBaseRoom(updateMembersResult = {})), + dispatchers: CoroutineDispatchers = testCoroutineDispatchers(), + analyticsService: FakeAnalyticsService = FakeAnalyticsService(), +): ChangeRolesPresenter { + return ChangeRolesPresenter( + role = role, + room = room, + dispatchers = dispatchers, + analyticsService = analyticsService, + ) } diff --git a/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt new file mode 100644 index 0000000000..5f68fe5970 --- /dev/null +++ b/features/changeroommemberroles/impl/src/test/kotlin/io/element/android/features/changeroommemberroles/impl/DefaultChangeRoomMemberRolesEntyPointTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.changeroommemberroles.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.changeroommemberroes.api.ChangeRoomMemberRolesListType +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultChangeRoomMemberRolesEntyPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultChangeRoomMemberRolesEntyPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ChangeRoomMemberRolesRootNode( + buildContext = buildContext, + plugins = plugins, + roomComponentFactory = { }, + ) + } + val room = FakeJoinedRoom() + val listType = ChangeRoomMemberRolesListType.Admins + val result = entryPoint.builder(parentNode, BuildContext.root(null)) + .room(FakeJoinedRoom()) + .listType(listType) + .build() + assertThat(result).isInstanceOf(ChangeRoomMemberRolesRootNode::class.java) + // Search for the Inputs plugin + val input = result.plugins.filterIsInstance().single() + assertThat(input.joinedRoom.roomId).isEqualTo(room.roomId) + assertThat(input.listType).isEqualTo(listType) + } +} diff --git a/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt new file mode 100644 index 0000000000..6c6790adff --- /dev/null +++ b/features/createroom/impl/src/test/kotlin/io/element/android/features/createroom/impl/DefaultCreateRoomEntryPointTest.kt @@ -0,0 +1,40 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.createroom.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.createroom.api.CreateRoomEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultCreateRoomEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultCreateRoomEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + CreateRoomFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : CreateRoomEntryPoint.Callback { + override fun onRoomCreated(roomId: RoomId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt index 1383bdde21..e8edea3ab6 100644 --- a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/AccountDeactivationPresenterTest.kt @@ -149,9 +149,10 @@ class AccountDeactivationPresenterTest { } } - private fun createPresenter( - matrixClient: MatrixClient = FakeMatrixClient(), - ) = AccountDeactivationPresenter( - matrixClient = matrixClient, - ) } + +internal fun createPresenter( + matrixClient: MatrixClient = FakeMatrixClient(), +) = AccountDeactivationPresenter( + matrixClient = matrixClient, +) diff --git a/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt new file mode 100644 index 0000000000..e055b4a979 --- /dev/null +++ b/features/deactivation/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultAccountDeactivationEntryPointTest.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultAccountDeactivationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultAccountDeactivationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + AccountDeactivationNode( + buildContext = buildContext, + plugins = plugins, + presenter = createPresenter(), + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(AccountDeactivationNode::class.java) + } +} diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt new file mode 100644 index 0000000000..3a4a2ea334 --- /dev/null +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueEntryPointTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.ftue.impl + +import android.content.Context +import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultFtueEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultFtueEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + FtueFlowNode( + buildContext = buildContext, + plugins = plugins, + analyticsEntryPoint = { _, _ -> lambdaError() }, + ftueState = createDefaultFtueService(), + analyticsService = FakeAnalyticsService(), + lockScreenEntryPoint = object : LockScreenEntryPoint { + override fun nodeBuilder( + parentNode: com.bumble.appyx.core.node.Node, + buildContext: BuildContext, + navTarget: LockScreenEntryPoint.Target + ): LockScreenEntryPoint.NodeBuilder { + lambdaError() + } + + override fun pinUnlockIntent(context: Context): Intent { + lambdaError() + } + }, + ) + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .build() + assertThat(result).isInstanceOf(FtueFlowNode::class.java) + } +} diff --git a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt index 4a05433e5e..1a4a8738dc 100644 --- a/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt +++ b/features/ftue/impl/src/test/kotlin/io/element/android/features/ftue/impl/DefaultFtueServiceTest.kt @@ -226,22 +226,22 @@ class DefaultFtueServiceTest { resetPermissionLambda.assertions().isCalledOnce() .with(value("android.permission.POST_NOTIFICATIONS")) } - - private fun TestScope.createDefaultFtueService( - sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), - analyticsService: AnalyticsService = FakeAnalyticsService(), - permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(permissionGranted = false), - lockScreenService: LockScreenService = FakeLockScreenService(), - sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), - // First version where notification permission is required - sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, - ) = DefaultFtueService( - sessionCoroutineScope = backgroundScope, - sessionVerificationService = sessionVerificationService, - sdkVersionProvider = FakeBuildVersionSdkIntProvider(sdkIntVersion), - analyticsService = analyticsService, - permissionStateProvider = permissionStateProvider, - lockScreenService = lockScreenService, - sessionPreferencesStore = sessionPreferencesStore, - ) } + +internal fun TestScope.createDefaultFtueService( + sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(), + analyticsService: AnalyticsService = FakeAnalyticsService(), + permissionStateProvider: PermissionStateProvider = FakePermissionStateProvider(permissionGranted = false), + lockScreenService: LockScreenService = FakeLockScreenService(), + sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(), + // First version where notification permission is required + sdkIntVersion: Int = Build.VERSION_CODES.TIRAMISU, +) = DefaultFtueService( + sessionCoroutineScope = backgroundScope, + sessionVerificationService = sessionVerificationService, + sdkVersionProvider = FakeBuildVersionSdkIntProvider(sdkIntVersion), + analyticsService = analyticsService, + permissionStateProvider = permissionStateProvider, + lockScreenService = lockScreenService, + sessionPreferencesStore = sessionPreferencesStore, +) diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt new file mode 100644 index 0000000000..0eacd792c7 --- /dev/null +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/DefaultHomeEntryPointTest.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.home.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.home.api.HomeEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultHomeEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultHomeEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + HomeFlowNode( + buildContext = buildContext, + plugins = plugins, + matrixClient = FakeMatrixClient(), + presenter = createHomePresenter(), + inviteFriendsUseCase = { lambdaError() }, + analyticsService = FakeAnalyticsService(), + acceptDeclineInviteView = { _, _, _, _ -> lambdaError() }, + directLogoutView = { _ -> lambdaError() }, + reportRoomEntryPoint = { _, _, _ -> lambdaError() }, + declineInviteAndBlockUserEntryPoint = { _, _, _ -> lambdaError() }, + changeRoomMemberRolesEntryPoint = { _, _ -> lambdaError() }, + leaveRoomRenderer = { _, _, _ -> lambdaError() }, + ) + } + val callback = object : HomeEntryPoint.Callback { + override fun onRoomClick(roomId: RoomId) = lambdaError() + override fun onStartChatClick() = lambdaError() + override fun onSettingsClick() = lambdaError() + override fun onSetUpRecoveryClick() = lambdaError() + override fun onSessionConfirmRecoveryKeyClick() = lambdaError() + override fun onRoomSettingsClick(roomId: RoomId) = lambdaError() + override fun onReportBugClick() = lambdaError() + override fun onLogoutForNativeSlidingSyncMigrationNeeded() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(HomeFlowNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt index 57f270d3d3..a84dbd6309 100644 --- a/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt +++ b/features/home/impl/src/test/kotlin/io/element/android/features/home/impl/HomePresenterTest.kt @@ -175,24 +175,24 @@ class HomePresenterTest { assertThat(finalState.showNavigationBar).isFalse() } } - - private fun createHomePresenter( - client: MatrixClient = FakeMatrixClient(), - syncService: SyncService = FakeSyncService(), - snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), - rageshakeFeatureAvailability: RageshakeFeatureAvailability = RageshakeFeatureAvailability { flowOf(false) }, - indicatorService: IndicatorService = FakeIndicatorService(), - featureFlagService: FeatureFlagService = FakeFeatureFlagService(), - homeSpacesPresenter: Presenter = Presenter { aHomeSpacesState() }, - ) = HomePresenter( - client = client, - syncService = syncService, - snackbarDispatcher = snackbarDispatcher, - indicatorService = indicatorService, - logoutPresenter = { aDirectLogoutState() }, - roomListPresenter = { aRoomListState() }, - homeSpacesPresenter = homeSpacesPresenter, - rageshakeFeatureAvailability = rageshakeFeatureAvailability, - featureFlagService = featureFlagService, - ) } + +internal fun createHomePresenter( + client: MatrixClient = FakeMatrixClient(), + syncService: SyncService = FakeSyncService(), + snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), + rageshakeFeatureAvailability: RageshakeFeatureAvailability = RageshakeFeatureAvailability { flowOf(false) }, + indicatorService: IndicatorService = FakeIndicatorService(), + featureFlagService: FeatureFlagService = FakeFeatureFlagService(), + homeSpacesPresenter: Presenter = Presenter { aHomeSpacesState() }, +) = HomePresenter( + client = client, + syncService = syncService, + snackbarDispatcher = snackbarDispatcher, + indicatorService = indicatorService, + logoutPresenter = { aDirectLogoutState() }, + roomListPresenter = { aRoomListState() }, + homeSpacesPresenter = homeSpacesPresenter, + rageshakeFeatureAvailability = rageshakeFeatureAvailability, + featureFlagService = featureFlagService, +) diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt index 78be5ebd16..a098443c45 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/acceptdecline/AcceptDeclineInviteView.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import io.element.android.libraries.matrix.api.core.RoomId -interface AcceptDeclineInviteView { +fun interface AcceptDeclineInviteView { @Composable fun Render( state: AcceptDeclineInviteState, diff --git a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt index 27080ee354..8517fe2786 100644 --- a/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt +++ b/features/invite/api/src/main/kotlin/io/element/android/features/invite/api/declineandblock/DeclineInviteAndBlockEntryPoint.kt @@ -12,6 +12,6 @@ import com.bumble.appyx.core.node.Node import io.element.android.features.invite.api.InviteData import io.element.android.libraries.architecture.FeatureEntryPoint -interface DeclineInviteAndBlockEntryPoint : FeatureEntryPoint { +fun interface DeclineInviteAndBlockEntryPoint : FeatureEntryPoint { fun createNode(parentNode: Node, buildContext: BuildContext, inviteData: InviteData): Node } diff --git a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt index 527a467ba9..f9639f69fe 100644 --- a/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt +++ b/features/invite/impl/src/main/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenter.kt @@ -35,7 +35,7 @@ class DeclineAndBlockPresenter( private val snackbarDispatcher: SnackbarDispatcher, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(inviteData: InviteData): DeclineAndBlockPresenter } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt index c5d2f53c92..ae8893f829 100644 --- a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DeclineAndBlockPresenterTest.kt @@ -11,6 +11,7 @@ import com.google.common.truth.Truth.assertThat import io.element.android.features.invite.api.InviteData import io.element.android.features.invite.impl.DeclineInvite import io.element.android.features.invite.impl.fake.FakeDeclineInvite +import io.element.android.features.invite.test.anInviteData import io.element.android.libraries.architecture.AsyncAction import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher import io.element.android.libraries.matrix.api.core.RoomId @@ -148,28 +149,16 @@ class DeclineAndBlockPresenterTest { .isCalledOnce() .with(value(A_ROOM_ID), value(true), value(false), value("")) } - - private fun anInviteData( - roomId: RoomId = A_ROOM_ID, - name: String = A_ROOM_NAME, - isDm: Boolean = false, - ): InviteData { - return InviteData( - roomId = roomId, - roomName = name, - isDm = isDm, - ) - } - - private fun createDeclineAndBlockPresenter( - inviteData: InviteData = anInviteData(), - declineInvite: DeclineInvite = FakeDeclineInvite(), - snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), - ): DeclineAndBlockPresenter { - return DeclineAndBlockPresenter( - inviteData = inviteData, - declineInvite = declineInvite, - snackbarDispatcher = snackbarDispatcher, - ) - } +} + +internal fun createDeclineAndBlockPresenter( + inviteData: InviteData = anInviteData(), + declineInvite: DeclineInvite = FakeDeclineInvite(), + snackbarDispatcher: SnackbarDispatcher = SnackbarDispatcher(), +): DeclineAndBlockPresenter { + return DeclineAndBlockPresenter( + inviteData = inviteData, + declineInvite = declineInvite, + snackbarDispatcher = snackbarDispatcher, + ) } diff --git a/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt new file mode 100644 index 0000000000..a3016a785c --- /dev/null +++ b/features/invite/impl/src/test/kotlin/io/element/android/features/invite/impl/declineandblock/DefaultDeclineAndBlockEntryPointTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.invite.impl.declineandblock + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.invite.test.anInviteData +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultDeclineAndBlockEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultDeclineAndBlockEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + DeclineAndBlockNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { inviteData -> createDeclineAndBlockPresenter() } + ) + } + val inviteData = anInviteData() + val result = entryPoint.createNode( + parentNode = parentNode, + buildContext = BuildContext.root(null), + inviteData = inviteData + ) + assertThat(result).isInstanceOf(DeclineAndBlockNode::class.java) + assertThat(result.plugins).contains(DeclineAndBlockNode.Inputs(inviteData)) + } +} diff --git a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt index 5fe12a42d9..3200d75f78 100644 --- a/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt +++ b/features/joinroom/impl/src/main/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenter.kt @@ -70,7 +70,7 @@ class JoinRoomPresenter( private val buildMeta: BuildMeta, private val seenInvitesStore: SeenInvitesStore, ) : Presenter { - interface Factory { + fun interface Factory { fun create( roomId: RoomId, roomIdOrAlias: RoomIdOrAlias, diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt new file mode 100644 index 0000000000..aa81b0c51b --- /dev/null +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/DefaultJoinRoomEntryPointTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.joinroom.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import im.vector.app.features.analytics.plan.JoinedRoom +import io.element.android.features.invite.api.InviteData +import io.element.android.features.invite.api.declineandblock.DeclineInviteAndBlockEntryPoint +import io.element.android.features.joinroom.api.JoinRoomEntryPoint +import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith +import java.util.Optional + +@RunWith(AndroidJUnit4::class) +class DefaultJoinRoomEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultJoinRoomEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + JoinRoomFlowNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _, _, _, _ -> createJoinRoomPresenter() }, + acceptDeclineInviteView = { _, _, _, _ -> lambdaError() }, + declineAndBlockEntryPoint = object : DeclineInviteAndBlockEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext, inviteData: InviteData) = lambdaError() + } + + ) + } + val inputs = JoinRoomEntryPoint.Inputs( + roomId = A_ROOM_ID, + roomIdOrAlias = A_ROOM_ID.toRoomIdOrAlias(), + roomDescription = Optional.ofNullable(null), + serverNames = emptyList(), + trigger = JoinedRoom.Trigger.RoomDirectory, + ) + val result = entryPoint.createNode(parentNode, BuildContext.root(null), inputs) + assertThat(result).isInstanceOf(JoinRoomFlowNode::class.java) + assertThat(result.plugins).contains(inputs) + } +} diff --git a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt index cabab56802..a06a80ab58 100644 --- a/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt +++ b/features/joinroom/impl/src/test/kotlin/io/element/android/features/joinroom/impl/JoinRoomPresenterTest.kt @@ -1042,39 +1042,6 @@ class JoinRoomPresenterTest { } } - private fun createJoinRoomPresenter( - roomId: RoomId = A_ROOM_ID, - roomDescription: Optional = Optional.empty(), - serverNames: List = emptyList(), - trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite, - matrixClient: MatrixClient = FakeMatrixClient(), - joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> - Result.success(Unit) - }, - knockRoom: KnockRoom = FakeKnockRoom(), - cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(), - forgetRoom: ForgetRoom = FakeForgetRoom(), - buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"), - acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() }, - seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), - ): JoinRoomPresenter { - return JoinRoomPresenter( - roomId = roomId, - roomIdOrAlias = roomId.toRoomIdOrAlias(), - roomDescription = roomDescription, - serverNames = serverNames, - trigger = trigger, - matrixClient = matrixClient, - joinRoom = FakeJoinRoom(joinRoomLambda), - knockRoom = knockRoom, - cancelKnockRoom = cancelKnockRoom, - forgetRoom = forgetRoom, - buildMeta = buildMeta, - acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, - seenInvitesStore = seenInvitesStore, - ) - } - private fun aRoomDescription( roomId: RoomId = A_ROOM_ID, name: String? = A_ROOM_NAME, @@ -1095,3 +1062,36 @@ class JoinRoomPresenterTest { ) } } + +internal fun createJoinRoomPresenter( + roomId: RoomId = A_ROOM_ID, + roomDescription: Optional = Optional.empty(), + serverNames: List = emptyList(), + trigger: JoinedRoom.Trigger = JoinedRoom.Trigger.Invite, + matrixClient: MatrixClient = FakeMatrixClient(), + joinRoomLambda: (RoomIdOrAlias, List, JoinedRoom.Trigger) -> Result = { _, _, _ -> + Result.success(Unit) + }, + knockRoom: KnockRoom = FakeKnockRoom(), + cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(), + forgetRoom: ForgetRoom = FakeForgetRoom(), + buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"), + acceptDeclineInvitePresenter: Presenter = Presenter { anAcceptDeclineInviteState() }, + seenInvitesStore: SeenInvitesStore = InMemorySeenInvitesStore(), +): JoinRoomPresenter { + return JoinRoomPresenter( + roomId = roomId, + roomIdOrAlias = roomId.toRoomIdOrAlias(), + roomDescription = roomDescription, + serverNames = serverNames, + trigger = trigger, + matrixClient = matrixClient, + joinRoom = FakeJoinRoom(joinRoomLambda), + knockRoom = knockRoom, + cancelKnockRoom = cancelKnockRoom, + forgetRoom = forgetRoom, + buildMeta = buildMeta, + acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, + seenInvitesStore = seenInvitesStore, + ) +} diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt new file mode 100644 index 0000000000..2a4196da9b --- /dev/null +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/DefaultKnockRequestsListEntryPointTest.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.knockrequests.impl.list + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultKnockRequestsListEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultKnockRequestsListEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + KnockRequestsListNode( + buildContext = buildContext, + plugins = plugins, + presenter = createKnockRequestsListPresenter(), + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(KnockRequestsListNode::class.java) + } +} diff --git a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt index 2d33642a06..18269e06f3 100644 --- a/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt +++ b/features/knockrequests/impl/src/test/kotlin/io/element/android/features/knockrequests/impl/list/KnockRequestsListPresenterTest.kt @@ -286,19 +286,19 @@ class KnockRequestsListPresenterTest { assert(acceptFailureLambda).isCalledOnce() assert(acceptSuccessLambda).isCalledOnce() } - - private fun TestScope.createKnockRequestsListPresenter( - canAccept: Boolean = true, - canDecline: Boolean = true, - canBan: Boolean = true, - knockRequestsFlow: Flow> = flowOf(emptyList()) - ): KnockRequestsListPresenter { - val knockRequestsService = KnockRequestsService( - knockRequestsFlow = knockRequestsFlow, - coroutineScope = backgroundScope, - isKnockFeatureEnabledFlow = flowOf(true), - permissionsFlow = flowOf(KnockRequestPermissions(canAccept, canDecline, canBan)), - ) - return KnockRequestsListPresenter(knockRequestsService = knockRequestsService) - } +} + +internal fun TestScope.createKnockRequestsListPresenter( + canAccept: Boolean = true, + canDecline: Boolean = true, + canBan: Boolean = true, + knockRequestsFlow: Flow> = flowOf(emptyList()) +): KnockRequestsListPresenter { + val knockRequestsService = KnockRequestsService( + knockRequestsFlow = knockRequestsFlow, + coroutineScope = backgroundScope, + isKnockFeatureEnabledFlow = flowOf(true), + permissionsFlow = flowOf(KnockRequestPermissions(canAccept, canDecline, canBan)), + ) + return KnockRequestsListPresenter(knockRequestsService = knockRequestsService) } diff --git a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt index 8bd6fe830b..80252a83a6 100644 --- a/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt +++ b/features/leaveroom/api/src/main/kotlin/io/element/android/features/leaveroom/api/LeaveRoomRenderer.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import io.element.android.libraries.matrix.api.core.RoomId -interface LeaveRoomRenderer { +fun interface LeaveRoomRenderer { @Composable fun Render( state: LeaveRoomState, diff --git a/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt new file mode 100644 index 0000000000..730760cb93 --- /dev/null +++ b/features/licenses/impl/src/test/kotlin/io/element/android/features/licenses/impl/DefaultOpenSourcesLicensesEntryPointTest.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.licenses.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultOpenSourcesLicensesEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultOpenSourcesLicensesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + DependenciesFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val result = entryPoint.getNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(DependenciesFlowNode::class.java) + } +} diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt index 410214ec88..82e54ba977 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/common/permissions/PermissionsPresenter.kt @@ -10,7 +10,7 @@ package io.element.android.features.location.impl.common.permissions import io.element.android.libraries.architecture.Presenter interface PermissionsPresenter : Presenter { - interface Factory { + fun interface Factory { fun create(permissions: List): PermissionsPresenter } } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt index 15f858ecff..f8d78b96e2 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/send/SendLocationPresenter.kt @@ -47,7 +47,7 @@ class SendLocationPresenter( private val buildMeta: BuildMeta, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(timelineMode: Timeline.Mode): SendLocationPresenter } diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt index 053f1864de..c0a6c5b6ad 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationNode.kt @@ -25,10 +25,10 @@ import io.element.android.services.analytics.api.AnalyticsService @ContributesNode(RoomScope::class) @Inject class ShowLocationNode( - presenterFactory: ShowLocationPresenter.Factory, - analyticsService: AnalyticsService, @Assisted buildContext: BuildContext, @Assisted plugins: List, + presenterFactory: ShowLocationPresenter.Factory, + analyticsService: AnalyticsService, ) : Node(buildContext, plugins = plugins) { init { lifecycle.subscribe( diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt index af89331c6f..b304505367 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt @@ -28,14 +28,14 @@ import io.element.android.libraries.core.meta.BuildMeta @Inject class ShowLocationPresenter( + @Assisted private val location: Location, + @Assisted private val description: String?, permissionsPresenterFactory: PermissionsPresenter.Factory, private val locationActions: LocationActions, private val buildMeta: BuildMeta, - @Assisted private val location: Location, - @Assisted private val description: String? ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(location: Location, description: String?): ShowLocationPresenter } diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt new file mode 100644 index 0000000000..705d2a293c --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/send/DefaultSendLocationEntryPointTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.send + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.impl.common.actions.FakeLocationActions +import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.features.messages.test.FakeMessageComposerContext +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSendLocationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultSendLocationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + SendLocationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { timelineMode: Timeline.Mode -> + SendLocationPresenter( + permissionsPresenterFactory = { FakePermissionsPresenter() }, + room = FakeJoinedRoom(), + timelineMode = timelineMode, + analyticsService = FakeAnalyticsService(), + messageComposerContext = FakeMessageComposerContext(), + locationActions = FakeLocationActions(), + buildMeta = aBuildMeta(), + ) + }, + analyticsService = FakeAnalyticsService(), + ) + } + val timelineMode = Timeline.Mode.Live + val result = entryPoint.builder(timelineMode) + .build(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(SendLocationNode::class.java) + assertThat(result.plugins).contains(SendLocationNode.Inputs(timelineMode)) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt new file mode 100644 index 0000000000..046f286550 --- /dev/null +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/DefaultShowLocationEntryPointTest.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.location.impl.show + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.location.api.Location +import io.element.android.features.location.api.ShowLocationEntryPoint +import io.element.android.features.location.impl.common.actions.FakeLocationActions +import io.element.android.features.location.impl.common.permissions.FakePermissionsPresenter +import io.element.android.libraries.matrix.test.core.aBuildMeta +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultShowLocationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultShowLocationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ShowLocationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { location: Location, description: String? -> + ShowLocationPresenter( + permissionsPresenterFactory = { FakePermissionsPresenter() }, + locationActions = FakeLocationActions(), + buildMeta = aBuildMeta(), + location = location, + description = description, + ) + }, + analyticsService = FakeAnalyticsService(), + ) + } + val inputs = ShowLocationEntryPoint.Inputs( + location = Location(37.4219983, -122.084, 10f), + description = "My location", + ) + val result = entryPoint.createNode( + parentNode, + BuildContext.root(null), + inputs = inputs, + ) + assertThat(result).isInstanceOf(ShowLocationNode::class.java) + assertThat(result.plugins).contains(inputs) + } +} diff --git a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt index 937d1d475e..cc53badbb2 100644 --- a/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt +++ b/features/location/impl/src/test/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenterTest.kt @@ -37,10 +37,10 @@ class ShowLocationPresenterTest { permissionsPresenterFactory = object : PermissionsPresenter.Factory { override fun create(permissions: List): PermissionsPresenter = fakePermissionsPresenter }, - fakeLocationActions, - fakeBuildMeta, - location, - A_DESCRIPTION, + locationActions = fakeLocationActions, + buildMeta = fakeBuildMeta, + location = location, + description = A_DESCRIPTION, ) @Test diff --git a/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt index 8ba29a65aa..69a3331ffb 100644 --- a/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt +++ b/features/location/test/src/main/kotlin/io/element/android/features/location/test/FakeLocationService.kt @@ -10,7 +10,7 @@ package io.element.android.features.location.test import io.element.android.features.location.api.LocationService class FakeLocationService( - private val isServiceAvailable: Boolean, + private val isServiceAvailable: Boolean = false, ) : LocationService { override fun isServiceAvailable() = isServiceAvailable } diff --git a/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt new file mode 100644 index 0000000000..854e89b13a --- /dev/null +++ b/features/lockscreen/impl/src/test/kotlin/io/element/android/features/lockscreen/impl/DefaultLockScreenEntryPointTest.kt @@ -0,0 +1,62 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.lockscreen.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLockScreenEntryPointTest { + @Test + fun `test node builder Setup`() { + val entryPoint = DefaultLockScreenEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + LockScreenFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : LockScreenEntryPoint.Callback { + override fun onSetupDone() = lambdaError() + } + val navTarget = LockScreenEntryPoint.Target.Setup + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null), navTarget) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LockScreenFlowNode::class.java) + assertThat(result.plugins).contains(LockScreenFlowNode.Inputs(LockScreenFlowNode.NavTarget.Setup)) + assertThat(result.plugins).contains(callback) + } + + @Test + fun `test node builder Settings`() { + val entryPoint = DefaultLockScreenEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + LockScreenFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : LockScreenEntryPoint.Callback { + override fun onSetupDone() = lambdaError() + } + val navTarget = LockScreenEntryPoint.Target.Settings + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null), navTarget) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LockScreenFlowNode::class.java) + assertThat(result.plugins).contains(LockScreenFlowNode.Inputs(LockScreenFlowNode.NavTarget.Settings)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt new file mode 100644 index 0000000000..6b44f836b6 --- /dev/null +++ b/features/login/impl/src/test/kotlin/io/element/android/features/login/impl/DefaultLoginEntryPointTest.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.login.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.enterprise.test.FakeEnterpriseService +import io.element.android.features.login.api.LoginEntryPoint +import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource +import io.element.android.libraries.oidc.test.customtab.FakeOidcActionFlow +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLoginEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultLoginEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + LoginFlowNode( + buildContext = buildContext, + plugins = plugins, + accountProviderDataSource = AccountProviderDataSource(FakeEnterpriseService()), + oidcActionFlow = FakeOidcActionFlow(), + ) + } + val callback = object : LoginEntryPoint.Callback { + override fun onReportProblem() = lambdaError() + } + val params = LoginEntryPoint.Params( + accountProvider = "ac", + loginHint = "lh", + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LoginFlowNode::class.java) + assertThat(result.plugins).contains(LoginFlowNode.Params(params.accountProvider, params.loginHint)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt index 4d6b6df3d2..08a7047c1c 100644 --- a/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt +++ b/features/logout/api/src/main/kotlin/io/element/android/features/logout/api/direct/DirectLogoutView.kt @@ -9,7 +9,7 @@ package io.element.android.features.logout.api.direct import androidx.compose.runtime.Composable -interface DirectLogoutView { +fun interface DirectLogoutView { @Composable fun Render(state: DirectLogoutState) } diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt new file mode 100644 index 0000000000..86300353b0 --- /dev/null +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/DefaultLogoutEntryPointTest.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.logout.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.logout.api.LogoutEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultLogoutEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultLogoutEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + LogoutNode( + buildContext = buildContext, + plugins = plugins, + presenter = createLogoutPresenter(), + ) + } + val callback = object : LogoutEntryPoint.Callback { + override fun onChangeRecoveryKeyClick() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(LogoutNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt index 3a309ab7b9..34406aa098 100644 --- a/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt +++ b/features/logout/impl/src/test/kotlin/io/element/android/features/logout/impl/LogoutPresenterTest.kt @@ -225,12 +225,12 @@ class LogoutPresenterTest { skipItems(2) return awaitItem() } - - private fun createLogoutPresenter( - matrixClient: MatrixClient = FakeMatrixClient(), - encryptionService: EncryptionService = FakeEncryptionService(), - ): LogoutPresenter = LogoutPresenter( - matrixClient = matrixClient, - encryptionService = encryptionService, - ) } + +internal fun createLogoutPresenter( + matrixClient: MatrixClient = FakeMatrixClient(), + encryptionService: EncryptionService = FakeEncryptionService(), +): LogoutPresenter = LogoutPresenter( + matrixClient = matrixClient, + encryptionService = encryptionService, +) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt new file mode 100644 index 0000000000..dd4f4e4d41 --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/DefaultMessagesEntryPointTest.kt @@ -0,0 +1,121 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl + +import androidx.compose.runtime.Composable +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.ElementCallEntryPoint +import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint +import io.element.android.features.location.api.SendLocationEntryPoint +import io.element.android.features.location.api.ShowLocationEntryPoint +import io.element.android.features.location.test.FakeLocationService +import io.element.android.features.messages.api.MessagesEntryPoint +import io.element.android.features.messages.impl.pinned.banner.createPinnedEventsTimelineProvider +import io.element.android.features.messages.impl.timeline.createTimelineController +import io.element.android.features.poll.api.create.CreatePollEntryPoint +import io.element.android.libraries.dateformatter.test.FakeDateFormatter +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.permalink.PermalinkData +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.AN_EVENT_ID +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.matrix.test.room.FakeBaseRoom +import io.element.android.libraries.matrix.ui.messages.RoomMemberProfilesCache +import io.element.android.libraries.matrix.ui.messages.RoomNamesCache +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.libraries.textcomposer.mentions.MentionSpanTheme +import io.element.android.libraries.textcomposer.mentions.MentionSpanUpdater +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import io.element.android.tests.testutils.testCoroutineDispatchers +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultMessagesEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultMessagesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + MessagesFlowNode( + buildContext = buildContext, + plugins = plugins, + matrixClient = FakeMatrixClient(), + sendLocationEntryPoint = object : SendLocationEntryPoint { + override fun builder(timelineMode: Timeline.Mode) = lambdaError() + }, + showLocationEntryPoint = object : ShowLocationEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext, inputs: ShowLocationEntryPoint.Inputs) = lambdaError() + }, + createPollEntryPoint = object : CreatePollEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + elementCallEntryPoint = object : ElementCallEntryPoint { + override fun startCall(callType: CallType) = lambdaError() + override suspend fun handleIncomingCall( + callType: CallType.RoomCall, + eventId: EventId, + senderId: UserId, + roomName: String?, + senderName: String?, + avatarUrl: String?, + timestamp: Long, + notificationChannelId: String, + textContent: String?, + ) = lambdaError() + }, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + analyticsService = FakeAnalyticsService(), + locationService = FakeLocationService(), + room = FakeBaseRoom(), + roomMemberProfilesCache = RoomMemberProfilesCache(), + roomNamesCache = RoomNamesCache(), + mentionSpanUpdater = object : MentionSpanUpdater { + override fun updateMentionSpans(text: CharSequence) = text + + @Composable + override fun rememberMentionSpans(text: CharSequence) = text + }, + mentionSpanTheme = MentionSpanTheme(A_USER_ID), + pinnedEventsTimelineProvider = createPinnedEventsTimelineProvider(), + timelineController = createTimelineController(), + knockRequestsListEntryPoint = object : KnockRequestsListEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + dateFormatter = FakeDateFormatter(), + coroutineDispatchers = testCoroutineDispatchers(), + ) + } + val callback = object : MessagesEntryPoint.Callback { + override fun onRoomDetailsClick() = lambdaError() + override fun onUserDataClick(userId: UserId) = lambdaError() + override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() + override fun onForwardedToSingleRoom(roomId: RoomId) = lambdaError() + } + val initialTarget = MessagesEntryPoint.InitialTarget.Messages(focusedEventId = AN_EVENT_ID) + val params = MessagesEntryPoint.Params(initialTarget) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MessagesFlowNode::class.java) + assertThat(result.plugins).contains(MessagesEntryPoint.Params(initialTarget)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index 4840d5bed1..38182dec1d 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -178,10 +178,9 @@ class PinnedMessagesBannerPresenterTest { ), syncService: SyncService = FakeSyncService(), ): PinnedMessagesBannerPresenter { - val timelineProvider = PinnedEventsTimelineProvider( + val timelineProvider = createPinnedEventsTimelineProvider( room = room, syncService = syncService, - dispatchers = testCoroutineDispatchers(), ) timelineProvider.launchIn(backgroundScope) @@ -192,3 +191,12 @@ class PinnedMessagesBannerPresenterTest { ) } } + +internal fun TestScope.createPinnedEventsTimelineProvider( + room: JoinedRoom = FakeJoinedRoom(), + syncService: SyncService = FakeSyncService(), +) = PinnedEventsTimelineProvider( + room = room, + syncService = syncService, + dispatchers = testCoroutineDispatchers(), +) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt index a2005b7a39..71d295ba8b 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/TimelineControllerTest.kt @@ -217,3 +217,13 @@ class TimelineControllerTest { } } } + +internal fun createTimelineController( + room: FakeJoinedRoom = FakeJoinedRoom(liveTimeline = FakeTimeline()), + liveTimeline: Timeline = FakeTimeline(name = "live"), +): TimelineController { + return TimelineController( + room = room, + liveTimeline = liveTimeline + ) +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt index 134742f7d1..2d760d8314 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/create/CreatePollPresenter.kt @@ -47,7 +47,7 @@ class CreatePollPresenter( @Assisted private val timelineMode: Timeline.Mode, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( timelineMode: Timeline.Mode, backNavigator: () -> Unit, diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt index 4fbb7f1499..983e3157a3 100644 --- a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/data/PollRepository.kt @@ -33,7 +33,7 @@ class PollRepository( @Assisted private val timelineMode: Timeline.Mode, ) { @AssistedFactory - interface Factory { + fun interface Factory { fun create( timelineMode: Timeline.Mode, ): PollRepository diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt new file mode 100644 index 0000000000..2150292c4c --- /dev/null +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/create/DefaultCreatePollEntryPointTest.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.poll.impl.create + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.test.FakeMessageComposerContext +import io.element.android.features.poll.api.create.CreatePollEntryPoint +import io.element.android.features.poll.api.create.CreatePollMode +import io.element.android.features.poll.impl.data.PollRepository +import io.element.android.libraries.matrix.api.timeline.Timeline +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.matrix.test.timeline.LiveTimelineProvider +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultCreatePollEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultCreatePollEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + CreatePollNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { timelineMode: Timeline.Mode, backNavigator: () -> Unit, mode: CreatePollMode -> + CreatePollPresenter( + repositoryFactory = { + val room = FakeJoinedRoom() + PollRepository(room, LiveTimelineProvider(room), timelineMode) + }, + analyticsService = FakeAnalyticsService(), + messageComposerContext = FakeMessageComposerContext(), + navigateUp = backNavigator, + mode = mode, + timelineMode = timelineMode, + ) + }, + analyticsService = FakeAnalyticsService(), + ) + } + val params = CreatePollEntryPoint.Params( + timelineMode = Timeline.Mode.Live, + mode = CreatePollMode.NewPoll, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .build() + assertThat(result).isInstanceOf(CreatePollNode::class.java) + assertThat(result.plugins).contains(CreatePollNode.Inputs(timelineMode = params.timelineMode, mode = params.mode)) + } +} diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt new file mode 100644 index 0000000000..6d9e44a8a2 --- /dev/null +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPointTest.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.poll.impl.history + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.poll.api.create.CreatePollEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultPollHistoryEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultPollHistoryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + PollHistoryFlowNode( + buildContext = buildContext, + plugins = plugins, + createPollEntryPoint = object : CreatePollEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + } + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null)) + assertThat(result).isInstanceOf(PollHistoryFlowNode::class.java) + } +} diff --git a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt index eeb4d0d223..cac5fae135 100644 --- a/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt +++ b/features/poll/impl/src/test/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenterTest.kt @@ -151,23 +151,23 @@ class PollHistoryPresenterTest { assert(paginateLambda).isCalledExactly(2) } } - - private fun TestScope.createPollHistoryPresenter( - room: FakeJoinedRoom = FakeJoinedRoom(), - endPollAction: EndPollAction = FakeEndPollAction(), - sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(), - pollHistoryItemFactory: PollHistoryItemsFactory = PollHistoryItemsFactory( - pollContentStateFactory = DefaultPollContentStateFactory(FakeMatrixClient()), - dateFormatter = FakeDateFormatter(), - dispatchers = testCoroutineDispatchers(), - ), - ): PollHistoryPresenter { - return PollHistoryPresenter( - sessionCoroutineScope = this, - sendPollResponseAction = sendPollResponseAction, - endPollAction = endPollAction, - pollHistoryItemFactory = pollHistoryItemFactory, - room = room, - ) - } +} + +internal fun TestScope.createPollHistoryPresenter( + room: FakeJoinedRoom = FakeJoinedRoom(), + endPollAction: EndPollAction = FakeEndPollAction(), + sendPollResponseAction: SendPollResponseAction = FakeSendPollResponseAction(), + pollHistoryItemFactory: PollHistoryItemsFactory = PollHistoryItemsFactory( + pollContentStateFactory = DefaultPollContentStateFactory(FakeMatrixClient()), + dateFormatter = FakeDateFormatter(), + dispatchers = testCoroutineDispatchers(), + ), +): PollHistoryPresenter { + return PollHistoryPresenter( + sessionCoroutineScope = this, + sendPollResponseAction = sendPollResponseAction, + endPollAction = endPollAction, + pollHistoryItemFactory = pollHistoryItemFactory, + room = room, + ) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt new file mode 100644 index 0000000000..971ca6ab51 --- /dev/null +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/DefaultPreferencesEntryPointTest.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.preferences.impl + +import android.content.Context +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.deactivation.api.AccountDeactivationEntryPoint +import io.element.android.features.licenses.api.OpenSourceLicensesEntryPoint +import io.element.android.features.lockscreen.api.LockScreenEntryPoint +import io.element.android.features.logout.api.LogoutEntryPoint +import io.element.android.features.preferences.api.PreferencesEntryPoint +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint +import io.element.android.libraries.troubleshoot.api.PushHistoryEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultPreferencesEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultPreferencesEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + PreferencesFlowNode( + buildContext = buildContext, + plugins = plugins, + lockScreenEntryPoint = object : LockScreenEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext, navTarget: LockScreenEntryPoint.Target) = lambdaError() + override fun pinUnlockIntent(context: Context) = lambdaError() + }, + notificationTroubleShootEntryPoint = object : NotificationTroubleShootEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + pushHistoryEntryPoint = object : PushHistoryEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + logoutEntryPoint = object : LogoutEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + openSourceLicensesEntryPoint = object : OpenSourceLicensesEntryPoint { + override fun getNode(node: Node, buildContext: BuildContext) = lambdaError() + }, + accountDeactivationEntryPoint = object : AccountDeactivationEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : PreferencesEntryPoint.Callback { + override fun onOpenBugReport() = lambdaError() + override fun onSecureBackupClick() = lambdaError() + override fun onOpenRoomNotificationSettings(roomId: RoomId) = lambdaError() + override fun navigateTo(sessionId: SessionId, roomId: RoomId, eventId: EventId) = lambdaError() + } + val params = PreferencesEntryPoint.Params( + initialElement = PreferencesEntryPoint.InitialTarget.NotificationSettings, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(PreferencesFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt index 027e2fb38c..362b3798d6 100644 --- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/BugReportPresenterTest.kt @@ -225,15 +225,15 @@ class BugReportPresenterTest { assertThat(awaitItem().sending).isEqualTo(AsyncAction.Uninitialized) } } - - private fun TestScope.createPresenter( - bugReporter: BugReporter = FakeBugReporter(), - crashDataStore: CrashDataStore = FakeCrashDataStore(), - screenshotHolder: ScreenshotHolder = FakeScreenshotHolder(), - ) = BugReportPresenter( - bugReporter = bugReporter, - crashDataStore = crashDataStore, - screenshotHolder = screenshotHolder, - appCoroutineScope = this, - ) } + +internal fun TestScope.createPresenter( + bugReporter: BugReporter = FakeBugReporter(), + crashDataStore: CrashDataStore = FakeCrashDataStore(), + screenshotHolder: ScreenshotHolder = FakeScreenshotHolder(), +) = BugReportPresenter( + bugReporter = bugReporter, + crashDataStore = crashDataStore, + screenshotHolder = screenshotHolder, + appCoroutineScope = this, +) diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt new file mode 100644 index 0000000000..5ea1bb23db --- /dev/null +++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/bugreport/DefaultBugReportEntryPointTest.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.rageshake.impl.bugreport + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.rageshake.api.bugreport.BugReportEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultBugReportEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultBugReportEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + BugReportNode( + buildContext = buildContext, + plugins = plugins, + presenter = createPresenter(), + bugReporter = FakeBugReporter(), + ) + } + val callback = object : BugReportEntryPoint.Callback { + override fun onBugReportSent() = lambdaError() + override fun onViewLogs(basePath: String) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(BugReportNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt b/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt index 7f531fb9e3..1eff7f8206 100644 --- a/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt +++ b/features/reportroom/api/src/main/kotlin/io/element/android/features/reportroom/api/ReportRoomEntryPoint.kt @@ -12,6 +12,6 @@ import com.bumble.appyx.core.node.Node import io.element.android.libraries.architecture.FeatureEntryPoint import io.element.android.libraries.matrix.api.core.RoomId -interface ReportRoomEntryPoint : FeatureEntryPoint { +fun interface ReportRoomEntryPoint : FeatureEntryPoint { fun createNode(parentNode: Node, buildContext: BuildContext, roomId: RoomId): Node } diff --git a/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt b/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt index fccea0e576..f47ab19004 100644 --- a/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt +++ b/features/reportroom/impl/src/main/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenter.kt @@ -31,7 +31,7 @@ class ReportRoomPresenter( private val reportRoom: ReportRoom, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(roomId: RoomId): ReportRoomPresenter } diff --git a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt new file mode 100644 index 0000000000..c8d5998149 --- /dev/null +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/DefaultReportRoomEntryPointTest.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.reportroom.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.test.A_ROOM_ID +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultReportRoomEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultReportRoomEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ReportRoomNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { roomId -> + assertThat(roomId).isEqualTo(A_ROOM_ID) + createReportRoomPresenter() + } + ) + } + val result = entryPoint.createNode(parentNode, BuildContext.root(null), A_ROOM_ID) + assertThat(result).isInstanceOf(ReportRoomNode::class.java) + assertThat(result.plugins).contains(ReportRoomNode.Inputs(A_ROOM_ID)) + } +} diff --git a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt index d85f2b86e8..eb2e94366d 100644 --- a/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt +++ b/features/reportroom/impl/src/test/kotlin/io/element/android/features/reportroom/impl/ReportRoomPresenterTest.kt @@ -141,11 +141,11 @@ class ReportRoomPresenterTest { ) } } - - fun createReportRoomPresenter( - roomId: RoomId = A_ROOM_ID, - reportRoom: ReportRoom = FakeReportRoom() - ): ReportRoomPresenter { - return ReportRoomPresenter(roomId, reportRoom) - } +} + +internal fun createReportRoomPresenter( + roomId: RoomId = A_ROOM_ID, + reportRoom: ReportRoom = FakeReportRoom() +): ReportRoomPresenter { + return ReportRoomPresenter(roomId, reportRoom) } diff --git a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt index 95ed62a819..9b65d3e14a 100644 --- a/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt +++ b/features/roomaliasresolver/impl/src/main/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasResolverPresenter.kt @@ -30,7 +30,7 @@ class RoomAliasResolverPresenter( @Assisted private val roomAlias: RoomAlias, private val matrixClient: MatrixClient, ) : Presenter { - interface Factory { + fun interface Factory { fun create( roomAlias: RoomAlias, ): RoomAliasResolverPresenter diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt new file mode 100644 index 0000000000..efd25c60df --- /dev/null +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/DefaultRoomAliasResolverEntryPointTest.kt @@ -0,0 +1,53 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomaliasresolver.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.roomaliasesolver.api.RoomAliasResolverEntryPoint +import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias +import io.element.android.libraries.matrix.test.A_ROOM_ALIAS +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomAliasResolverEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultRoomAliasResolverEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomAliasResolverNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { alias -> + assertThat(alias).isEqualTo(A_ROOM_ALIAS) + createPresenter( + alias, + ) + } + + ) + } + val callback = object : RoomAliasResolverEntryPoint.Callback { + override fun onAliasResolved(data: ResolvedRoomAlias) = lambdaError() + } + val params = RoomAliasResolverEntryPoint.Params( + roomAlias = A_ROOM_ALIAS + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomAliasResolverNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt index 3071d8943a..f90b07c91b 100644 --- a/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt +++ b/features/roomaliasresolver/impl/src/test/kotlin/io/element/android/features/roomaliasresolver/impl/RoomAliasHelperPresenterTest.kt @@ -79,16 +79,16 @@ class RoomAliasHelperPresenterTest { assertThat(retryState.resolveState.errorOrNull()).isEqualTo(AN_EXCEPTION) } } - - private fun createPresenter( - roomAlias: RoomAlias = A_ROOM_ALIAS, - matrixClient: MatrixClient = FakeMatrixClient(), - ) = RoomAliasResolverPresenter( - roomAlias = roomAlias, - matrixClient = matrixClient, - ) } +internal fun createPresenter( + roomAlias: RoomAlias = A_ROOM_ALIAS, + matrixClient: MatrixClient = FakeMatrixClient(), +) = RoomAliasResolverPresenter( + roomAlias = roomAlias, + matrixClient = matrixClient, +) + internal fun aResolvedRoomAlias( roomId: RoomId = A_ROOM_ID, servers: List = A_SERVER_LIST, diff --git a/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt new file mode 100644 index 0000000000..e863b7b562 --- /dev/null +++ b/features/roomdetails/impl/src/test/kotlin/io/element/android/features/roomdetails/impl/DefaultRoomDetailsEntryPointTest.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdetails.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.ElementCallEntryPoint +import io.element.android.features.changeroommemberroes.api.ChangeRoomMemberRolesEntryPoint +import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint +import io.element.android.features.messages.api.MessagesEntryPoint +import io.element.android.features.poll.api.history.PollHistoryEntryPoint +import io.element.android.features.reportroom.api.ReportRoomEntryPoint +import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint +import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.permalink.PermalinkData +import io.element.android.libraries.matrix.test.room.FakeJoinedRoom +import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.services.analytics.test.FakeAnalyticsService +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomDetailsEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultRoomDetailsEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomDetailsFlowNode( + buildContext = buildContext, + plugins = plugins, + pollHistoryEntryPoint = object : PollHistoryEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + elementCallEntryPoint = object : ElementCallEntryPoint { + override fun startCall(callType: CallType) = lambdaError() + override suspend fun handleIncomingCall( + callType: CallType.RoomCall, + eventId: EventId, + senderId: UserId, + roomName: String?, + senderName: String?, + avatarUrl: String?, + timestamp: Long, + notificationChannelId: String, + textContent: String? + ) = lambdaError() + }, + room = FakeJoinedRoom(), + analyticsService = FakeAnalyticsService(), + messagesEntryPoint = object : MessagesEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + knockRequestsListEntryPoint = object : KnockRequestsListEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + mediaGalleryEntryPoint = object : MediaGalleryEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + outgoingVerificationEntryPoint = object : OutgoingVerificationEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + reportRoomEntryPoint = object : ReportRoomEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext, roomId: RoomId) = lambdaError() + }, + changeRoomMemberRolesEntryPoint = object : ChangeRoomMemberRolesEntryPoint { + override fun builder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : RoomDetailsEntryPoint.Callback { + override fun onOpenGlobalNotificationSettings() = lambdaError() + override fun onOpenRoom(roomId: RoomId, serverNames: List) = lambdaError() + override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) = lambdaError() + override fun onForwardedToSingleRoom(roomId: RoomId) = lambdaError() + } + val params = RoomDetailsEntryPoint.Params( + initialElement = RoomDetailsEntryPoint.InitialTarget.RoomDetails, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomDetailsFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt new file mode 100644 index 0000000000..fc3ffa2ec3 --- /dev/null +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/DefaultRoomDirectoryEntryPointTest.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.roomdirectory.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.roomdirectory.api.RoomDescription +import io.element.android.features.roomdirectory.api.RoomDirectoryEntryPoint +import io.element.android.features.roomdirectory.impl.root.RoomDirectoryNode +import io.element.android.features.roomdirectory.impl.root.createRoomDirectoryPresenter +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomDirectoryEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultRoomDirectoryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomDirectoryNode( + buildContext = buildContext, + plugins = plugins, + presenter = createRoomDirectoryPresenter(), + ) + } + val callback = object : RoomDirectoryEntryPoint.Callback { + override fun onResultClick(roomDescription: RoomDescription) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomDirectoryNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt index d6ebb6cd95..4af983b307 100644 --- a/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt +++ b/features/roomdirectory/impl/src/test/kotlin/io/element/android/features/roomdirectory/impl/root/RoomDirectoryPresenterTest.kt @@ -122,15 +122,15 @@ class RoomDirectoryPresenterTest { .isCalledOnce() .withNoParameter() } - - private fun TestScope.createRoomDirectoryPresenter( - roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService( - createRoomDirectoryListFactory = { FakeRoomDirectoryList() } - ), - ): RoomDirectoryPresenter { - return RoomDirectoryPresenter( - dispatchers = testCoroutineDispatchers(), - roomDirectoryService = roomDirectoryService, - ) - } +} + +internal fun TestScope.createRoomDirectoryPresenter( + roomDirectoryService: RoomDirectoryService = FakeRoomDirectoryService( + createRoomDirectoryListFactory = { FakeRoomDirectoryList() } + ), +): RoomDirectoryPresenter { + return RoomDirectoryPresenter( + dispatchers = testCoroutineDispatchers(), + roomDirectoryService = roomDirectoryService, + ) } diff --git a/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt new file mode 100644 index 0000000000..13a00ff046 --- /dev/null +++ b/features/securebackup/impl/src/test/kotlin/io/element/android/features/securebackup/impl/DefaultSecureBackupEntryPointTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.securebackup.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.securebackup.api.SecureBackupEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSecureBackupEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultSecureBackupEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + SecureBackupFlowNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : SecureBackupEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val params = SecureBackupEntryPoint.Params(SecureBackupEntryPoint.InitialTarget.ResetIdentity) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(SecureBackupFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt index aaadf6f8d0..056d8b912e 100644 --- a/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt +++ b/features/share/impl/src/main/kotlin/io/element/android/features/share/impl/SharePresenter.kt @@ -43,7 +43,7 @@ class SharePresenter( private val mediaOptimizationConfigProvider: MediaOptimizationConfigProvider, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(intent: Intent): SharePresenter } diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt new file mode 100644 index 0000000000..2762af89c7 --- /dev/null +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/DefaultShareEntryPointTest.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.share.impl + +import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.share.api.ShareEntryPoint +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultShareEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultShareEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ShareNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { createSharePresenter() }, + roomSelectEntryPoint = object : RoomSelectEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext): RoomSelectEntryPoint.NodeBuilder { + lambdaError() + } + }, + ) + } + val callback = object : ShareEntryPoint.Callback { + override fun onDone(roomIds: List) = lambdaError() + } + val params = ShareEntryPoint.Params( + intent = Intent(), + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(ShareNode::class.java) + assertThat(result.plugins).contains(ShareNode.Inputs(params.intent)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt index 7ddb7d0ae4..b1b39b2e80 100644 --- a/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt +++ b/features/share/impl/src/test/kotlin/io/element/android/features/share/impl/SharePresenterTest.kt @@ -158,23 +158,23 @@ class SharePresenterTest { sendFileResult.assertions().isCalledOnce() } } - - private fun TestScope.createSharePresenter( - intent: Intent = Intent(), - shareIntentHandler: ShareIntentHandler = FakeShareIntentHandler(), - matrixClient: MatrixClient = FakeMatrixClient(), - mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(), - activeRoomsHolder: ActiveRoomsHolder = ActiveRoomsHolder(), - mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), - ): SharePresenter { - return SharePresenter( - intent = intent, - sessionCoroutineScope = this, - shareIntentHandler = shareIntentHandler, - matrixClient = matrixClient, - mediaPreProcessor = mediaPreProcessor, - activeRoomsHolder = activeRoomsHolder, - mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, - ) - } +} + +internal fun TestScope.createSharePresenter( + intent: Intent = Intent(), + shareIntentHandler: ShareIntentHandler = FakeShareIntentHandler(), + matrixClient: MatrixClient = FakeMatrixClient(), + mediaPreProcessor: MediaPreProcessor = FakeMediaPreProcessor(), + activeRoomsHolder: ActiveRoomsHolder = ActiveRoomsHolder(), + mediaOptimizationConfigProvider: FakeMediaOptimizationConfigProvider = FakeMediaOptimizationConfigProvider(), +): SharePresenter { + return SharePresenter( + intent = intent, + sessionCoroutineScope = this, + shareIntentHandler = shareIntentHandler, + matrixClient = matrixClient, + mediaPreProcessor = mediaPreProcessor, + activeRoomsHolder = activeRoomsHolder, + mediaOptimizationConfigProvider = mediaOptimizationConfigProvider, + ) } diff --git a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt index 6516a2a1c6..9810892ff3 100644 --- a/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt +++ b/features/signedout/impl/src/main/kotlin/io/element/android/features/signedout/impl/SignedOutPresenter.kt @@ -29,7 +29,7 @@ class SignedOutPresenter( private val buildMeta: BuildMeta, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(sessionId: String): SignedOutPresenter } diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt new file mode 100644 index 0000000000..0edcbf2054 --- /dev/null +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/DefaultSignedOutEntryPointTest.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.signedout.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.signedout.api.SignedOutEntryPoint +import io.element.android.libraries.matrix.test.A_SESSION_ID +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultSignedOutEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultSignedOutEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + SignedOutNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { sessionId -> + assertThat(sessionId).isEqualTo(A_SESSION_ID.value) + createSignedOutPresenter() + } + ) + } + val params = SignedOutEntryPoint.Params(A_SESSION_ID) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .build() + assertThat(result).isInstanceOf(SignedOutNode::class.java) + assertThat(result.plugins).contains(SignedOutNode.Inputs(params.sessionId)) + } +} diff --git a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt index 8674020f1e..d3a52c8b37 100644 --- a/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt +++ b/features/signedout/impl/src/test/kotlin/io/element/android/features/signedout/impl/SignedOutPresenterTest.kt @@ -22,12 +22,12 @@ import kotlinx.coroutines.test.runTest import org.junit.Rule import org.junit.Test +private val appName = "AppName" + class SignedOutPresenterTest { @get:Rule val warmUpRule = WarmUpRule() - private val appName = "AppName" - @Test fun `present - initial state`() = runTest { val aSessionData = aSessionData() @@ -64,15 +64,15 @@ class SignedOutPresenterTest { assertThat(sessionStore.getAllSessions()).isEmpty() } } - - private fun createSignedOutPresenter( - sessionId: SessionId = A_SESSION_ID, - sessionStore: SessionStore = InMemorySessionStore(), - ): SignedOutPresenter { - return SignedOutPresenter( - sessionId = sessionId.value, - sessionStore = sessionStore, - buildMeta = aBuildMeta(applicationName = appName), - ) - } +} + +internal fun createSignedOutPresenter( + sessionId: SessionId = A_SESSION_ID, + sessionStore: SessionStore = InMemorySessionStore(), +): SignedOutPresenter { + return SignedOutPresenter( + sessionId = sessionId.value, + sessionStore = sessionStore, + buildMeta = aBuildMeta(applicationName = appName), + ) } diff --git a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt index a0afb36630..f57ee5cafb 100644 --- a/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt +++ b/features/space/impl/src/test/kotlin/io/element/android/features/space/impl/DefaultSpaceEntryPointTest.kt @@ -25,7 +25,7 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class DefaultSpaceEntryPointTest { @Test - fun `test DefaultSpaceEntryPoint`() { + fun `test node builder`() { val entryPoint = DefaultSpaceEntryPoint() val nodeInputs = SpaceEntryPoint.Inputs(A_ROOM_ID) val parentNode = TestParentNode.create { buildContext, plugins -> diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt new file mode 100644 index 0000000000..351ccb651a --- /dev/null +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/DefaultStartChatEntryPointTest.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.startchat.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.createroom.api.CreateRoomEntryPoint +import io.element.android.features.startchat.api.StartChatEntryPoint +import io.element.android.features.startchat.impl.root.StartChatNode +import io.element.android.libraries.matrix.api.core.RoomIdOrAlias +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultStartChatEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultStartChatEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + StartChatFlowNode( + buildContext = buildContext, + plugins = plugins, + createRoomEntryPoint = object : CreateRoomEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : StartChatEntryPoint.Callback { + override fun onOpenRoom(roomIdOrAlias: RoomIdOrAlias, serverNames: List) = lambdaError() + override fun onOpenRoomDirectory() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(StartChatFlowNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt index 59a8838c6b..7340981053 100644 --- a/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt +++ b/features/startchat/impl/src/test/kotlin/io/element/android/features/startchat/impl/root/StartChatPresenterTest.kt @@ -177,23 +177,23 @@ class StartChatPresenterTest { } } } - - private fun createStartChatPresenter( - startDMAction: StartDMAction = FakeStartDMAction(), - isRoomDirectorySearchEnabled: Boolean = false, - ): StartChatPresenter { - val featureFlagService = FakeFeatureFlagService( - initialState = mapOf( - FeatureFlags.RoomDirectorySearch.key to isRoomDirectorySearchEnabled, - ), - ) - return StartChatPresenter( - presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()), - userRepository = FakeUserRepository(), - userListDataStore = UserListDataStore(), - startDMAction = startDMAction, - featureFlagService = featureFlagService, - buildMeta = aBuildMeta(), - ) - } +} + +internal fun createStartChatPresenter( + startDMAction: StartDMAction = FakeStartDMAction(), + isRoomDirectorySearchEnabled: Boolean = false, +): StartChatPresenter { + val featureFlagService = FakeFeatureFlagService( + initialState = mapOf( + FeatureFlags.RoomDirectorySearch.key to isRoomDirectorySearchEnabled, + ), + ) + return StartChatPresenter( + presenterFactory = FakeUserListPresenterFactory(FakeUserListPresenter()), + userRepository = FakeUserRepository(), + userListDataStore = UserListDataStore(), + startDMAction = startDMAction, + featureFlagService = featureFlagService, + buildMeta = aBuildMeta(), + ) } diff --git a/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt new file mode 100644 index 0000000000..266d709ccf --- /dev/null +++ b/features/userprofile/impl/src/test/kotlin/io/element/android/features/userprofile/impl/DefaultUserProfileEntryPointTest.kt @@ -0,0 +1,79 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.userprofile.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.features.call.api.CallType +import io.element.android.features.call.api.ElementCallEntryPoint +import io.element.android.features.userprofile.api.UserProfileEntryPoint +import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.user.CurrentSessionIdHolder +import io.element.android.libraries.matrix.test.A_USER_ID +import io.element.android.libraries.matrix.test.FakeMatrixClient +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultUserProfileEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultUserProfileEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + UserProfileFlowNode( + buildContext = buildContext, + plugins = plugins, + sessionIdHolder = CurrentSessionIdHolder(FakeMatrixClient()), + elementCallEntryPoint = object : ElementCallEntryPoint { + override fun startCall(callType: CallType) = lambdaError() + override suspend fun handleIncomingCall( + callType: CallType.RoomCall, + eventId: EventId, + senderId: UserId, + roomName: String?, + senderName: String?, + avatarUrl: String?, + timestamp: Long, + notificationChannelId: String, + textContent: String? + ) = lambdaError() + }, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + outgoingVerificationEntryPoint = object : OutgoingVerificationEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + }, + ) + } + val callback = object : UserProfileEntryPoint.Callback { + override fun onOpenRoom(roomId: RoomId) { + lambdaError() + } + } + val params = UserProfileEntryPoint.Params( + userId = A_USER_ID, + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(UserProfileFlowNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt index aab6ff0329..8be176f117 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenter.kt @@ -48,7 +48,7 @@ class IncomingVerificationPresenter( private val dateFormatter: DateFormatter, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( verificationRequest: VerificationRequest.Incoming, navigator: IncomingVerificationNavigator, diff --git a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt index 5b6004845d..84ebec96de 100644 --- a/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt +++ b/features/verifysession/impl/src/main/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenter.kt @@ -42,7 +42,7 @@ class OutgoingVerificationPresenter( private val encryptionService: EncryptionService, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( verificationRequest: VerificationRequest.Outgoing, showDeviceVerifiedScreen: Boolean, diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt new file mode 100644 index 0000000000..b3ac839b54 --- /dev/null +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/DefaultIncomingVerificationEntryPointTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.verifysession.impl.incoming + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.verifysession.api.IncomingVerificationEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultIncomingVerificationEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultIncomingVerificationEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + IncomingVerificationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _ -> createPresenter() } + ) + } + val callback = object : IncomingVerificationEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val params = IncomingVerificationEntryPoint.Params( + verificationRequest = anIncomingSessionVerificationRequest() + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(IncomingVerificationNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt index 8fdf62df4f..06c4956ea9 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/incoming/IncomingVerificationPresenterTest.kt @@ -289,31 +289,31 @@ class IncomingVerificationPresenterTest { navigatorLambda.assertions().isCalledOnce() } } - - private val anIncomingSessionVerificationRequest = VerificationRequest.Incoming.OtherSession( - details = SessionVerificationRequestDetails( - senderProfile = SessionVerificationRequestDetails.SenderProfile( - userId = A_USER_ID, - displayName = "a device name", - avatarUrl = null, - ), - flowId = FlowId("flowId"), - deviceId = A_DEVICE_ID, - firstSeenTimestamp = A_TIMESTAMP, - ) - ) - - private fun TestScope.createPresenter( - verificationRequest: VerificationRequest.Incoming = anIncomingSessionVerificationRequest, - navigator: IncomingVerificationNavigator = IncomingVerificationNavigator { lambdaError() }, - service: SessionVerificationService = FakeSessionVerificationService(), - dateFormatter: DateFormatter = FakeDateFormatter(), - ) = IncomingVerificationPresenter( - verificationRequest = verificationRequest, - navigator = navigator, - sessionVerificationService = service, - stateMachine = IncomingVerificationStateMachine(service), - dateFormatter = dateFormatter, - sessionCoroutineScope = backgroundScope, - ) } + +private val anIncomingSessionVerificationRequest = VerificationRequest.Incoming.OtherSession( + details = SessionVerificationRequestDetails( + senderProfile = SessionVerificationRequestDetails.SenderProfile( + userId = A_USER_ID, + displayName = "a device name", + avatarUrl = null, + ), + flowId = FlowId("flowId"), + deviceId = A_DEVICE_ID, + firstSeenTimestamp = A_TIMESTAMP, + ) +) + +internal fun TestScope.createPresenter( + verificationRequest: VerificationRequest.Incoming = anIncomingSessionVerificationRequest, + navigator: IncomingVerificationNavigator = IncomingVerificationNavigator { lambdaError() }, + service: SessionVerificationService = FakeSessionVerificationService(), + dateFormatter: DateFormatter = FakeDateFormatter(), +) = IncomingVerificationPresenter( + verificationRequest = verificationRequest, + navigator = navigator, + sessionVerificationService = service, + stateMachine = IncomingVerificationStateMachine(service), + dateFormatter = dateFormatter, + sessionCoroutineScope = backgroundScope, +) diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt new file mode 100644 index 0000000000..f4b53a133c --- /dev/null +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/DefaultOutgoingVerificationEntryPointTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.verifysession.impl.outgoing + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.verifysession.api.OutgoingVerificationEntryPoint +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultOutgoingVerificationEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultOutgoingVerificationEntryPoint() + + val parentNode = TestParentNode.create { buildContext, plugins -> + OutgoingVerificationNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _ -> + createOutgoingVerificationPresenter() + } + ) + } + val callback = object : OutgoingVerificationEntryPoint.Callback { + override fun onLearnMoreAboutEncryption() = lambdaError() + override fun onBack() = lambdaError() + override fun onDone() = lambdaError() + } + val params = OutgoingVerificationEntryPoint.Params( + showDeviceVerifiedScreen = true, + verificationRequest = anOutgoingSessionVerificationRequest(), + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(OutgoingVerificationNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } +} diff --git a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt index 06940f37a5..2eac19d018 100644 --- a/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt +++ b/features/verifysession/impl/src/test/kotlin/io/element/android/features/verifysession/impl/outgoing/OutgoingVerificationPresenterTest.kt @@ -321,18 +321,18 @@ class OutgoingVerificationPresenterTest { emitVerifiedStatus(SessionVerifiedStatus.NotVerified) } } - - private fun createOutgoingVerificationPresenter( - service: SessionVerificationService, - verificationRequest: VerificationRequest.Outgoing = anOutgoingSessionVerificationRequest(), - encryptionService: EncryptionService = FakeEncryptionService(), - showDeviceVerifiedScreen: Boolean = false, - ): OutgoingVerificationPresenter { - return OutgoingVerificationPresenter( - showDeviceVerifiedScreen = showDeviceVerifiedScreen, - verificationRequest = verificationRequest, - sessionVerificationService = service, - encryptionService = encryptionService, - ) - } +} + +internal fun createOutgoingVerificationPresenter( + service: SessionVerificationService = FakeSessionVerificationService(), + verificationRequest: VerificationRequest.Outgoing = anOutgoingSessionVerificationRequest(), + encryptionService: EncryptionService = FakeEncryptionService(), + showDeviceVerifiedScreen: Boolean = false, +): OutgoingVerificationPresenter { + return OutgoingVerificationPresenter( + showDeviceVerifiedScreen = showDeviceVerifiedScreen, + verificationRequest = verificationRequest, + sessionVerificationService = service, + encryptionService = encryptionService, + ) } diff --git a/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt new file mode 100644 index 0000000000..dc2431c986 --- /dev/null +++ b/features/viewfolder/impl/src/test/kotlin/io/element/android/features/viewfolder/impl/DefaultViewFolderEntryPointTest.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.viewfolder.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.features.viewfolder.api.ViewFolderEntryPoint +import io.element.android.features.viewfolder.impl.root.ViewFolderRootNode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultViewFolderEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultViewFolderEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + ViewFolderRootNode( + buildContext = buildContext, + plugins = plugins, + ) + } + val callback = object : ViewFolderEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val params = ViewFolderEntryPoint.Params( + rootPath = "path", + ) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(ViewFolderRootNode::class.java) + assertThat(result.plugins).contains(ViewFolderRootNode.Inputs(params.rootPath)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt index 2a64bb7c98..d5a932b705 100644 --- a/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt +++ b/libraries/architecture/src/main/kotlin/io/element/android/libraries/architecture/FeatureEntryPoint.kt @@ -18,6 +18,6 @@ interface FeatureEntryPoint /** * Can be used when the feature only exposes a simple node without the need of plugins. */ -interface SimpleFeatureEntryPoint : FeatureEntryPoint { +fun interface SimpleFeatureEntryPoint : FeatureEntryPoint { fun createNode(parentNode: Node, buildContext: BuildContext): Node } diff --git a/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt b/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt index 5c5bcf5043..7c8910e156 100644 --- a/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt +++ b/libraries/deeplink/api/src/main/kotlin/io/element/android/libraries/deeplink/api/usecase/InviteFriendsUseCase.kt @@ -9,6 +9,6 @@ package io.element.android.libraries.deeplink.api.usecase import android.app.Activity -interface InviteFriendsUseCase { +fun interface InviteFriendsUseCase { fun execute(activity: Activity) } diff --git a/libraries/mediaviewer/impl/build.gradle.kts b/libraries/mediaviewer/impl/build.gradle.kts index acddcfcf76..4af1c54f46 100644 --- a/libraries/mediaviewer/impl/build.gradle.kts +++ b/libraries/mediaviewer/impl/build.gradle.kts @@ -54,6 +54,7 @@ dependencies { implementation(projects.libraries.matrix.api) testCommonDependencies(libs, true) + testImplementation(projects.libraries.audio.test) testImplementation(projects.libraries.dateformatter.test) testImplementation(projects.libraries.featureflag.test) testImplementation(projects.libraries.matrix.test) diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt index 1d5df9025b..5d998d25fd 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/FocusedTimelineMediaGalleryDataSourceFactory.kt @@ -14,7 +14,7 @@ import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.room.JoinedRoom import io.element.android.libraries.mediaviewer.impl.model.MediaItem -interface FocusedTimelineMediaGalleryDataSourceFactory { +fun interface FocusedTimelineMediaGalleryDataSourceFactory { fun createFor( eventId: EventId, mediaItem: MediaItem.Event, diff --git a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt index b2534f3f71..93ef09cf4f 100644 --- a/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt +++ b/libraries/mediaviewer/impl/src/main/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenter.kt @@ -58,7 +58,7 @@ class MediaViewerPresenter( private val localMediaActions: LocalMediaActions, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create( inputs: MediaViewerEntryPoint.Params, navigator: MediaViewerNavigator, diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt new file mode 100644 index 0000000000..27dc68e75e --- /dev/null +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaGalleryEntryPointTest.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.mediaviewer.api.MediaGalleryEntryPoint +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.libraries.mediaviewer.impl.gallery.root.MediaGalleryRootNode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultMediaGalleryEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultMediaGalleryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaGalleryRootNode( + buildContext = buildContext, + plugins = plugins, + mediaViewerEntryPoint = object : MediaViewerEntryPoint { + override fun nodeBuilder(parentNode: Node, buildContext: BuildContext) = lambdaError() + } + ) + } + val callback = object : MediaGalleryEntryPoint.Callback { + override fun onBackClick() = lambdaError() + override fun onViewInTimeline(eventId: EventId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MediaGalleryRootNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt new file mode 100644 index 0000000000..90ff2f4e70 --- /dev/null +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/DefaultMediaViewerEntryPointTest.kt @@ -0,0 +1,145 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.mediaviewer.impl + +import android.net.Uri +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.core.mimetype.MimeTypes +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.UserId +import io.element.android.libraries.matrix.api.media.MediaSource +import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader +import io.element.android.libraries.mediaplayer.test.FakeAudioFocus +import io.element.android.libraries.mediaviewer.api.MediaInfo +import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint +import io.element.android.libraries.mediaviewer.impl.datasource.createTimelineMediaGalleryDataSource +import io.element.android.libraries.mediaviewer.impl.viewer.MediaViewerNode +import io.element.android.libraries.mediaviewer.impl.viewer.PagerKeysHandler +import io.element.android.libraries.mediaviewer.impl.viewer.createMediaViewerEntryPointParams +import io.element.android.libraries.mediaviewer.impl.viewer.createMediaViewerPresenter +import io.element.android.libraries.mediaviewer.test.FakeLocalMediaFactory +import io.element.android.services.toolbox.test.systemclock.FakeSystemClock +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import io.element.android.tests.testutils.testCoroutineDispatchers +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultMediaViewerEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultMediaViewerEntryPoint() + val mockMediaUri: Uri = mockk("localMediaUri") + val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaViewerNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _, _ -> + createMediaViewerPresenter( + localMediaFactory = localMediaFactory, + ) + }, + timelineMediaGalleryDataSource = createTimelineMediaGalleryDataSource(), + focusedTimelineMediaGalleryDataSourceFactory = { _, _, _ -> + lambdaError() + }, + mediaLoader = FakeMatrixMediaLoader(), + localMediaFactory = FakeLocalMediaFactory(mockMediaUri), + coroutineDispatchers = testCoroutineDispatchers(), + systemClock = FakeSystemClock(), + pagerKeysHandler = PagerKeysHandler(), + textFileViewer = { _, _ -> lambdaError() }, + audioFocus = FakeAudioFocus(), + ) + } + val callback = object : MediaViewerEntryPoint.Callback { + override fun onDone() = lambdaError() + override fun onViewInTimeline(eventId: EventId) = lambdaError() + } + val params = createMediaViewerEntryPointParams() + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MediaViewerNode::class.java) + assertThat(result.plugins).contains(params) + assertThat(result.plugins).contains(callback) + } + + @Test + fun `test node builder avatar`() = runTest { + val entryPoint = DefaultMediaViewerEntryPoint() + val mockMediaUri: Uri = mockk("localMediaUri") + val localMediaFactory = FakeLocalMediaFactory(mockMediaUri) + val parentNode = TestParentNode.create { buildContext, plugins -> + MediaViewerNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { _, _, _ -> + createMediaViewerPresenter( + localMediaFactory = localMediaFactory, + ) + }, + timelineMediaGalleryDataSource = createTimelineMediaGalleryDataSource(), + focusedTimelineMediaGalleryDataSourceFactory = { _, _, _ -> + lambdaError() + }, + mediaLoader = FakeMatrixMediaLoader(), + localMediaFactory = FakeLocalMediaFactory(mockMediaUri), + coroutineDispatchers = testCoroutineDispatchers(), + systemClock = FakeSystemClock(), + pagerKeysHandler = PagerKeysHandler(), + textFileViewer = { _, _ -> lambdaError() }, + audioFocus = FakeAudioFocus(), + ) + } + val callback = object : MediaViewerEntryPoint.Callback { + override fun onDone() = lambdaError() + override fun onViewInTimeline(eventId: EventId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .avatar( + filename = "fn", + avatarUrl = "avatarUrl", + ) + .callback(callback) + .build() + assertThat(result).isInstanceOf(MediaViewerNode::class.java) + assertThat(result.plugins).contains( + MediaViewerEntryPoint.Params( + mode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, + eventId = null, + mediaInfo = MediaInfo( + filename = "fn", + fileSize = null, + caption = null, + mimeType = MimeTypes.Images, + formattedFileSize = "", + fileExtension = "", + senderId = UserId("@dummy:server.org"), + senderName = null, + senderAvatar = null, + dateSent = null, + dateSentFull = null, + waveform = null, + duration = null, + ), + mediaSource = MediaSource(url = "avatarUrl"), + thumbnailSource = null, + canShowInfo = false, + ) + ) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt index 7e9f1870f5..771c82e4a2 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/datasource/TimelineMediaGalleryDataSourceTest.kt @@ -255,19 +255,19 @@ class TimelineMediaGalleryDataSourceTest { ) } } +} - private fun TestScope.createTimelineMediaGalleryDataSource( - room: JoinedRoom = FakeJoinedRoom( - liveTimeline = FakeTimeline(), - ), - ): TimelineMediaGalleryDataSource { - return TimelineMediaGalleryDataSource( - room = room, - mediaTimeline = LiveMediaTimeline(room), - timelineMediaItemsFactory = createTimelineMediaItemsFactory(), - mediaItemsPostProcessor = MediaItemsPostProcessor(), - ) - } +internal fun TestScope.createTimelineMediaGalleryDataSource( + room: JoinedRoom = FakeJoinedRoom( + liveTimeline = FakeTimeline(), + ), +): TimelineMediaGalleryDataSource { + return TimelineMediaGalleryDataSource( + room = room, + mediaTimeline = LiveMediaTimeline(room), + timelineMediaItemsFactory = createTimelineMediaItemsFactory(), + mediaItemsPostProcessor = MediaItemsPostProcessor(), + ) } fun TestScope.createTimelineMediaItemsFactory() = TimelineMediaItemsFactory( diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt index e01eb53efb..b9964d8d3d 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/MediaViewerPresenterTest.kt @@ -29,6 +29,7 @@ import io.element.android.libraries.matrix.test.room.FakeJoinedRoom import io.element.android.libraries.matrix.test.timeline.FakeTimeline import io.element.android.libraries.mediaviewer.api.MediaViewerEntryPoint import io.element.android.libraries.mediaviewer.api.anApkMediaInfo +import io.element.android.libraries.mediaviewer.api.local.LocalMediaFactory import io.element.android.libraries.mediaviewer.impl.R import io.element.android.libraries.mediaviewer.impl.datasource.FakeMediaGalleryDataSource import io.element.android.libraries.mediaviewer.impl.datasource.MediaGalleryDataSource @@ -78,12 +79,13 @@ class MediaViewerPresenterTest { @Test fun `present - initial state null Event`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -97,13 +99,14 @@ class MediaViewerPresenterTest { @Test fun `present - initial state cannot show info`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, canShowInfo = false, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -117,13 +120,14 @@ class MediaViewerPresenterTest { @Test fun `present - initial state Event`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, eventId = AN_EVENT_ID, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, + canRedactOwnResult = { Result.success(true) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -137,14 +141,15 @@ class MediaViewerPresenterTest { @Test fun `present - initial state Event from other`() = runTest { val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, eventId = AN_EVENT_ID, room = FakeJoinedRoom( baseRoom = FakeBaseRoom( - sessionId = A_SESSION_ID_2, - canRedactOtherResult = { Result.success(false) }, + sessionId = A_SESSION_ID_2, + canRedactOtherResult = { Result.success(false) }, + ) ) ) - ) presenter.test { val initialState = awaitFirstItem() assertThat(initialState.listData).isEmpty() @@ -161,6 +166,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage() @@ -192,6 +198,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -224,10 +231,13 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, - room = FakeJoinedRoom(baseRoom = FakeBaseRoom( - canRedactOwnResult = { Result.success(true) }, - )) + room = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + canRedactOwnResult = { Result.success(true) }, + ) + ) ) val anImage = aMediaItemImage( mediaSourceUrl = aUrl, @@ -266,6 +276,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -298,6 +309,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -330,6 +342,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -362,6 +375,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -394,6 +408,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -441,6 +456,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, room = FakeJoinedRoom( liveTimeline = timeline, baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), @@ -498,6 +514,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -549,6 +566,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mode = mode, mediaGalleryDataSource = mediaGalleryDataSource, ) @@ -620,6 +638,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mode = mode, mediaGalleryDataSource = mediaGalleryDataSource, ) @@ -674,6 +693,7 @@ class MediaViewerPresenterTest { startLambda = { }, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) presenter.test { @@ -714,6 +734,7 @@ class MediaViewerPresenterTest { loadMoreLambda = loadMoreLambda, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaGalleryDataSource = mediaGalleryDataSource, ) val anImage = aMediaItemImage( @@ -744,6 +765,7 @@ class MediaViewerPresenterTest { onViewInTimelineClickLambda = onViewInTimelineClickLambda, ) val presenter = createMediaViewerPresenter( + localMediaFactory = localMediaFactory, mediaViewerNavigator = navigator, room = FakeJoinedRoom( baseRoom = FakeBaseRoom(canRedactOwnResult = { Result.success(true) }), @@ -764,42 +786,53 @@ class MediaViewerPresenterTest { private suspend fun ReceiveTurbine.awaitFirstItem(): T { return awaitItem() } - - private fun TestScope.createMediaViewerPresenter( - eventId: EventId? = null, - mode: MediaViewerEntryPoint.MediaViewerMode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, - matrixMediaLoader: FakeMatrixMediaLoader = FakeMatrixMediaLoader(), - localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(), - mediaGalleryDataSource: MediaGalleryDataSource = FakeMediaGalleryDataSource( - startLambda = { }, - ), - canShowInfo: Boolean = true, - mediaViewerNavigator: MediaViewerNavigator = FakeMediaViewerNavigator(), - room: JoinedRoom = FakeJoinedRoom( - liveTimeline = FakeTimeline(), - ), - ): MediaViewerPresenter { - return MediaViewerPresenter( - inputs = MediaViewerEntryPoint.Params( - mode = mode, - eventId = eventId, - mediaInfo = TESTED_MEDIA_INFO, - mediaSource = aMediaSource(), - thumbnailSource = null, - canShowInfo = canShowInfo, - ), - navigator = mediaViewerNavigator, - dataSource = MediaViewerDataSource( - mode = mode, - dispatcher = testCoroutineDispatchers().computation, - galleryDataSource = mediaGalleryDataSource, - mediaLoader = matrixMediaLoader, - localMediaFactory = localMediaFactory, - systemClock = FakeSystemClock(), - pagerKeysHandler = PagerKeysHandler(), - ), - room = room, - localMediaActions = localMediaActions, - ) - } } + +internal fun TestScope.createMediaViewerPresenter( + localMediaFactory: LocalMediaFactory, + eventId: EventId? = null, + mode: MediaViewerEntryPoint.MediaViewerMode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, + matrixMediaLoader: FakeMatrixMediaLoader = FakeMatrixMediaLoader(), + localMediaActions: FakeLocalMediaActions = FakeLocalMediaActions(), + mediaGalleryDataSource: MediaGalleryDataSource = FakeMediaGalleryDataSource( + startLambda = { }, + ), + canShowInfo: Boolean = true, + mediaViewerNavigator: MediaViewerNavigator = FakeMediaViewerNavigator(), + room: JoinedRoom = FakeJoinedRoom( + liveTimeline = FakeTimeline(), + ), +): MediaViewerPresenter { + return MediaViewerPresenter( + inputs = createMediaViewerEntryPointParams( + eventId = eventId, + mode = mode, + canShowInfo = canShowInfo, + ), + navigator = mediaViewerNavigator, + dataSource = MediaViewerDataSource( + mode = mode, + dispatcher = testCoroutineDispatchers().computation, + galleryDataSource = mediaGalleryDataSource, + mediaLoader = matrixMediaLoader, + localMediaFactory = localMediaFactory, + systemClock = FakeSystemClock(), + pagerKeysHandler = PagerKeysHandler(), + ), + room = room, + localMediaActions = localMediaActions, + ) +} + +internal fun createMediaViewerEntryPointParams( + eventId: EventId? = null, + mode: MediaViewerEntryPoint.MediaViewerMode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, + canShowInfo: Boolean = true, +) = MediaViewerEntryPoint.Params( + mode = mode, + eventId = eventId, + mediaInfo = TESTED_MEDIA_INFO, + mediaSource = aMediaSource(), + thumbnailSource = null, + canShowInfo = canShowInfo, +) diff --git a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt index 540f107601..c80aa15428 100644 --- a/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt +++ b/libraries/mediaviewer/impl/src/test/kotlin/io/element/android/libraries/mediaviewer/impl/viewer/SingleMediaGalleryDataSourceTest.kt @@ -168,7 +168,7 @@ class SingleMediaGalleryDataSourceTest { assertThat(resultData.fileItems).isEmpty() } - private fun aMediaViewerEntryPointParams( + internal fun aMediaViewerEntryPointParams( mediaInfo: MediaInfo, ) = MediaViewerEntryPoint.Params( mode = MediaViewerEntryPoint.MediaViewerMode.SingleMedia, diff --git a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt index 83c13bf775..50612c8478 100644 --- a/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt +++ b/libraries/roomselect/impl/src/main/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenter.kt @@ -33,7 +33,7 @@ class RoomSelectPresenter( private val dataSource: RoomSelectSearchDataSource, ) : Presenter { @AssistedFactory - interface Factory { + fun interface Factory { fun create(mode: RoomSelectMode): RoomSelectPresenter } diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt new file mode 100644 index 0000000000..c21eede8b8 --- /dev/null +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/DefaultRoomSelectEntryPointTest.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.roomselect.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.roomselect.api.RoomSelectEntryPoint +import io.element.android.libraries.roomselect.api.RoomSelectMode +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import kotlinx.coroutines.test.runTest +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultRoomSelectEntryPointTest { + @Test + fun `test node builder`() = runTest { + val entryPoint = DefaultRoomSelectEntryPoint() + val testMode = RoomSelectMode.Share + val parentNode = TestParentNode.create { buildContext, plugins -> + RoomSelectNode( + buildContext = buildContext, + plugins = plugins, + presenterFactory = { mode -> + assertThat(mode).isEqualTo(testMode) + createRoomSelectPresenter(mode) + }, + ) + } + val callback = object : RoomSelectEntryPoint.Callback { + override fun onRoomSelected(roomIds: List) = lambdaError() + override fun onCancel() = lambdaError() + } + val params = RoomSelectEntryPoint.Params(testMode) + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .params(params) + .callback(callback) + .build() + assertThat(result).isInstanceOf(RoomSelectNode::class.java) + assertThat(result.plugins).contains(RoomSelectNode.Inputs(params.mode)) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt index e8a8e11ca3..8294c97fad 100644 --- a/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt +++ b/libraries/roomselect/impl/src/test/kotlin/io/element/android/libraries/roomselect/impl/RoomSelectPresenterTest.kt @@ -111,15 +111,15 @@ class RoomSelectPresenterTest { cancel() } } - - private fun TestScope.createRoomSelectPresenter( - mode: RoomSelectMode = RoomSelectMode.Forward, - roomListService: RoomListService = FakeRoomListService(), - ) = RoomSelectPresenter( - mode = mode, - dataSource = RoomSelectSearchDataSource( - roomListService = roomListService, - coroutineDispatchers = testCoroutineDispatchers(), - ), - ) } + +internal fun TestScope.createRoomSelectPresenter( + mode: RoomSelectMode = RoomSelectMode.Forward, + roomListService: RoomListService = FakeRoomListService(), +) = RoomSelectPresenter( + mode = mode, + dataSource = RoomSelectSearchDataSource( + roomListService = roomListService, + coroutineDispatchers = testCoroutineDispatchers(), + ), +) diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt new file mode 100644 index 0000000000..9bdbae062f --- /dev/null +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/DefaultNotificationTroubleShootEntryPointTest.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.impl + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.troubleshoot.api.NotificationTroubleShootEntryPoint +import io.element.android.services.analytics.test.FakeScreenTracker +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultNotificationTroubleShootEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultNotificationTroubleShootEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + TroubleshootNotificationsNode( + buildContext = buildContext, + plugins = plugins, + presenter = createTroubleshootNotificationsPresenter(), + screenTracker = FakeScreenTracker(), + ) + } + val callback = object : NotificationTroubleShootEntryPoint.Callback { + override fun onDone() = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(TroubleshootNotificationsNode::class.java) + assertThat(result.plugins).contains(callback) + } +} diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt index 4b456fe494..211fa595b5 100644 --- a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/TroubleshootNotificationsPresenterTest.kt @@ -97,23 +97,23 @@ class TroubleshootNotificationsPresenterTest { assertThat(stateAfterStart.testSuiteState.mainState).isEqualTo(AsyncAction.Loading) } } - - private fun createTroubleshootTestSuite( - tests: Set = emptySet(), - currentPushProvider: String? = null, - ): TroubleshootTestSuite { - return TroubleshootTestSuite( - notificationTroubleshootTests = tests, - getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider), - analyticsService = FakeAnalyticsService(), - ) - } - - private fun createTroubleshootNotificationsPresenter( - troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(), - ): TroubleshootNotificationsPresenter { - return TroubleshootNotificationsPresenter( - troubleshootTestSuite = troubleshootTestSuite, - ) - } +} + +private fun createTroubleshootTestSuite( + tests: Set = emptySet(), + currentPushProvider: String? = null, +): TroubleshootTestSuite { + return TroubleshootTestSuite( + notificationTroubleshootTests = tests, + getCurrentPushProvider = FakeGetCurrentPushProvider(currentPushProvider), + analyticsService = FakeAnalyticsService(), + ) +} + +internal fun createTroubleshootNotificationsPresenter( + troubleshootTestSuite: TroubleshootTestSuite = createTroubleshootTestSuite(), +): TroubleshootNotificationsPresenter { + return TroubleshootNotificationsPresenter( + troubleshootTestSuite = troubleshootTestSuite, + ) } diff --git a/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt new file mode 100644 index 0000000000..9fb0e50309 --- /dev/null +++ b/libraries/troubleshoot/impl/src/test/kotlin/io/element/android/libraries/troubleshoot/impl/history/DefaultPushHistoryEntryPointTest.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.troubleshoot.impl.history + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.bumble.appyx.core.modality.BuildContext +import com.google.common.truth.Truth.assertThat +import io.element.android.libraries.matrix.api.core.EventId +import io.element.android.libraries.matrix.api.core.RoomId +import io.element.android.libraries.matrix.api.core.SessionId +import io.element.android.libraries.push.test.FakePushService +import io.element.android.libraries.troubleshoot.api.PushHistoryEntryPoint +import io.element.android.services.analytics.test.FakeScreenTracker +import io.element.android.tests.testutils.lambda.lambdaError +import io.element.android.tests.testutils.node.TestParentNode +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class DefaultPushHistoryEntryPointTest { + @Test + fun `test node builder`() { + val entryPoint = DefaultPushHistoryEntryPoint() + val parentNode = TestParentNode.create { buildContext, plugins -> + PushHistoryNode( + buildContext = buildContext, + plugins = plugins, + presenter = PushHistoryPresenter( + pushService = FakePushService(), + ), + screenTracker = FakeScreenTracker(), + ) + } + val callback = object : PushHistoryEntryPoint.Callback { + override fun onDone() = lambdaError() + override fun onItemClick(sessionId: SessionId, roomId: RoomId, eventId: EventId) = lambdaError() + } + val result = entryPoint.nodeBuilder(parentNode, BuildContext.root(null)) + .callback(callback) + .build() + assertThat(result).isInstanceOf(PushHistoryNode::class.java) + assertThat(result.plugins).contains(callback) + } +}