parent
41f57ae18d
commit
b961ec4a6c
@ -1,143 +0,0 @@
|
||||
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.compose.CreateGroup
|
||||
import org.thoughtcrime.securesms.groups.ViewState
|
||||
import org.thoughtcrime.securesms.ui.theme.PreviewTheme
|
||||
|
||||
@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)
|
||||
|
||||
var backPressed = false
|
||||
var closePressed = false
|
||||
|
||||
composeTest.setContent {
|
||||
PreviewTheme {
|
||||
CreateGroup(
|
||||
viewState = ViewState.DEFAULT,
|
||||
onBack = { backPressed = true },
|
||||
onClose = { closePressed = true },
|
||||
onContactItemClicked = {},
|
||||
updateState = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with(composeTest) {
|
||||
onNode(hasContentDescriptionExactly(nameDesc)).performTextInput("Name")
|
||||
onNode(hasContentDescriptionExactly(buttonDesc)).performClick()
|
||||
}
|
||||
|
||||
assertThat(backPressed, equalTo(false))
|
||||
assertThat(closePressed, equalTo(false))
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testFailToCreate() {
|
||||
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)
|
||||
|
||||
var backPressed = false
|
||||
var closePressed = false
|
||||
|
||||
composeTest.setContent {
|
||||
PreviewTheme {
|
||||
CreateGroup(
|
||||
viewState = ViewState.DEFAULT,
|
||||
onBack = { backPressed = true },
|
||||
onClose = { closePressed = true },
|
||||
updateState = {},
|
||||
onContactItemClicked = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
with(composeTest) {
|
||||
onNode(hasContentDescriptionExactly(nameDesc)).performTextInput("")
|
||||
onNode(hasContentDescriptionExactly(buttonDesc)).performClick()
|
||||
}
|
||||
|
||||
assertThat(backPressed, equalTo(false))
|
||||
assertThat(closePressed, equalTo(false))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBackButton() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
// Accessibility IDs
|
||||
val backDesc = application.getString(R.string.new_conversation_dialog_back_button_content_description)
|
||||
|
||||
var backPressed = false
|
||||
|
||||
composeTest.setContent {
|
||||
PreviewTheme {
|
||||
CreateGroup(
|
||||
viewState = ViewState.DEFAULT,
|
||||
onBack = { backPressed = true },
|
||||
onClose = {},
|
||||
onContactItemClicked = {},
|
||||
updateState = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with (composeTest) {
|
||||
onNode(hasContentDescriptionExactly(backDesc)).performClick()
|
||||
}
|
||||
|
||||
assertThat(backPressed, equalTo(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testCloseButton() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
// Accessibility IDs
|
||||
val closeDesc = application.getString(R.string.new_conversation_dialog_close_button_content_description)
|
||||
var closePressed = false
|
||||
|
||||
composeTest.setContent {
|
||||
PreviewTheme {
|
||||
CreateGroup(
|
||||
viewState = ViewState.DEFAULT,
|
||||
onBack = { },
|
||||
onClose = { closePressed = true },
|
||||
onContactItemClicked = {},
|
||||
updateState = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
with (composeTest) {
|
||||
onNode(hasContentDescriptionExactly(closeDesc)).performClick()
|
||||
}
|
||||
|
||||
assertThat(closePressed, equalTo(true))
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,257 +0,0 @@
|
||||
package network.loki.messenger
|
||||
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.assertTextEquals
|
||||
import androidx.compose.ui.test.hasContentDescriptionExactly
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.groups.compose.EditGroup
|
||||
import org.thoughtcrime.securesms.groups.EditGroupViewState
|
||||
import org.thoughtcrime.securesms.groups.MemberState
|
||||
import org.thoughtcrime.securesms.groups.MemberViewModel
|
||||
import org.thoughtcrime.securesms.ui.theme.PreviewTheme
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@SmallTest
|
||||
class EditGroupTests {
|
||||
|
||||
@get:Rule
|
||||
val composeTest = createComposeRule()
|
||||
|
||||
val oneMember = MemberViewModel(
|
||||
"Test User",
|
||||
"05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234",
|
||||
MemberState.InviteSent,
|
||||
false
|
||||
)
|
||||
val twoMember = MemberViewModel(
|
||||
"Test User 2",
|
||||
"05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1235",
|
||||
MemberState.InviteFailed,
|
||||
false
|
||||
)
|
||||
val threeMember = MemberViewModel(
|
||||
"Test User 3",
|
||||
"05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1236",
|
||||
MemberState.Member,
|
||||
false
|
||||
)
|
||||
|
||||
val fourMember = MemberViewModel(
|
||||
"Test User 4",
|
||||
"05abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1237",
|
||||
MemberState.Admin,
|
||||
false
|
||||
)
|
||||
|
||||
@Test
|
||||
fun testDisplaysNameAndDesc() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
// Accessibility IDs
|
||||
val nameDesc = application.getString(R.string.AccessibilityId_group_name)
|
||||
val descriptionDesc = application.getString(R.string.AccessibilityId_group_description)
|
||||
|
||||
with (composeTest) {
|
||||
val state = EditGroupViewState(
|
||||
"TestGroup",
|
||||
"TestDesc",
|
||||
emptyList(),
|
||||
false
|
||||
)
|
||||
|
||||
setContent {
|
||||
PreviewTheme {
|
||||
EditGroup(
|
||||
onBackClick = {},
|
||||
onAddMemberClick = {},
|
||||
onResendInviteClick = {},
|
||||
onPromoteClick = {},
|
||||
onRemoveClick = {},
|
||||
onEditName = {},
|
||||
onMemberSelected = {},
|
||||
viewState = state
|
||||
)
|
||||
}
|
||||
}
|
||||
onNode(hasContentDescriptionExactly(nameDesc)).assertTextEquals("TestGroup")
|
||||
onNode(hasContentDescriptionExactly(descriptionDesc)).assertTextEquals("TestDesc")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisplaysReinviteProperly() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
|
||||
// Accessibility IDs
|
||||
val reinviteDesc = application.getString(R.string.AccessibilityId_reinvite_member)
|
||||
val promoteDesc = application.getString(R.string.AccessibilityId_promote_member)
|
||||
|
||||
var reinvited = false
|
||||
|
||||
with (composeTest) {
|
||||
|
||||
val state = EditGroupViewState(
|
||||
"TestGroup",
|
||||
"TestDesc",
|
||||
listOf(
|
||||
twoMember
|
||||
),
|
||||
// reinvite only shows for admin users
|
||||
true
|
||||
)
|
||||
|
||||
setContent {
|
||||
PreviewTheme {
|
||||
EditGroup(
|
||||
onBackClick = {},
|
||||
onAddMemberClick = {},
|
||||
onResendInviteClick = { reinvited = true },
|
||||
onPromoteClick = {},
|
||||
onRemoveClick = {},
|
||||
onEditName = {},
|
||||
onMemberSelected = {},
|
||||
viewState = state
|
||||
)
|
||||
}
|
||||
}
|
||||
onNodeWithContentDescription(reinviteDesc).assertIsDisplayed().performClick()
|
||||
onNodeWithContentDescription(promoteDesc).assertDoesNotExist()
|
||||
assertThat(reinvited, equalTo(true))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisplaysRegularMemberProperly() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
|
||||
// Accessibility IDs
|
||||
val reinviteDesc = application.getString(R.string.AccessibilityId_reinvite_member)
|
||||
val promoteDesc = application.getString(R.string.AccessibilityId_promote_member)
|
||||
|
||||
var promoted = false
|
||||
|
||||
with (composeTest) {
|
||||
|
||||
val state = EditGroupViewState(
|
||||
"TestGroup",
|
||||
"TestDesc",
|
||||
listOf(
|
||||
threeMember
|
||||
),
|
||||
// reinvite only shows for admin users
|
||||
true
|
||||
)
|
||||
|
||||
setContent {
|
||||
PreviewTheme {
|
||||
EditGroup(
|
||||
onBackClick = {},
|
||||
onAddMemberClick = {},
|
||||
onResendInviteClick = {},
|
||||
onPromoteClick = { promoted = true },
|
||||
onRemoveClick = {},
|
||||
onEditName = {},
|
||||
onMemberSelected = {},
|
||||
viewState = state
|
||||
)
|
||||
}
|
||||
}
|
||||
onNodeWithContentDescription(reinviteDesc).assertDoesNotExist()
|
||||
onNodeWithContentDescription(promoteDesc).assertIsDisplayed().performClick()
|
||||
assertThat(promoted, equalTo(true))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisplaysAdminProperly() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
|
||||
// Accessibility IDs
|
||||
val reinviteDesc = application.getString(R.string.AccessibilityId_reinvite_member)
|
||||
val promoteDesc = application.getString(R.string.AccessibilityId_promote_member)
|
||||
|
||||
with (composeTest) {
|
||||
|
||||
val state = EditGroupViewState(
|
||||
"TestGroup",
|
||||
"TestDesc",
|
||||
listOf(
|
||||
fourMember
|
||||
),
|
||||
// reinvite only shows for admin users
|
||||
true
|
||||
)
|
||||
|
||||
setContent {
|
||||
PreviewTheme {
|
||||
EditGroup(
|
||||
onBackClick = {},
|
||||
onAddMemberClick = {},
|
||||
onResendInviteClick = {},
|
||||
onPromoteClick = {},
|
||||
onRemoveClick = {},
|
||||
onEditName = {},
|
||||
onMemberSelected = {},
|
||||
viewState = state
|
||||
)
|
||||
}
|
||||
}
|
||||
onNodeWithContentDescription(reinviteDesc).assertDoesNotExist()
|
||||
onNodeWithContentDescription(promoteDesc).assertDoesNotExist()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDisplaysPendingInviteProperly() {
|
||||
val application = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
|
||||
// Accessibility IDs
|
||||
val reinviteDesc = application.getString(R.string.AccessibilityId_reinvite_member)
|
||||
val promoteDesc = application.getString(R.string.AccessibilityId_promote_member)
|
||||
val stateDesc = application.getString(R.string.AccessibilityId_member_state)
|
||||
val memberDesc = application.getString(R.string.AccessibilityId_contact)
|
||||
|
||||
with (composeTest) {
|
||||
|
||||
val state = EditGroupViewState(
|
||||
"TestGroup",
|
||||
"TestDesc",
|
||||
listOf(
|
||||
oneMember
|
||||
),
|
||||
// reinvite only shows for admin users
|
||||
true
|
||||
)
|
||||
|
||||
setContent {
|
||||
PreviewTheme {
|
||||
EditGroup(
|
||||
onBackClick = {},
|
||||
onAddMemberClick = {},
|
||||
onResendInviteClick = {},
|
||||
onPromoteClick = {},
|
||||
onRemoveClick = {},
|
||||
onEditName = {},
|
||||
onMemberSelected = {},
|
||||
viewState = state
|
||||
)
|
||||
}
|
||||
}
|
||||
onNodeWithContentDescription(reinviteDesc).assertDoesNotExist()
|
||||
onNodeWithContentDescription(promoteDesc).assertDoesNotExist()
|
||||
onNodeWithContentDescription(stateDesc, useUnmergedTree = true).assertTextEquals("InviteSent")
|
||||
onNodeWithContentDescription(memberDesc, useUnmergedTree = true).assertTextEquals("Test User")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,183 +0,0 @@
|
||||
package network.loki.messenger
|
||||
|
||||
import android.app.Instrumentation
|
||||
import android.view.View
|
||||
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.matches
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDescendantOfA
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
|
||||
import androidx.test.espresso.matcher.ViewMatchers.isRoot
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.ext.junit.rules.ActivityScenarioRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import network.loki.messenger.util.sendMessage
|
||||
import network.loki.messenger.util.waitFor
|
||||
import androidx.test.uiautomator.By
|
||||
import androidx.test.uiautomator.UiDevice
|
||||
import com.adevinta.android.barista.interaction.PermissionGranter
|
||||
import com.bumptech.glide.Glide
|
||||
import network.loki.messenger.util.InputBarButtonDrawableMatcher.Companion.inputButtonWithDrawable
|
||||
import org.hamcrest.Matchers.allOf
|
||||
import org.hamcrest.Matchers.not
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
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.home.HomeActivity
|
||||
|
||||
/**
|
||||
* Currently not used as part of our CI/Deployment processes !!!!
|
||||
*/
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@SmallTest
|
||||
class HomeActivityTests {
|
||||
|
||||
@get:Rule
|
||||
var activityRule = ActivityScenarioRule(HomeActivity::class.java)
|
||||
|
||||
private val activityMonitor = Instrumentation.ActivityMonitor(ConversationActivityV2::class.java.name, null, false)
|
||||
|
||||
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
|
||||
|
||||
private val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
InstrumentationRegistry.getInstrumentation().addMonitor(activityMonitor)
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
InstrumentationRegistry.getInstrumentation().removeMonitor(activityMonitor)
|
||||
}
|
||||
|
||||
private fun sendMessage(messageToSend: String, linkPreview: LinkPreview? = null) {
|
||||
// assume in chat activity
|
||||
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),withId(R.id.inputBarEditText))).perform(ViewActions.replaceText(messageToSend))
|
||||
if (linkPreview != null) {
|
||||
val activity = activityMonitor.waitForActivity() as ConversationActivityV2
|
||||
val glide = Glide.with(activity)
|
||||
activity.findViewById<InputBar>(R.id.inputBar).updateLinkPreviewDraft(glide, linkPreview)
|
||||
}
|
||||
onView(allOf(isDescendantOfA(withId(R.id.inputBar)),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(isRoot()).perform(waitFor(500))
|
||||
}
|
||||
|
||||
private fun objectFromDesc(id: Int) = device.findObject(By.desc(context.getString(id)))
|
||||
|
||||
private fun setupLoggedInState(hasViewedSeed: Boolean = false) {
|
||||
// landing activity
|
||||
objectFromDesc(R.string.onboardingAccountCreate).click()
|
||||
|
||||
// display name selection
|
||||
objectFromDesc(R.string.displayNameEnter).click()
|
||||
device.pressKeyCode(65)
|
||||
device.pressKeyCode(66)
|
||||
device.pressKeyCode(67)
|
||||
|
||||
// Continue with display name
|
||||
objectFromDesc(R.string.theContinue).click()
|
||||
|
||||
// Continue with default push notification setting
|
||||
objectFromDesc(R.string.theContinue).click()
|
||||
|
||||
// PN select
|
||||
if (hasViewedSeed) {
|
||||
// has viewed seed is set to false after register activity
|
||||
TextSecurePreferences.setHasViewedSeed(InstrumentationRegistry.getInstrumentation().targetContext, true)
|
||||
}
|
||||
// allow notification permission
|
||||
PermissionGranter.allowPermissionsIfNeeded(Manifest.permission.POST_NOTIFICATIONS)
|
||||
}
|
||||
|
||||
/* private fun goToMyChat() {
|
||||
onView(withId(R.id.newConversationButton)).perform(ViewActions.click())
|
||||
onView(withId(R.id.createPrivateChatButton)).perform(ViewActions.click())
|
||||
// new chat
|
||||
Thread.sleep(500)
|
||||
onView(withId(R.id.publicKeyEditText)).perform(ViewActions.closeSoftKeyboard())
|
||||
onView(withId(R.id.copyButton)).perform(ViewActions.click())
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
lateinit var copied: String
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync {
|
||||
val clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
copied = clipboardManager.primaryClip!!.getItemAt(0).text.toString()
|
||||
}
|
||||
onView(withId(R.id.publicKeyEditText)).perform(ViewActions.typeText(copied))
|
||||
onView(withId(R.id.publicKeyEditText)).perform(ViewActions.closeSoftKeyboard())
|
||||
onView(withId(R.id.createPrivateChatButton)).perform(ViewActions.click())
|
||||
}*/
|
||||
|
||||
@Test
|
||||
fun testLaunches_dismiss_seedView() {
|
||||
setupLoggedInState()
|
||||
objectFromDesc(R.string.theContinue).click()
|
||||
objectFromDesc(R.string.copy).click()
|
||||
pressBack()
|
||||
onView(withId(R.id.seedReminderView)).check(matches(not(isDisplayed())))
|
||||
}
|
||||
|
||||
@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(matches(not(isDisplayed())))
|
||||
}
|
||||
|
||||
/* @Test
|
||||
fun testChat_withSelf() {
|
||||
setupLoggedInState()
|
||||
goToMyChat()
|
||||
TextSecurePreferences.setLinkPreviewsEnabled(context, true)
|
||||
with (activityMonitor.waitForActivity() as ConversationActivityV2) {
|
||||
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")
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testChat_displaysCorrectUrl() {
|
||||
setupLoggedInState()
|
||||
goToMyChat()
|
||||
TextSecurePreferences.setLinkPreviewsEnabled(InstrumentationRegistry.getInstrumentation().targetContext, true)
|
||||
// given the link url text
|
||||
val url = "https://www.ámazon.com"
|
||||
with (activityMonitor.waitForActivity() as ConversationActivityV2) {
|
||||
sendMessage(url, LinkPreview(url, "amazon", Optional.absent()))
|
||||
}
|
||||
|
||||
// when the URL span is clicked
|
||||
onView(withSubstring(url)).perform(ViewActions.click())
|
||||
|
||||
// then the URL dialog should be displayed with a known punycode url
|
||||
val amazonPuny = "https://www.xn--mazon-wqa.com/"
|
||||
|
||||
val dialogPromptText = InstrumentationRegistry.getInstrumentation().targetContext.getString(R.string.dialog_open_url_explanation, amazonPuny)
|
||||
|
||||
onView(isRoot()).perform(waitFor(1000)) // no other way for this to work apparently
|
||||
onView(withText(dialogPromptText)).check(matches(isDisplayed()))
|
||||
}*/
|
||||
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
package network.loki.messenger
|
||||
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.PreferenceManager
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.filters.SmallTest
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import network.loki.messenger.libsession_util.ConfigBase
|
||||
import network.loki.messenger.libsession_util.Contacts
|
||||
import network.loki.messenger.libsession_util.ConversationVolatileConfig
|
||||
import network.loki.messenger.libsession_util.util.Contact
|
||||
import network.loki.messenger.libsession_util.util.Conversation
|
||||
import network.loki.messenger.libsession_util.util.ExpiryMode
|
||||
import network.loki.messenger.util.applySpiedStorage
|
||||
import network.loki.messenger.util.maybeGetUserInfo
|
||||
import network.loki.messenger.util.randomSeedBytes
|
||||
import network.loki.messenger.util.randomSessionId
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.CoreMatchers.instanceOf
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.kotlin.any
|
||||
import org.mockito.kotlin.argThat
|
||||
import org.mockito.kotlin.argWhere
|
||||
import org.mockito.kotlin.eq
|
||||
import org.mockito.kotlin.spy
|
||||
import org.mockito.kotlin.verify
|
||||
import org.session.libsession.messaging.MessagingModuleConfiguration
|
||||
import org.session.libsession.snode.SnodeAPI
|
||||
import org.session.libsession.utilities.Address
|
||||
import org.session.libsession.utilities.TextSecurePreferences
|
||||
import org.session.libsignal.utilities.KeyHelper
|
||||
import org.session.libsignal.utilities.hexEncodedPublicKey
|
||||
import org.thoughtcrime.securesms.ApplicationContext
|
||||
import org.thoughtcrime.securesms.crypto.KeyPairUtilities
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
@SmallTest
|
||||
class LibSessionTests {
|
||||
|
||||
private var fakeHashI = 0
|
||||
private val nextFakeHash: String
|
||||
get() = "fakehash${fakeHashI++}"
|
||||
|
||||
private fun buildContactMessage(contactList: List<Contact>): ByteArray {
|
||||
val (key,_) = maybeGetUserInfo()!!
|
||||
val contacts = Contacts.newInstance(key)
|
||||
contactList.forEach { contact ->
|
||||
contacts.set(contact)
|
||||
}
|
||||
return contacts.push().config
|
||||
}
|
||||
|
||||
private fun buildVolatileMessage(conversations: List<Conversation>): ByteArray {
|
||||
val (key, _) = maybeGetUserInfo()!!
|
||||
val volatile = ConversationVolatileConfig.newInstance(key)
|
||||
conversations.forEach { conversation ->
|
||||
volatile.set(conversation)
|
||||
}
|
||||
return volatile.push().config
|
||||
}
|
||||
|
||||
private fun fakePollNewConfig(configBase: ConfigBase, toMerge: ByteArray) {
|
||||
configBase.merge(nextFakeHash to toMerge)
|
||||
MessagingModuleConfiguration.shared.configFactory.persist(configBase, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setupUser() {
|
||||
PreferenceManager.getDefaultSharedPreferences(InstrumentationRegistry.getInstrumentation().targetContext.applicationContext).edit {
|
||||
putBoolean(TextSecurePreferences.HAS_FORCED_NEW_CONFIG, true).apply()
|
||||
}
|
||||
val newBytes = randomSeedBytes().toByteArray()
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext
|
||||
val kp = KeyPairUtilities.generate(newBytes)
|
||||
KeyPairUtilities.store(context, kp.seed, kp.ed25519KeyPair, kp.x25519KeyPair)
|
||||
val registrationID = KeyHelper.generateRegistrationId(false)
|
||||
TextSecurePreferences.setLocalRegistrationId(context, registrationID)
|
||||
TextSecurePreferences.setLocalNumber(context, kp.x25519KeyPair.hexEncodedPublicKey)
|
||||
TextSecurePreferences.setRestorationTime(context, 0)
|
||||
TextSecurePreferences.setHasViewedSeed(context, false)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun migration_one_to_ones() {
|
||||
val applicationContext = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
val storage = applicationContext.applySpiedStorage()
|
||||
|
||||
val newContactId = randomSessionId()
|
||||
val singleContact = Contact(
|
||||
id = newContactId,
|
||||
approved = true,
|
||||
expiryMode = ExpiryMode.NONE
|
||||
)
|
||||
val newContactMerge = buildContactMessage(listOf(singleContact))
|
||||
val contacts = MessagingModuleConfiguration.shared.configFactory.contacts!!
|
||||
fakePollNewConfig(contacts, newContactMerge)
|
||||
verify(storage).addLibSessionContacts(argThat {
|
||||
first().let { it.id == newContactId && it.approved } && size == 1
|
||||
}, any())
|
||||
verify(storage).setRecipientApproved(argThat { address.serialize() == newContactId }, eq(true))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_expected_configs() {
|
||||
val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
val storageSpy = spy(app.storage)
|
||||
app.storage = storageSpy
|
||||
|
||||
val randomRecipient = randomSessionId()
|
||||
val newContact = Contact(
|
||||
id = randomRecipient,
|
||||
approved = true,
|
||||
expiryMode = ExpiryMode.AfterSend(1000)
|
||||
)
|
||||
val newConvo = Conversation.OneToOne(
|
||||
randomRecipient,
|
||||
SnodeAPI.nowWithOffset,
|
||||
false
|
||||
)
|
||||
val volatiles = MessagingModuleConfiguration.shared.configFactory.convoVolatile!!
|
||||
val contacts = MessagingModuleConfiguration.shared.configFactory.contacts!!
|
||||
val newContactMerge = buildContactMessage(listOf(newContact))
|
||||
val newVolatileMerge = buildVolatileMessage(listOf(newConvo))
|
||||
fakePollNewConfig(contacts, newContactMerge)
|
||||
fakePollNewConfig(volatiles, newVolatileMerge)
|
||||
verify(storageSpy).setExpirationConfiguration(argWhere { config ->
|
||||
config.expiryMode is ExpiryMode.AfterSend
|
||||
&& config.expiryMode.expirySeconds == 1000L
|
||||
})
|
||||
val threadId = storageSpy.getThreadId(Address.fromSerialized(randomRecipient))!!
|
||||
val newExpiry = storageSpy.getExpirationConfiguration(threadId)!!
|
||||
assertThat(newExpiry.expiryMode, instanceOf(ExpiryMode.AfterSend::class.java))
|
||||
assertThat(newExpiry.expiryMode.expirySeconds, equalTo(1000))
|
||||
assertThat(newExpiry.expiryMode.expiryMillis, equalTo(1000000))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test_overwrite_config() {
|
||||
val app = InstrumentationRegistry.getInstrumentation().targetContext.applicationContext as ApplicationContext
|
||||
val storageSpy = spy(app.storage)
|
||||
app.storage = storageSpy
|
||||
|
||||
// Initial state
|
||||
val randomRecipient = randomSessionId()
|
||||
val currentContact = Contact(
|
||||
id = randomRecipient,
|
||||
approved = true,
|
||||
expiryMode = ExpiryMode.NONE
|
||||
)
|
||||
val newConvo = Conversation.OneToOne(
|
||||
randomRecipient,
|
||||
SnodeAPI.nowWithOffset,
|
||||
false
|
||||
)
|
||||
val volatiles = MessagingModuleConfiguration.shared.configFactory.convoVolatile!!
|
||||
val contacts = MessagingModuleConfiguration.shared.configFactory.contacts!!
|
||||
val newContactMerge = buildContactMessage(listOf(currentContact))
|
||||
val newVolatileMerge = buildVolatileMessage(listOf(newConvo))
|
||||
fakePollNewConfig(contacts, newContactMerge)
|
||||
fakePollNewConfig(volatiles, newVolatileMerge)
|
||||
verify(storageSpy).setExpirationConfiguration(argWhere { config ->
|
||||
config.expiryMode == ExpiryMode.NONE
|
||||
})
|
||||
val threadId = storageSpy.getThreadId(Address.fromSerialized(randomRecipient))!!
|
||||
val currentExpiryConfig = storageSpy.getExpirationConfiguration(threadId)!!
|
||||
assertThat(currentExpiryConfig.expiryMode, equalTo(ExpiryMode.NONE))
|
||||
assertThat(currentExpiryConfig.expiryMode.expirySeconds, equalTo(0))
|
||||
assertThat(currentExpiryConfig.expiryMode.expiryMillis, equalTo(0))
|
||||
// Set new state and overwrite
|
||||
val updatedContact = currentContact.copy(expiryMode = ExpiryMode.AfterSend(1000))
|
||||
val updateContactMerge = buildContactMessage(listOf(updatedContact))
|
||||
fakePollNewConfig(contacts, updateContactMerge)
|
||||
val updatedExpiryConfig = storageSpy.getExpirationConfiguration(threadId)!!
|
||||
assertThat(updatedExpiryConfig.expiryMode, instanceOf(ExpiryMode.AfterSend::class.java))
|
||||
assertThat(updatedExpiryConfig.expiryMode.expirySeconds, equalTo(1000))
|
||||
}
|
||||
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
package network.loki.messenger
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.goterl.lazysodium.utils.Key
|
||||
import com.goterl.lazysodium.utils.KeyPair
|
||||
import org.hamcrest.CoreMatchers.equalTo
|
||||
import org.hamcrest.MatcherAssert.assertThat
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNull
|
||||
import org.junit.Assert.assertTrue
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.session.libsession.messaging.utilities.SodiumUtilities
|
||||
import org.session.libsignal.utilities.Base64
|
||||
import org.session.libsignal.utilities.Hex
|
||||
import org.session.libsignal.utilities.toHexString
|
||||
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class SodiumUtilitiesTest {
|
||||
|
||||
private val publicKey: String = "88672ccb97f40bb57238989226cf429b575ba355443f47bc76c5ab144a96c65b"
|
||||
private val privateKey: String = "30d796c1ddb4dc455fd998a98aa275c247494a9a7bde9c1fee86ae45cd585241"
|
||||
private val edKeySeed: String = "c010d89eccbaf5d1c6d19df766c6eedf965d4a28a56f87c9fc819edb59896dd9"
|
||||
private val edPublicKey: String = "bac6e71efd7dfa4a83c98ed24f254ab2c267f9ccdb172a5280a0444ad24e89cc"
|
||||
private val edSecretKey: String = "c010d89eccbaf5d1c6d19df766c6eedf965d4a28a56f87c9fc819edb59896dd9bac6e71efd7dfa4a83c98ed24f254ab2c267f9ccdb172a5280a0444ad24e89cc"
|
||||
private val blindedPublicKey: String = "98932d4bccbe595a8789d7eb1629cefc483a0eaddc7e20e8fe5c771efafd9af5"
|
||||
private val serverPublicKey: String = "c3b3c6f32f0ab5a57f853cc4f30f5da7fda5624b0c77b3fb0829de562ada081d"
|
||||
|
||||
private val edKeyPair = KeyPair(Key.fromHexString(edPublicKey), Key.fromHexString(edSecretKey))
|
||||
|
||||
@Test
|
||||
fun generateBlindingFactorSuccess() {
|
||||
val result = SodiumUtilities.generateBlindingFactor(serverPublicKey)
|
||||
|
||||
assertThat(result?.toHexString(), equalTo("84e3eb75028a9b73fec031b7448e322a68ca6485fad81ab1bead56f759ebeb0f"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun generateBlindingFactorFailure() {
|
||||
val result = SodiumUtilities.generateBlindingFactor("Test")
|
||||
|
||||
assertNull(result?.toHexString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun blindedKeyPairSuccess() {
|
||||
val result = SodiumUtilities.blindedKeyPair(serverPublicKey, edKeyPair)!!
|
||||
|
||||
assertThat(result.publicKey.asHexString.lowercase(), equalTo(blindedPublicKey))
|
||||
assertThat(result.secretKey.asHexString.take(64).lowercase(), equalTo("16663322d6b684e1c9dcc02b9e8642c3affd3bc431a9ea9e63dbbac88ce7a305"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun blindedKeyPairFailurePublicKeyLength() {
|
||||
val result = SodiumUtilities.blindedKeyPair(
|
||||
serverPublicKey,
|
||||
KeyPair(Key.fromHexString(edPublicKey.take(4)), Key.fromHexString(edKeySeed))
|
||||
)
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun blindedKeyPairFailureSecretKeyLength() {
|
||||
val result = SodiumUtilities.blindedKeyPair(
|
||||
serverPublicKey,
|
||||
KeyPair(Key.fromHexString(edPublicKey), Key.fromHexString(edSecretKey.take(4)))
|
||||
)
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun blindedKeyPairFailureBlindingFactor() {
|
||||
val result = SodiumUtilities.blindedKeyPair("Test", edKeyPair)
|
||||
|
||||
assertNull(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sogsSignature() {
|
||||
val expectedSignature = "dcc086abdd2a740d9260b008fb37e12aa0ff47bd2bd9e177bbbec37fd46705a9072ce747bda66c788c3775cdd7ad60ad15a478e0886779aad5d795fd7bf8350d"
|
||||
|
||||
val result = SodiumUtilities.sogsSignature(
|
||||
"TestMessage".toByteArray(),
|
||||
Hex.fromStringCondensed(edSecretKey),
|
||||
Hex.fromStringCondensed("44d82cc15c0a5056825cae7520b6b52d000a23eb0c5ed94c4be2d9dc41d2d409"),
|
||||
Hex.fromStringCondensed("0bb7815abb6ba5142865895f3e5286c0527ba4d31dbb75c53ce95e91ffe025a2")
|
||||
)
|
||||
|
||||
assertThat(result?.toHexString(), equalTo(expectedSignature))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun combineKeysSuccess() {
|
||||
val result = SodiumUtilities.combineKeys(
|
||||
Hex.fromStringCondensed(edSecretKey),
|
||||
Hex.fromStringCondensed(edPublicKey)
|
||||
)
|
||||
|
||||
assertThat(result?.toHexString(), equalTo("1159b5d0fcfba21228eb2121a0f59712fa8276fc6e5547ff519685a40b9819e6"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun combineKeysFailure() {
|
||||
val result = SodiumUtilities.combineKeys(
|
||||
SodiumUtilities.generatePrivateKeyScalar(Hex.fromStringCondensed(edSecretKey))!!,
|
||||
Hex.fromStringCondensed(publicKey)
|
||||
)
|
||||
|
||||
assertNull(result?.toHexString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sharedBlindedEncryptionKeySuccess() {
|
||||
val result = SodiumUtilities.sharedBlindedEncryptionKey(
|
||||
Hex.fromStringCondensed(edSecretKey),
|
||||
Hex.fromStringCondensed(blindedPublicKey),
|
||||
Hex.fromStringCondensed(publicKey),
|
||||
Hex.fromStringCondensed(blindedPublicKey)
|
||||
)
|
||||
|
||||
assertThat(result?.toHexString(), equalTo("388ee09e4c356b91f1cce5cc0aa0cf59e8e8cade69af61685d09c2d2731bc99e"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun sharedBlindedEncryptionKeyFailure() {
|
||||
val result = SodiumUtilities.sharedBlindedEncryptionKey(
|
||||
Hex.fromStringCondensed(edSecretKey),
|
||||
Hex.fromStringCondensed(publicKey),
|
||||
Hex.fromStringCondensed(edPublicKey),
|
||||
Hex.fromStringCondensed(publicKey)
|
||||
)
|
||||
|
||||
assertNull(result?.toHexString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun accountIdSuccess() {
|
||||
val result = SodiumUtilities.accountId("05$publicKey", "15$blindedPublicKey", serverPublicKey)
|
||||
|
||||
assertTrue(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun accountIdFailureInvalidAccountId() {
|
||||
val result = SodiumUtilities.accountId("AB$publicKey", "15$blindedPublicKey", serverPublicKey)
|
||||
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun accountIdFailureInvalidBlindedId() {
|
||||
val result = SodiumUtilities.accountId("05$publicKey", "AB$blindedPublicKey", serverPublicKey)
|
||||
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun accountIdFailureBlindingFactor() {
|
||||
val result = SodiumUtilities.accountId("05$publicKey", "15$blindedPublicKey", "Test")
|
||||
|
||||
assertFalse(result)
|
||||
}
|
||||
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
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
|
||||
|
||||
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
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
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