Merge pull request #7322 from vector-im/feature/nfe/app_layout_tests
new app layout home screen unit tests
This commit is contained in:
commit
62c07fa02c
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home
|
||||
|
||||
import com.airbnb.mvrx.test.MavericksTestRule
|
||||
import im.vector.app.features.home.room.list.home.invites.InvitesAction
|
||||
import im.vector.app.features.home.room.list.home.invites.InvitesViewEvents
|
||||
import im.vector.app.features.home.room.list.home.invites.InvitesViewModel
|
||||
import im.vector.app.features.home.room.list.home.invites.InvitesViewState
|
||||
import im.vector.app.test.fakes.FakeDrawableProvider
|
||||
import im.vector.app.test.fakes.FakeSession
|
||||
import im.vector.app.test.fakes.FakeStringProvider
|
||||
import im.vector.app.test.fixtures.RoomSummaryFixture
|
||||
import im.vector.app.test.test
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.mockkStatic
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
|
||||
class InvitesViewModelTest {
|
||||
|
||||
@get:Rule
|
||||
val mavericksTestRule = MavericksTestRule()
|
||||
|
||||
private val fakeSession = FakeSession()
|
||||
private val fakeStringProvider = FakeStringProvider()
|
||||
private val fakeDrawableProvider = FakeDrawableProvider()
|
||||
|
||||
private var initialState = InvitesViewState()
|
||||
private lateinit var viewModel: InvitesViewModel
|
||||
|
||||
private val anInvite = RoomSummaryFixture.aRoomSummary("invite")
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockkStatic("org.matrix.android.sdk.flow.FlowSessionKt")
|
||||
|
||||
every {
|
||||
fakeSession.fakeRoomService.getPagedRoomSummariesLive(
|
||||
queryParams = match {
|
||||
it.memberships == listOf(Membership.INVITE)
|
||||
},
|
||||
pagedListConfig = any(),
|
||||
sortOrder = any()
|
||||
)
|
||||
} returns mockk()
|
||||
|
||||
viewModelWith(initialState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when invite accepted then membership map is updated and open event posted`() = runTest {
|
||||
val test = viewModel.test()
|
||||
|
||||
viewModel.handle(InvitesAction.AcceptInvitation(anInvite))
|
||||
|
||||
test.assertEvents(
|
||||
InvitesViewEvents.OpenRoom(
|
||||
roomSummary = anInvite,
|
||||
shouldCloseInviteView = false,
|
||||
isInviteAlreadySelected = true
|
||||
)
|
||||
).finish()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when invite rejected then membership map is updated and open event posted`() = runTest {
|
||||
coEvery { fakeSession.roomService().leaveRoom(any(), any()) } returns Unit
|
||||
|
||||
viewModel.handle(InvitesAction.RejectInvitation(anInvite))
|
||||
|
||||
coVerify {
|
||||
fakeSession.roomService().leaveRoom(anInvite.roomId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun viewModelWith(state: InvitesViewState) {
|
||||
InvitesViewModel(
|
||||
state,
|
||||
session = fakeSession,
|
||||
stringProvider = fakeStringProvider.instance,
|
||||
drawableProvider = fakeDrawableProvider.instance,
|
||||
).also {
|
||||
viewModel = it
|
||||
initialState = state
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.home
|
||||
|
||||
import android.widget.ImageView
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.airbnb.mvrx.test.MavericksTestRule
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.StateView
|
||||
import im.vector.app.features.displayname.getBestName
|
||||
import im.vector.app.features.home.room.list.home.HomeRoomListAction
|
||||
import im.vector.app.features.home.room.list.home.HomeRoomListViewModel
|
||||
import im.vector.app.features.home.room.list.home.HomeRoomListViewState
|
||||
import im.vector.app.features.home.room.list.home.header.HomeRoomFilter
|
||||
import im.vector.app.test.fakes.FakeAnalyticsTracker
|
||||
import im.vector.app.test.fakes.FakeDrawableProvider
|
||||
import im.vector.app.test.fakes.FakeHomeLayoutPreferencesStore
|
||||
import im.vector.app.test.fakes.FakeSession
|
||||
import im.vector.app.test.fakes.FakeSpaceStateHandler
|
||||
import im.vector.app.test.fakes.FakeStringProvider
|
||||
import im.vector.app.test.fixtures.RoomSummaryFixture.aRoomSummary
|
||||
import im.vector.app.test.test
|
||||
import io.mockk.every
|
||||
import io.mockk.mockkStatic
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.matrix.android.sdk.api.query.SpaceFilter
|
||||
import org.matrix.android.sdk.api.session.getUserOrDefault
|
||||
import org.matrix.android.sdk.api.session.room.model.Membership
|
||||
import org.matrix.android.sdk.api.util.Optional
|
||||
import org.matrix.android.sdk.api.util.toMatrixItem
|
||||
import org.matrix.android.sdk.flow.FlowSession
|
||||
|
||||
class RoomsListViewModelTest {
|
||||
|
||||
@get:Rule
|
||||
val mavericksTestRule = MavericksTestRule()
|
||||
|
||||
@get:Rule
|
||||
var rule = InstantTaskExecutorRule()
|
||||
|
||||
private val fakeSession = FakeSession()
|
||||
private val fakeAnalyticsTracker = FakeAnalyticsTracker()
|
||||
private val fakeStringProvider = FakeStringProvider()
|
||||
private val fakeDrawableProvider = FakeDrawableProvider()
|
||||
private val fakeSpaceStateHandler = FakeSpaceStateHandler()
|
||||
private val fakeHomeLayoutPreferencesStore = FakeHomeLayoutPreferencesStore()
|
||||
|
||||
private var initialState = HomeRoomListViewState()
|
||||
private lateinit var viewModel: HomeRoomListViewModel
|
||||
private lateinit var fakeFLowSession: FlowSession
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
mockkStatic("org.matrix.android.sdk.flow.FlowSessionKt")
|
||||
fakeFLowSession = fakeSession.givenFlowSession()
|
||||
|
||||
every { fakeSpaceStateHandler.getSelectedSpaceFlow() } returns flowOf(Optional.empty())
|
||||
every { fakeSpaceStateHandler.getCurrentSpace() } returns null
|
||||
every { fakeFLowSession.liveRoomSummaries(any(), any()) } returns flowOf(emptyList())
|
||||
|
||||
val roomA = aRoomSummary("room_a")
|
||||
val roomB = aRoomSummary("room_b")
|
||||
val roomC = aRoomSummary("room_c")
|
||||
val allRooms = listOf(roomA, roomB, roomC)
|
||||
|
||||
every {
|
||||
fakeFLowSession.liveRoomSummaries(
|
||||
match {
|
||||
it.roomCategoryFilter == null &&
|
||||
it.roomTagQueryFilter == null &&
|
||||
it.memberships == listOf(Membership.JOIN) &&
|
||||
it.spaceFilter is SpaceFilter.NoFilter
|
||||
}, any()
|
||||
)
|
||||
} returns flowOf(allRooms)
|
||||
|
||||
viewModelWith(initialState)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when recents are enabled then updates state`() = runTest {
|
||||
val fakeFLowSession = fakeSession.givenFlowSession()
|
||||
every { fakeFLowSession.liveRoomSummaries(any()) } returns flowOf(emptyList())
|
||||
val test = viewModel.test()
|
||||
|
||||
val roomA = aRoomSummary("room_a")
|
||||
val roomB = aRoomSummary("room_b")
|
||||
val roomC = aRoomSummary("room_c")
|
||||
val recentRooms = listOf(roomA, roomB, roomC)
|
||||
|
||||
every { fakeFLowSession.liveBreadcrumbs(any()) } returns flowOf(recentRooms)
|
||||
fakeHomeLayoutPreferencesStore.givenRecentsEnabled(true)
|
||||
|
||||
val userName = fakeSession.getUserOrDefault(fakeSession.myUserId).toMatrixItem().getBestName()
|
||||
val allEmptyState = StateView.State.Empty(
|
||||
title = fakeStringProvider.instance.getString(R.string.home_empty_no_rooms_title, userName),
|
||||
message = fakeStringProvider.instance.getString(R.string.home_empty_no_rooms_message),
|
||||
image = fakeDrawableProvider.instance.getDrawable(R.drawable.ill_empty_all_chats),
|
||||
isBigImage = true
|
||||
)
|
||||
|
||||
test.assertLatestState(
|
||||
initialState.copy(emptyState = allEmptyState, headersData = initialState.headersData.copy(recents = recentRooms))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when filter tabs are enabled then updates state`() = runTest {
|
||||
val test = viewModel.test()
|
||||
|
||||
fakeHomeLayoutPreferencesStore.givenFiltersEnabled(true)
|
||||
|
||||
val filtersData = mutableListOf(
|
||||
HomeRoomFilter.ALL,
|
||||
HomeRoomFilter.UNREADS
|
||||
)
|
||||
|
||||
val userName = fakeSession.getUserOrDefault(fakeSession.myUserId).toMatrixItem().getBestName()
|
||||
val allEmptyState = StateView.State.Empty(
|
||||
title = fakeStringProvider.instance.getString(R.string.home_empty_no_rooms_title, userName),
|
||||
message = fakeStringProvider.instance.getString(R.string.home_empty_no_rooms_message),
|
||||
image = fakeDrawableProvider.instance.getDrawable(R.drawable.ill_empty_all_chats),
|
||||
isBigImage = true
|
||||
)
|
||||
|
||||
test.assertLatestState(
|
||||
initialState.copy(emptyState = allEmptyState, headersData = initialState.headersData.copy(filtersList = filtersData))
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when filter tab is selected then updates state`() = runTest {
|
||||
val test = viewModel.test()
|
||||
|
||||
val aFilter = HomeRoomFilter.UNREADS
|
||||
viewModel.handle(HomeRoomListAction.ChangeRoomFilter(filter = aFilter))
|
||||
|
||||
val unreadsEmptyState = StateView.State.Empty(
|
||||
title = fakeStringProvider.instance.getString(R.string.home_empty_no_unreads_title),
|
||||
message = fakeStringProvider.instance.getString(R.string.home_empty_no_unreads_message),
|
||||
image = fakeDrawableProvider.instance.getDrawable(R.drawable.ill_empty_unreads),
|
||||
isBigImage = true,
|
||||
imageScaleType = ImageView.ScaleType.CENTER_INSIDE
|
||||
)
|
||||
|
||||
test.assertLatestState(
|
||||
initialState.copy(emptyState = unreadsEmptyState, headersData = initialState.headersData.copy(currentFilter = aFilter))
|
||||
)
|
||||
}
|
||||
|
||||
private fun viewModelWith(state: HomeRoomListViewState) {
|
||||
HomeRoomListViewModel(
|
||||
state,
|
||||
session = fakeSession,
|
||||
spaceStateHandler = fakeSpaceStateHandler,
|
||||
preferencesStore = fakeHomeLayoutPreferencesStore.instance,
|
||||
stringProvider = fakeStringProvider.instance,
|
||||
drawableProvider = fakeDrawableProvider.instance,
|
||||
analyticsTracker = fakeAnalyticsTracker
|
||||
|
||||
).also {
|
||||
viewModel = it
|
||||
initialState = state
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (c) 2021 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.core.resources.DrawableProvider
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
||||
class FakeDrawableProvider {
|
||||
val instance = mockk<DrawableProvider>()
|
||||
|
||||
init {
|
||||
every { instance.getDrawable(any()) } returns mockk()
|
||||
every { instance.getDrawable(any(), any()) } returns mockk()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.features.home.room.list.home.HomeLayoutPreferencesStore
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
|
||||
class FakeHomeLayoutPreferencesStore {
|
||||
|
||||
private val _areRecentsEnabledFlow = MutableSharedFlow<Boolean>()
|
||||
private val _areFiltersEnabledFlow = MutableSharedFlow<Boolean>()
|
||||
private val _isAZOrderingEnabledFlow = MutableSharedFlow<Boolean>()
|
||||
|
||||
val instance = mockk<HomeLayoutPreferencesStore>(relaxed = true) {
|
||||
every { areRecentsEnabledFlow } returns _areRecentsEnabledFlow
|
||||
every { areFiltersEnabledFlow } returns _areFiltersEnabledFlow
|
||||
every { isAZOrderingEnabledFlow } returns _isAZOrderingEnabledFlow
|
||||
}
|
||||
|
||||
suspend fun givenRecentsEnabled(enabled: Boolean) {
|
||||
_areRecentsEnabledFlow.emit(enabled)
|
||||
}
|
||||
|
||||
suspend fun givenFiltersEnabled(enabled: Boolean) {
|
||||
_areFiltersEnabledFlow.emit(enabled)
|
||||
}
|
||||
}
|
|
@ -30,4 +30,8 @@ class FakeRoomService(
|
|||
fun getRoomSummaryReturns(roomSummary: RoomSummary?) {
|
||||
every { getRoomSummary(any()) } returns roomSummary
|
||||
}
|
||||
|
||||
fun set(roomSummary: RoomSummary?) {
|
||||
every { getRoomSummary(any()) } returns roomSummary
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ class FakeSession(
|
|||
val fakeSharedSecretStorageService: FakeSharedSecretStorageService = FakeSharedSecretStorageService(),
|
||||
val fakeRoomService: FakeRoomService = FakeRoomService(),
|
||||
val fakePushersService: FakePushersService = FakePushersService(),
|
||||
val fakeUserService: FakeUserService = FakeUserService(),
|
||||
private val fakeEventService: FakeEventService = FakeEventService(),
|
||||
val fakeSessionAccountDataService: FakeSessionAccountDataService = FakeSessionAccountDataService()
|
||||
) : Session by mockk(relaxed = true) {
|
||||
|
@ -62,6 +63,7 @@ class FakeSession(
|
|||
override fun eventService() = fakeEventService
|
||||
override fun pushersService() = fakePushersService
|
||||
override fun accountDataService() = fakeSessionAccountDataService
|
||||
override fun userService() = fakeUserService
|
||||
|
||||
fun givenVectorStore(vectorSessionStore: VectorSessionStore) {
|
||||
coEvery {
|
||||
|
@ -92,8 +94,10 @@ class FakeSession(
|
|||
/**
|
||||
* Do not forget to call mockkStatic("org.matrix.android.sdk.flow.FlowSessionKt") in the setup method of the tests.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
fun givenFlowSession(): FlowSession {
|
||||
val fakeFlowSession = mockk<FlowSession>()
|
||||
|
||||
every { flow() } returns fakeFlowSession
|
||||
return fakeFlowSession
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package im.vector.app.test.fakes
|
||||
|
||||
import im.vector.app.core.resources.StringProvider
|
||||
import io.mockk.InternalPlatformDsl.toStr
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
|
||||
|
@ -27,6 +28,9 @@ class FakeStringProvider {
|
|||
every { instance.getString(any()) } answers {
|
||||
"test-${args[0]}"
|
||||
}
|
||||
every { instance.getString(any(), any()) } answers {
|
||||
"test-${args[0]}-${args[1].toStr()}"
|
||||
}
|
||||
|
||||
every { instance.getQuantityString(any(), any(), any()) } answers {
|
||||
"test-${args[0]}-${args[1]}"
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.test.fakes
|
||||
|
||||
import io.mockk.every
|
||||
import io.mockk.mockk
|
||||
import io.mockk.slot
|
||||
import org.matrix.android.sdk.api.session.user.UserService
|
||||
import org.matrix.android.sdk.api.session.user.model.User
|
||||
|
||||
class FakeUserService : UserService by mockk() {
|
||||
|
||||
private val userIdSlot = slot<String>()
|
||||
|
||||
init {
|
||||
every { getUser(capture(userIdSlot)) } answers { User(userId = userIdSlot.captured) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue