adding unit test to execute screenshot test with custom state

This commit is contained in:
Adam Brown 2022-08-30 14:12:10 +01:00
parent ace01876dd
commit eb8931c6da
8 changed files with 164 additions and 77 deletions

View File

@ -32,6 +32,7 @@ buildscript {
classpath 'org.owasp:dependency-check-gradle:7.1.1' classpath 'org.owasp:dependency-check-gradle:7.1.1'
classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10" classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10"
classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0" classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0"
classpath "com.karumi:shot:5.14.1"
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }

View File

@ -57,6 +57,7 @@ ext.groups = [
'com.facebook.flipper', 'com.facebook.flipper',
'com.facebook.fresco', 'com.facebook.fresco',
'com.facebook.infer.annotation', 'com.facebook.infer.annotation',
'com.facebook.testing.screenshot',
'com.facebook.soloader', 'com.facebook.soloader',
'com.facebook.stetho', 'com.facebook.stetho',
'com.facebook.yoga', 'com.facebook.yoga',
@ -97,6 +98,7 @@ ext.groups = [
'com.ibm.icu', 'com.ibm.icu',
'com.jakewharton.android.repackaged', 'com.jakewharton.android.repackaged',
'com.jakewharton.timber', 'com.jakewharton.timber',
'com.karumi',
'com.kgurgul.flipper', 'com.kgurgul.flipper',
'com.linkedin.dexmaker', 'com.linkedin.dexmaker',
'com.mapbox.mapboxsdk', 'com.mapbox.mapboxsdk',

View File

@ -9,6 +9,7 @@ apply plugin: 'kotlin-kapt'
apply plugin: 'com.likethesalad.stem' apply plugin: 'com.likethesalad.stem'
apply plugin: 'dagger.hilt.android.plugin' apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlinx-knit' apply plugin: 'kotlinx-knit'
apply plugin: 'shot'
if (project.hasProperty("coverage")) { if (project.hasProperty("coverage")) {
apply plugin: 'jacoco' apply plugin: 'jacoco'
@ -156,7 +157,8 @@ android {
buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\"" buildConfigField "String", "GIT_BRANCH_NAME", "\"${gitBranchName()}\""
buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\"" buildConfigField "String", "BUILD_NUMBER", "\"${buildNumber}\""
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunner "com.karumi.shot.ShotTestRunner"
// Keep abiFilter for the universalApk // Keep abiFilter for the universalApk
ndk { ndk {
@ -601,5 +603,5 @@ dependencies {
androidTestImplementation libs.mockk.mockkAndroid androidTestImplementation libs.mockk.mockkAndroid
androidTestUtil libs.androidx.orchestrator androidTestUtil libs.androidx.orchestrator
debugImplementation libs.androidx.fragmentTesting debugImplementation libs.androidx.fragmentTesting
androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.7.10" androidTestImplementation "org.jetbrains.kotlin:kotlin-reflect:1.6.10"
} }

View File

@ -0,0 +1,85 @@
/*
* 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.screenshot
import android.os.Bundle
import androidx.test.core.app.ActivityScenario
import androidx.test.platform.app.InstrumentationRegistry
import com.airbnb.mvrx.Success
import com.airbnb.mvrx.launcher.MavericksLauncherMockActivity
import com.airbnb.mvrx.mocking.MockableMavericksView
import com.airbnb.mvrx.mocking.getMockVariants
import com.airbnb.mvrx.mocking.mockSingleViewModel
import com.karumi.shot.ActivityScenarioUtils.waitForActivity
import com.karumi.shot.ScreenshotTest
import im.vector.app.features.roomprofile.RoomProfileFragment
import im.vector.app.features.roomprofile.mocks.mockRoomProfileArgs
import im.vector.app.features.roomprofile.mocks.mockRoomProfileViewState
import org.junit.Test
import kotlin.reflect.KClass
class MvRxScreenshotTest : ScreenshotTest {
private val context = InstrumentationRegistry.getInstrumentation().targetContext
@Test
fun defaultRoomProfileFragmentScreenshotTest() {
val mock = MockRoomProfileFragment::class.getMock("Default state")
val scenario = ActivityScenario.launch<MavericksLauncherMockActivity>(
MavericksLauncherMockActivity.intent(context, mock)
)
compareScreenshot(scenario.waitForActivity())
}
@Test
fun anotherRoomProfileFragmentScreenshotTest() {
val mock = MockRoomProfileFragment::class.getMock("my-state")
val scenario = ActivityScenario.launch<MavericksLauncherMockActivity>(
MavericksLauncherMockActivity.intent(context, mock)
)
compareScreenshot(scenario.waitForActivity())
}
}
fun <T : MockableMavericksView> KClass<T>.getMock(name: String) = getMockVariants(this.java)!!.first { it.mock.name == name }
class MockRoomProfileFragment : RoomProfileFragment(), MockableMavericksView {
override fun provideMocks() = mockSingleViewModel(
viewModelReference = MockRoomProfileFragment::roomProfileViewModel,
defaultState = mockRoomProfileViewState,
defaultArgs = mockRoomProfileArgs,
) {
state("my-state") {
val summary = (mockRoomProfileViewState.roomSummary as Success)().copy(
displayName = "another state"
)
mockRoomProfileViewState.copy(
roomSummary = Success(summary)
)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
registerMockPrinter()
super.onCreate(savedInstanceState)
}
}

View File

@ -29,9 +29,6 @@ import androidx.fragment.app.setFragmentResultListener
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import com.airbnb.mvrx.args import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.mocking.MavericksViewMocks
import com.airbnb.mvrx.mocking.MockableMavericksView
import com.airbnb.mvrx.mocking.mockSingleViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@ -56,8 +53,6 @@ import im.vector.app.features.home.room.detail.RoomDetailPendingActionStore
import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet import im.vector.app.features.home.room.detail.upgrade.MigrateRoomBottomSheet
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedAction
import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel
import im.vector.app.features.roomprofile.mocks.mockRoomProfileArgs
import im.vector.app.features.roomprofile.mocks.mockRoomProfileViewState
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
@ -72,9 +67,8 @@ data class RoomProfileArgs(
) : Parcelable ) : Parcelable
@AndroidEntryPoint @AndroidEntryPoint
class RoomProfileFragment : open class RoomProfileFragment :
VectorBaseFragment<FragmentMatrixProfileBinding>(), VectorBaseFragment<FragmentMatrixProfileBinding>(),
MockableMavericksView,
RoomProfileController.Callback, RoomProfileController.Callback,
VectorMenuProvider { VectorMenuProvider {
@ -87,16 +81,10 @@ class RoomProfileFragment :
private val roomProfileArgs: RoomProfileArgs by args() private val roomProfileArgs: RoomProfileArgs by args()
private lateinit var roomListQuickActionsSharedActionViewModel: RoomListQuickActionsSharedActionViewModel private lateinit var roomListQuickActionsSharedActionViewModel: RoomListQuickActionsSharedActionViewModel
private lateinit var roomProfileSharedActionViewModel: RoomProfileSharedActionViewModel private lateinit var roomProfileSharedActionViewModel: RoomProfileSharedActionViewModel
private val roomProfileViewModel: RoomProfileViewModel by fragmentViewModel() val roomProfileViewModel: RoomProfileViewModel by fragmentViewModel()
private var appBarStateChangeListener: AppBarStateChangeListener? = null private var appBarStateChangeListener: AppBarStateChangeListener? = null
override fun provideMocks() = mockSingleViewModel(
viewModelReference = RoomProfileFragment::roomProfileViewModel,
defaultState = mockRoomProfileViewState,
defaultArgs = mockRoomProfileArgs
){}
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentMatrixProfileBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentMatrixProfileBinding {
return FragmentMatrixProfileBinding.inflate(inflater, container, false) return FragmentMatrixProfileBinding.inflate(inflater, container, false)
} }
@ -105,7 +93,6 @@ class RoomProfileFragment :
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
registerMockPrinter()
analyticsScreenName = MobileScreen.ScreenName.RoomDetails analyticsScreenName = MobileScreen.ScreenName.RoomDetails
setFragmentResultListener(MigrateRoomBottomSheet.REQUEST_KEY) { _, bundle -> setFragmentResultListener(MigrateRoomBottomSheet.REQUEST_KEY) { _, bundle ->
bundle.getString(MigrateRoomBottomSheet.BUNDLE_KEY_REPLACEMENT_ROOM)?.let { replacementRoomId -> bundle.getString(MigrateRoomBottomSheet.BUNDLE_KEY_REPLACEMENT_ROOM)?.let { replacementRoomId ->

View File

@ -19,7 +19,8 @@ import org.matrix.android.sdk.api.session.room.model.create.RoomCreateContent
import org.matrix.android.sdk.api.session.room.sender.SenderInfo import org.matrix.android.sdk.api.session.room.sender.SenderInfo
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
val mockRoomProfileViewState by lazy { RoomProfileViewState( val mockRoomProfileViewState by lazy {
RoomProfileViewState(
roomId = "!CWLUCoEWXSFyTCOtfL:matrix.org", roomId = "!CWLUCoEWXSFyTCOtfL:matrix.org",
roomSummary = Success( roomSummary = Success(
value = RoomSummary( value = RoomSummary(
@ -35,7 +36,13 @@ latestPreviewableEvent = TimelineEvent(
root = Event( root = Event(
type = "m.room.encrypted", type = "m.room.encrypted",
eventId = "\$zo2MIeXtdl9dWNhz1cbY3YT55rlpQLG8XpYBTFN-JXI", eventId = "\$zo2MIeXtdl9dWNhz1cbY3YT55rlpQLG8XpYBTFN-JXI",
content = mutableMapOf("algorithm" to "m.megolm.v1.aes-sha2","ciphertext" to "AwgAEoADprWrq3ZJ4BLD/w0+Lx9H/3mXZpnEQdgbF2FoWOPB1fuki6/1w7vikL1Sb6rP5AwMuA4TPJQ14Pl++/TCGCUzRoZE9m8TsYe0nQXKb2VWRDB6u7i1ib27l3epbtQAIOYfKuCg6MnbMmadef9fEA1K4lHl3xxf0SdWF9PQKGq3nf9rhcZwa3AZW+FDepI094NO98bTHmssKJ5YTp1ChStjALy4FwdcfanlD5WWPHbKqij/RIC63FNAspIOUeb3AkBmcAdoUctBrxXml+NpJKKCGKxXvFudeSkiqHMG","device_id" to "QBOXOIATIX","sender_key" to "dGWOgnrcFYOdsYAfwvKJQcDr4dwuZ0R743B3ZlGSMWU","session_id" to "Eg1c1yyhczbhGt2baH4m6qI4TpJxN0Kb59TxZ3JY5lE"), content = mutableMapOf(
"algorithm" to "m.megolm.v1.aes-sha2",
"ciphertext" to "AwgAEoADprWrq3ZJ4BLD/w0+Lx9H/3mXZpnEQdgbF2FoWOPB1fuki6/1w7vikL1Sb6rP5AwMuA4TPJQ14Pl++/TCGCUzRoZE9m8TsYe0nQXKb2VWRDB6u7i1ib27l3epbtQAIOYfKuCg6MnbMmadef9fEA1K4lHl3xxf0SdWF9PQKGq3nf9rhcZwa3AZW+FDepI094NO98bTHmssKJ5YTp1ChStjALy4FwdcfanlD5WWPHbKqij/RIC63FNAspIOUeb3AkBmcAdoUctBrxXml+NpJKKCGKxXvFudeSkiqHMG",
"device_id" to "QBOXOIATIX",
"sender_key" to "dGWOgnrcFYOdsYAfwvKJQcDr4dwuZ0R743B3ZlGSMWU",
"session_id" to "Eg1c1yyhczbhGt2baH4m6qI4TpJxN0Kb59TxZ3JY5lE"
),
originServerTs = 1661232614808, originServerTs = 1661232614808,
senderId = "@DatseMultimedia:matrix.org", senderId = "@DatseMultimedia:matrix.org",
roomId = "!CWLUCoEWXSFyTCOtfL:matrix.org", roomId = "!CWLUCoEWXSFyTCOtfL:matrix.org",
@ -75,9 +82,12 @@ roomVersion = "5",
predecessor = Predecessor(roomId = "!UCnwUWwIKhcpaPTHtR:sw1v.org", eventId = "\$1574382534206ivbfT:matrix.org") predecessor = Predecessor(roomId = "!UCnwUWwIKhcpaPTHtR:sw1v.org", eventId = "\$1574382534206ivbfT:matrix.org")
) )
), ),
bannedMembership = Success(value = listOf( bannedMembership = Success(
value = listOf(
)), )
),
actionPermissions = RoomProfileViewState.ActionPermissions(), actionPermissions = RoomProfileViewState.ActionPermissions(),
recommendedRoomVersion = "9" recommendedRoomVersion = "9"
) } )
}