mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
fix: Home activity crash handling from the seed view optimisations. added tests for that plus rendering URL crash
This commit is contained in:
parent
b9cf70ec3a
commit
bf6c2d29f1
@ -127,19 +127,30 @@ dependencies {
|
||||
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
|
||||
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
|
||||
testImplementation 'androidx.test:core:1.3.0'
|
||||
androidTestImplementation 'androidx.multidex:multidex:2.0.1'
|
||||
androidTestImplementation 'androidx.multidex:multidex-instrumentation:2.0.0'
|
||||
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
|
||||
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
|
||||
androidTestImplementation ('org.assertj:assertj-core:1.7.1') {
|
||||
exclude group: 'org.hamcrest', module: 'hamcrest-core'
|
||||
}
|
||||
androidTestImplementation ('com.squareup.assertj:assertj-android:1.1.1') {
|
||||
exclude group: 'org.hamcrest', module: 'hamcrest-core'
|
||||
exclude group: 'com.android.support', module: 'support-annotations'
|
||||
}
|
||||
testImplementation 'org.robolectric:robolectric:4.2.1'
|
||||
testImplementation 'org.robolectric:shadows-multidex:4.2'
|
||||
// Core library
|
||||
androidTestImplementation 'androidx.test:core:1.4.0'
|
||||
|
||||
// AndroidJUnitRunner and JUnit Rules
|
||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.4.0'
|
||||
|
||||
// Assertions
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.ext:truth:1.4.0'
|
||||
androidTestImplementation 'com.google.truth:truth:1.0'
|
||||
|
||||
// Espresso dependencies
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-web:3.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.4.0'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.4.0'
|
||||
androidTestUtil 'androidx.test:orchestrator:1.4.0'
|
||||
|
||||
testImplementation 'org.robolectric:robolectric:4.4'
|
||||
testImplementation 'org.robolectric:shadows-multidex:4.4'
|
||||
}
|
||||
|
||||
def canonicalVersionCode = 217
|
||||
@ -209,6 +220,14 @@ android {
|
||||
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
|
||||
|
||||
resConfigs autoResConfig()
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
// The following argument makes the Android Test Orchestrator run its
|
||||
// "pm clear" command after each test invocation. This command ensures
|
||||
// that the app's state is completely cleared between tests.
|
||||
testInstrumentationRunnerArguments clearPackageData: 'true'
|
||||
testOptions {
|
||||
execution 'ANDROIDX_TEST_ORCHESTRATOR'
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
8
app/src/androidTest/AndroidManifest.xml
Normal file
8
app/src/androidTest/AndroidManifest.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="network.loki.messenger">
|
||||
<application>
|
||||
<uses-library android:name="android.test.runner"
|
||||
android:required="false" />
|
||||
</application>
|
||||
</manifest>
|
@ -0,0 +1,100 @@
|
||||
package network.loki.messenger
|
||||
|
||||
import android.content.ClipboardManager
|
||||
import android.content.Context
|
||||
import androidx.test.espresso.Espresso.onView
|
||||
import androidx.test.espresso.Espresso.pressBack
|
||||
import androidx.test.espresso.action.ViewActions
|
||||
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
|
||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.LargeTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import network.loki.messenger.util.InputBarButtonDrawableMatcher.Companion.inputButtonWithDrawable
|
||||
import network.loki.messenger.util.NewConversationButtonDrawableMatcher.Companion.newConversationButtonWithDrawable
|
||||
import org.hamcrest.Matchers.allOf
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.thoughtcrime.securesms.home.HomeActivity
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@LargeTest
|
||||
class HomeActivityTests {
|
||||
|
||||
@get:Rule
|
||||
var activityRule = ActivityScenarioRule(HomeActivity::class.java)
|
||||
|
||||
private fun sendMessage(messageToSend: String) {
|
||||
// assume in chat activity
|
||||
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),withId(R.id.inputBarEditText))).perform(ViewActions.replaceText(messageToSend))
|
||||
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),inputButtonWithDrawable(R.drawable.ic_arrow_up))).perform(ViewActions.click())
|
||||
}
|
||||
|
||||
private fun setupLoggedInState(hasViewedSeed: Boolean = false) {
|
||||
// landing activity
|
||||
onView(withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
// session ID - register activity
|
||||
onView(withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
// display name selection
|
||||
onView(withId(R.id.displayNameEditText)).perform(ViewActions.typeText("test-user123"))
|
||||
onView(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(withId(R.id.backgroundPollingOptionView)).perform(ViewActions.click())
|
||||
onView(withId(R.id.registerButton)).perform(ViewActions.click())
|
||||
}
|
||||
|
||||
private fun goToMyChat() {
|
||||
onView(newConversationButtonWithDrawable(R.drawable.ic_plus)).perform(ViewActions.click())
|
||||
onView(newConversationButtonWithDrawable(R.drawable.ic_message)).perform(ViewActions.click())
|
||||
// new chat
|
||||
onView(withId(R.id.copyButton)).perform(ViewActions.click())
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val copied = clipboardManager.primaryClip!!.getItemAt(0).text
|
||||
onView(withId(R.id.publicKeyEditText)).perform(ViewActions.typeText(copied.toString()))
|
||||
onView(withId(R.id.createPrivateChatButton)).perform(ViewActions.click())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testLaunches_dismiss_seedView() {
|
||||
setupLoggedInState()
|
||||
onView(allOf(withId(R.id.button), isDescendantOfA(withId(R.id.seedReminderView)))).perform(ViewActions.click())
|
||||
onView(withId(R.id.copyButton)).perform(ViewActions.click())
|
||||
pressBack()
|
||||
onView(withId(R.id.seedReminderView)).check(matches(withEffectiveVisibility(Visibility.GONE)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsVisible_seedView() {
|
||||
setupLoggedInState()
|
||||
onView(withId(R.id.seedReminderView)).check(matches(isCompletelyDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testIsVisible_alreadyDismissed_seedView() {
|
||||
setupLoggedInState(hasViewedSeed = true)
|
||||
onView(withId(R.id.seedReminderView)).check(doesNotExist())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testChat_withSelf() {
|
||||
setupLoggedInState()
|
||||
goToMyChat()
|
||||
TextSecurePreferences.setLinkPreviewsEnabled(InstrumentationRegistry.getInstrumentation().targetContext, true)
|
||||
sendMessage("howdy")
|
||||
sendMessage("test")
|
||||
// tests url rewriter doesn't crash
|
||||
sendMessage("https://www.getsession.org?random_query_parameter=testtesttesttesttesttesttesttest&other_query_parameter=testtesttesttesttesttesttesttest")
|
||||
sendMessage("https://www.ámazon.com")
|
||||
// TODO: check data / tap URL and check it's displayed properly here
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package network.loki.messenger.util
|
||||
|
||||
import android.view.View
|
||||
import androidx.annotation.DrawableRes
|
||||
import org.hamcrest.Description
|
||||
import org.hamcrest.TypeSafeMatcher
|
||||
import org.thoughtcrime.securesms.conversation.v2.input_bar.InputBarButton
|
||||
import org.thoughtcrime.securesms.home.NewConversationButtonSetView
|
||||
|
||||
class NewConversationButtonDrawableMatcher(@DrawableRes private val expectedId: Int): TypeSafeMatcher<View>() {
|
||||
|
||||
companion object {
|
||||
@JvmStatic fun newConversationButtonWithDrawable(@DrawableRes expectedId: Int) = NewConversationButtonDrawableMatcher(expectedId)
|
||||
}
|
||||
|
||||
override fun describeTo(description: Description?) {
|
||||
description?.appendText("with drawable on button with resource id: $expectedId")
|
||||
}
|
||||
|
||||
override fun matchesSafely(item: View): Boolean {
|
||||
if (item !is NewConversationButtonSetView.Button) return false
|
||||
|
||||
return item.getIconID() == expectedId
|
||||
}
|
||||
}
|
||||
|
||||
class InputBarButtonDrawableMatcher(@DrawableRes private val expectedId: Int): TypeSafeMatcher<View>() {
|
||||
|
||||
companion object {
|
||||
@JvmStatic fun inputButtonWithDrawable(@DrawableRes expectedId: Int) = InputBarButtonDrawableMatcher(expectedId)
|
||||
}
|
||||
|
||||
override fun describeTo(description: Description?) {
|
||||
description?.appendText("with drawable on button with resource id: $expectedId")
|
||||
}
|
||||
|
||||
override fun matchesSafely(item: View): Boolean {
|
||||
if (item !is InputBarButton) return false
|
||||
|
||||
return item.getIconID() == expectedId
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@ import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.Gravity
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.MotionEvent
|
||||
@ -18,10 +17,7 @@ import android.widget.RelativeLayout
|
||||
import androidx.annotation.DrawableRes
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.util.*
|
||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||
import org.thoughtcrime.securesms.util.InputBarButtonImageViewContainer
|
||||
import java.util.*
|
||||
import kotlin.math.abs
|
||||
|
||||
class InputBarButton : RelativeLayout {
|
||||
private val gestureHandler = Handler(Looper.getMainLooper())
|
||||
@ -105,6 +101,8 @@ class InputBarButton : RelativeLayout {
|
||||
isHapticFeedbackEnabled = true
|
||||
}
|
||||
|
||||
fun getIconID() = iconID
|
||||
|
||||
fun expand() {
|
||||
GlowViewUtilities.animateColorChange(context, imageViewContainer, colorID, R.color.accent)
|
||||
imageViewContainer.animateSizeChange(R.dimen.input_bar_button_collapsed_size, R.dimen.input_bar_button_expanded_size, animationDuration)
|
||||
|
@ -20,6 +20,7 @@ import androidx.loader.content.Loader
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import kotlinx.android.synthetic.main.activity_home.*
|
||||
import kotlinx.android.synthetic.main.seed_reminder_stub.*
|
||||
import kotlinx.android.synthetic.main.seed_reminder_stub.view.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.*
|
||||
@ -168,7 +169,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
|
||||
profileButton.update()
|
||||
val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this)
|
||||
if (hasViewedSeed) {
|
||||
seedReminderStub.visibility = View.GONE
|
||||
seedReminderView?.isVisible = false
|
||||
}
|
||||
if (TextSecurePreferences.getConfigurationMessageSynced(this)) {
|
||||
lifecycleScope.launch(Dispatchers.IO) {
|
||||
|
@ -17,8 +17,6 @@ import androidx.annotation.ColorRes
|
||||
import androidx.annotation.DrawableRes
|
||||
import network.loki.messenger.R
|
||||
import org.thoughtcrime.securesms.util.*
|
||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
||||
import org.thoughtcrime.securesms.util.NewConversationButtonImageView
|
||||
|
||||
class NewConversationButtonSetView : RelativeLayout {
|
||||
private var expandedButton: Button? = null
|
||||
@ -52,6 +50,8 @@ class NewConversationButtonSetView : RelativeLayout {
|
||||
@DrawableRes private var iconID = 0
|
||||
private var isMain = false
|
||||
|
||||
fun getIconID() = iconID
|
||||
|
||||
companion object {
|
||||
val animationDuration = 250.toLong()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user