refactor: move test functions to automation and storage utilities, add compose component activity dependency and create group fragment content descriptions, add compose only testing for create group logic, update protos to match latest for chunk 2
parent
f69e3846e3
commit
e79a980f2c
@ -1,8 +1,10 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="network.loki.messenger.test">
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner"
|
||||
android:required="false" />
|
||||
|
||||
<activity android:name="androidx.activity.ComponentActivity"/>
|
||||
|
||||
</application>
|
||||
</manifest>
|
@ -0,0 +1,63 @@
|
||||
package network.loki.messenger
|
||||
|
||||
import androidx.compose.ui.test.hasContentDescriptionExactly
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.hamcrest.CoreMatchers.*
|
||||
import org.hamcrest.MatcherAssert.*
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.groups.CreateGroup
|
||||
import org.thoughtcrime.securesms.groups.CreateGroupFragment
|
||||
import org.thoughtcrime.securesms.groups.CreateGroupState
|
||||
import org.thoughtcrime.securesms.ui.AppTheme
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@SmallTest
|
||||
class CreateGroupTests {
|
||||
|
||||
@get:Rule
|
||||
val composeTest = createComposeRule()
|
||||
|
||||
@Test
|
||||
fun testNavigateToCreateGroup() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
// Accessibility IDs
|
||||
val nameDesc = application.getString(R.string.AccessibilityId_closed_group_edit_group_name)
|
||||
val buttonDesc = application.getString(R.string.AccessibilityId_create_closed_group_create_button)
|
||||
|
||||
lateinit var postedGroup: CreateGroupState
|
||||
var backPressed = false
|
||||
var closePressed = false
|
||||
|
||||
composeTest.setContent {
|
||||
AppTheme {
|
||||
CreateGroup(
|
||||
viewState = CreateGroupFragment.ViewState.DEFAULT,
|
||||
createGroupState = CreateGroupState("", "", emptySet()),
|
||||
onCreate = { submitted ->
|
||||
postedGroup = submitted
|
||||
},
|
||||
onBack = { backPressed = true },
|
||||
onClose = { closePressed = true })
|
||||
}
|
||||
}
|
||||
|
||||
with(composeTest) {
|
||||
onNode(hasContentDescriptionExactly(nameDesc)).performTextInput("Name")
|
||||
onNode(hasContentDescriptionExactly(buttonDesc)).performClick()
|
||||
}
|
||||
|
||||
assertThat(postedGroup.groupName, equalTo("Name"))
|
||||
assertThat(backPressed, equalTo(false))
|
||||
assertThat(closePressed, equalTo(false))
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package network.loki.messenger.util
|
||||
|
||||
import android.Manifest
|
||||
import android.view.View
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.UiController
|
||||
import androidx.test.espresso.ViewAction
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.matcher.ViewMatchers
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.adevinta.android.barista.interaction.PermissionGranter
|
||||
import network.loki.messenger.R
|
||||
import org.hamcrest.Matcher
|
||||
import org.hamcrest.Matchers
|
||||
import org.session.libsession.messaging.sending_receiving.link_preview.LinkPreview
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
|
||||
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBar
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
|
||||
fun setupLoggedInState(hasViewedSeed: Boolean = false) {
|
||||
// landing activity
|
||||
onView(ViewMatchers.withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
// session ID - register activity
|
||||
onView(ViewMatchers.withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
// display name selection
|
||||
onView(ViewMatchers.withId(R.id.displayNameEditText))
|
||||
.perform(ViewActions.typeText("test-user123"))
|
||||
onView(ViewMatchers.withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
// PN select
|
||||
if (hasViewedSeed) {
|
||||
// has viewed seed is set to false after register activity
|
||||
TextSecurePreferences.setHasViewedSeed(
|
||||
InstrumentationRegistry.getInstrumentation().targetContext,
|
||||
true
|
||||
)
|
||||
}
|
||||
onView(ViewMatchers.withId(R.id.backgroundPollingOptionView))
|
||||
.perform(ViewActions.click())
|
||||
onView(ViewMatchers.withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
// allow notification permission
|
||||
PermissionGranter.allowPermissionsIfNeeded(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
fun ConversationActivityV2.sendMessage(messageToSend: String, linkPreview: LinkPreview? = null) {
|
||||
// assume in chat activity
|
||||
onView(
|
||||
Matchers.allOf(
|
||||
ViewMatchers.isDescendantOfA(ViewMatchers.withId(R.id.inputBar)),
|
||||
ViewMatchers.withId(R.id.inputBarEditText)
|
||||
)
|
||||
).perform(ViewActions.replaceText(messageToSend))
|
||||
if (linkPreview != null) {
|
||||
val glide = GlideApp.with(this)
|
||||
this.findViewById<InputBar>(R.id.inputBar).updateLinkPreviewDraft(glide, linkPreview)
|
||||
}
|
||||
onView(
|
||||
Matchers.allOf(
|
||||
ViewMatchers.isDescendantOfA(ViewMatchers.withId(R.id.inputBar)),
|
||||
InputBarButtonDrawableMatcher.inputButtonWithDrawable(R.drawable.ic_arrow_up)
|
||||
)
|
||||
).perform(ViewActions.click())
|
||||
// TODO: text can flaky on cursor reload, figure out a better way to wait for the UI to settle with new data
|
||||
onView(ViewMatchers.isRoot()).perform(waitFor(500))
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform action of waiting for a specific time.
|
||||
*/
|
||||
fun waitFor(millis: Long): ViewAction {
|
||||
return object : ViewAction {
|
||||
override fun getConstraints(): Matcher<View>? {
|
||||
return ViewMatchers.isRoot()
|
||||
}
|
||||
|
||||
override fun getDescription(): String = "Wait for $millis milliseconds."
|
||||
|
||||
override fun perform(uiController: UiController, view: View?) {
|
||||
uiController.loopMainThreadForAtLeast(millis)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package network.loki.messenger.util
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.mockito.kotlin.spy
|
||||
import org.session.libsignal.utilities.hexEncodedPublicKey
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||
import org.thoughtcrime.securesms.database.Storage
|
||||
import kotlin.random.Random
|
||||
|
||||
fun maybeGetUserInfo(): Pair<ByteArray, String>? {
|
||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
val prefs = appContext.prefs
|
||||
val localUserPublicKey = prefs.getLocalNumber()
|
||||
val secretKey = with(appContext) {
|
||||
val edKey = KeyPairUtilities.getUserED25519KeyPair(this) ?: return null
|
||||
edKey.secretKey.asBytes
|
||||
}
|
||||
return if (localUserPublicKey == null || secretKey == null) null
|
||||
else secretKey to localUserPublicKey
|
||||
}
|
||||
|
||||
fun ApplicationContext.applySpiedStorage(): Storage {
|
||||
val storageSpy = spy(storage)!!
|
||||
storage = storageSpy
|
||||
return storageSpy
|
||||
}
|
||||
|
||||
fun randomSeedBytes() = (0 until 16).map { Random.nextInt(UByte.MAX_VALUE.toInt()).toByte() }
|
||||
fun randomKeyPair() = KeyPairUtilities.generate(randomSeedBytes().toByteArray())
|
||||
fun randomSessionId() = randomKeyPair().x25519KeyPair.hexEncodedPublicKey
|
Loading…
Reference in New Issue