mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15: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-module-junit4-rule:1.6.1'
|
||||||
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
|
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
|
||||||
testImplementation 'androidx.test:core:1.3.0'
|
testImplementation 'androidx.test:core:1.3.0'
|
||||||
androidTestImplementation 'androidx.multidex:multidex:2.0.1'
|
// Core library
|
||||||
androidTestImplementation 'androidx.multidex:multidex-instrumentation:2.0.0'
|
androidTestImplementation 'androidx.test:core:1.4.0'
|
||||||
androidTestImplementation 'com.google.dexmaker:dexmaker:1.2'
|
|
||||||
androidTestImplementation 'com.google.dexmaker:dexmaker-mockito:1.2'
|
// AndroidJUnitRunner and JUnit Rules
|
||||||
androidTestImplementation ('org.assertj:assertj-core:1.7.1') {
|
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||||
exclude group: 'org.hamcrest', module: 'hamcrest-core'
|
androidTestImplementation 'androidx.test:rules:1.4.0'
|
||||||
}
|
|
||||||
androidTestImplementation ('com.squareup.assertj:assertj-android:1.1.1') {
|
// Assertions
|
||||||
exclude group: 'org.hamcrest', module: 'hamcrest-core'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
exclude group: 'com.android.support', module: 'support-annotations'
|
androidTestImplementation 'androidx.test.ext:truth:1.4.0'
|
||||||
}
|
androidTestImplementation 'com.google.truth:truth:1.0'
|
||||||
testImplementation 'org.robolectric:robolectric:4.2.1'
|
|
||||||
testImplementation 'org.robolectric:shadows-multidex:4.2'
|
// 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
|
def canonicalVersionCode = 217
|
||||||
@ -209,6 +220,14 @@ android {
|
|||||||
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
|
buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode"
|
||||||
|
|
||||||
resConfigs autoResConfig()
|
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 {
|
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.Handler
|
||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.util.Log
|
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.HapticFeedbackConstants
|
import android.view.HapticFeedbackConstants
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
@ -18,10 +17,7 @@ import android.widget.RelativeLayout
|
|||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.util.*
|
import org.thoughtcrime.securesms.util.*
|
||||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
|
||||||
import org.thoughtcrime.securesms.util.InputBarButtonImageViewContainer
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.abs
|
|
||||||
|
|
||||||
class InputBarButton : RelativeLayout {
|
class InputBarButton : RelativeLayout {
|
||||||
private val gestureHandler = Handler(Looper.getMainLooper())
|
private val gestureHandler = Handler(Looper.getMainLooper())
|
||||||
@ -105,6 +101,8 @@ class InputBarButton : RelativeLayout {
|
|||||||
isHapticFeedbackEnabled = true
|
isHapticFeedbackEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getIconID() = iconID
|
||||||
|
|
||||||
fun expand() {
|
fun expand() {
|
||||||
GlowViewUtilities.animateColorChange(context, imageViewContainer, colorID, R.color.accent)
|
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)
|
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.localbroadcastmanager.content.LocalBroadcastManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import kotlinx.android.synthetic.main.activity_home.*
|
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.android.synthetic.main.seed_reminder_stub.view.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
@ -168,7 +169,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), ConversationClickLis
|
|||||||
profileButton.update()
|
profileButton.update()
|
||||||
val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this)
|
val hasViewedSeed = TextSecurePreferences.getHasViewedSeed(this)
|
||||||
if (hasViewedSeed) {
|
if (hasViewedSeed) {
|
||||||
seedReminderStub.visibility = View.GONE
|
seedReminderView?.isVisible = false
|
||||||
}
|
}
|
||||||
if (TextSecurePreferences.getConfigurationMessageSynced(this)) {
|
if (TextSecurePreferences.getConfigurationMessageSynced(this)) {
|
||||||
lifecycleScope.launch(Dispatchers.IO) {
|
lifecycleScope.launch(Dispatchers.IO) {
|
||||||
|
@ -17,8 +17,6 @@ import androidx.annotation.ColorRes
|
|||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import network.loki.messenger.R
|
import network.loki.messenger.R
|
||||||
import org.thoughtcrime.securesms.util.*
|
import org.thoughtcrime.securesms.util.*
|
||||||
import org.thoughtcrime.securesms.util.GlowViewUtilities
|
|
||||||
import org.thoughtcrime.securesms.util.NewConversationButtonImageView
|
|
||||||
|
|
||||||
class NewConversationButtonSetView : RelativeLayout {
|
class NewConversationButtonSetView : RelativeLayout {
|
||||||
private var expandedButton: Button? = null
|
private var expandedButton: Button? = null
|
||||||
@ -52,6 +50,8 @@ class NewConversationButtonSetView : RelativeLayout {
|
|||||||
@DrawableRes private var iconID = 0
|
@DrawableRes private var iconID = 0
|
||||||
private var isMain = false
|
private var isMain = false
|
||||||
|
|
||||||
|
fun getIconID() = iconID
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val animationDuration = 250.toLong()
|
val animationDuration = 250.toLong()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user