Skip to content

Commit

Permalink
fixed "no private key available" issue. Part 2. add email to existing…
Browse files Browse the repository at this point in the history
… key (#2669)

* Added ChoosePrivateKeyDialogFragment.| #597

* Added AddNewUserIdToPrivateKeyDialogFragment.| #597

* 'add email to existing key'. Handled a case when a private key has a passphrase in RAM.| #597

* 'add email to existing key'. Added updating contacts after editing a private key.| #597

* wip

* wip

* Fixed option "no private key available|add email to existing key" if only a single key exists.| #597

* Added ComposeScreenNoKeyAvailableFlowTest.testAddEmailToExistingSingleKeyPassphraseInDatabase().| #597

* wip

* wip

* Added ComposeScreenNoKeyAvailableMultipleKeysWithPassphraseInDatabaseFlowTest.| #597

* Added ComposeScreenNoKeyAvailableMultipleKeysWithPassphraseInRamFlowTest.| #597

* Added ComposeScreenNoKeyAvailableSingleKeyWithPassphraseInRamFlowTest.| #597

* Refactored code
  • Loading branch information
DenBond7 authored Apr 5, 2024
1 parent 08b6e03 commit da407eb
Show file tree
Hide file tree
Showing 30 changed files with 1,233 additions and 62 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* © 2016-present FlowCrypt a.s. Limitations apply. Contact [email protected]
* Contributors: DenBond7
*/

package com.flowcrypt.email.ui

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.ViewMatchers.hasTextColor
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.espresso.matcher.ViewMatchers.withText
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import com.flowcrypt.email.R
import com.flowcrypt.email.TestConstants
import com.flowcrypt.email.extensions.kotlin.asInternetAddress
import com.flowcrypt.email.junit.annotations.FlowCryptTestSettings
import com.flowcrypt.email.rules.AddPrivateKeyToDatabaseRule
import com.flowcrypt.email.rules.ClearAppSettingsRule
import com.flowcrypt.email.rules.GrantPermissionRuleChooser
import com.flowcrypt.email.rules.RetryRule
import com.flowcrypt.email.rules.ScreenshotTestRule
import com.flowcrypt.email.ui.base.BaseComposeScreenNoKeyAvailableTest
import org.hamcrest.CoreMatchers.not
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.runner.RunWith

/**
* @author Denys Bondarenko
*/
@MediumTest
@RunWith(AndroidJUnit4::class)
@FlowCryptTestSettings(useCommonIdling = false)
class ComposeScreenNoKeyAvailableMultipleKeysWithPassphraseInDatabaseFlowTest :
BaseComposeScreenNoKeyAvailableTest() {
private val addPrivateKeyToDatabaseRuleFirst = AddPrivateKeyToDatabaseRule(
keyPath = "pgp/[email protected]_keyA_strong.asc"
)

private val addPrivateKeyToDatabaseRuleSecond = AddPrivateKeyToDatabaseRule(
keyPath = "pgp/[email protected]_keyC_strong.asc"
)

@get:Rule
var ruleChain: TestRule = RuleChain
.outerRule(RetryRule.DEFAULT)
.around(ClearAppSettingsRule())
.around(GrantPermissionRuleChooser.grant(android.Manifest.permission.POST_NOTIFICATIONS))
.around(addAccountToDatabaseRule)
.around(addPrivateKeyToDatabaseRuleFirst)
.around(addPrivateKeyToDatabaseRuleSecond)
.around(activeActivityRule)
.around(ScreenshotTestRule())

@Test
fun testAddEmailToExistingKey() {
doTestAddEmailToExistingKey {
waitForObjectWithText(getResString(android.R.string.ok), 2000)

onView(withId(R.id.buttonOk))
.check(matches(isDisplayed()))
.perform(click())
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* © 2016-present FlowCrypt a.s. Limitations apply. Contact [email protected]
* Contributors: DenBond7
*/

package com.flowcrypt.email.ui

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.clearText
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.action.ViewActions.pressImeActionButton
import androidx.test.espresso.action.ViewActions.replaceText
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.matcher.RootMatchers
import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import com.flowcrypt.email.R
import com.flowcrypt.email.TestConstants
import com.flowcrypt.email.database.entity.KeyEntity
import com.flowcrypt.email.junit.annotations.FlowCryptTestSettings
import com.flowcrypt.email.rules.AddPrivateKeyToDatabaseRule
import com.flowcrypt.email.rules.ClearAppSettingsRule
import com.flowcrypt.email.rules.GrantPermissionRuleChooser
import com.flowcrypt.email.rules.RetryRule
import com.flowcrypt.email.rules.ScreenshotTestRule
import com.flowcrypt.email.ui.base.BaseComposeScreenNoKeyAvailableTest
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.runner.RunWith

/**
* @author Denys Bondarenko
*/
@MediumTest
@RunWith(AndroidJUnit4::class)
@FlowCryptTestSettings(useCommonIdling = false)
class ComposeScreenNoKeyAvailableMultipleKeysWithPassphraseInRamFlowTest :
BaseComposeScreenNoKeyAvailableTest() {
private val addPrivateKeyToDatabaseRuleFirst = AddPrivateKeyToDatabaseRule(
keyPath = "pgp/[email protected]_keyA_strong.asc",
passphraseType = KeyEntity.PassphraseType.RAM
)

private val addPrivateKeyToDatabaseRuleSecond = AddPrivateKeyToDatabaseRule(
keyPath = "pgp/[email protected]_keyC_strong.asc",
passphraseType = KeyEntity.PassphraseType.RAM
)

@get:Rule
var ruleChain: TestRule = RuleChain
.outerRule(RetryRule.DEFAULT)
.around(ClearAppSettingsRule())
.around(GrantPermissionRuleChooser.grant(android.Manifest.permission.POST_NOTIFICATIONS))
.around(addAccountToDatabaseRule)
.around(addPrivateKeyToDatabaseRuleFirst)
.around(addPrivateKeyToDatabaseRuleSecond)
.around(activeActivityRule)
.around(ScreenshotTestRule())

@Test
fun testAddEmailToExistingKey() {
doTestAddEmailToExistingKey {
waitForObjectWithText(getResString(android.R.string.ok), 2000)

onView(withId(R.id.buttonOk))
.check(matches(isDisplayed()))
.perform(click())

waitForObjectWithText(getResString(R.string.provide_passphrase), 2000)

onView(withId(R.id.eTKeyPassword))
.inRoot(RootMatchers.isDialog())
.perform(
clearText(),
replaceText(TestConstants.DEFAULT_STRONG_PASSWORD),
pressImeActionButton()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,32 +23,25 @@ import com.flowcrypt.email.extensions.kotlin.asInternetAddress
import com.flowcrypt.email.junit.annotations.FlowCryptTestSettings
import com.flowcrypt.email.rules.AddPrivateKeyToDatabaseRule
import com.flowcrypt.email.rules.ClearAppSettingsRule
import com.flowcrypt.email.rules.FlowCryptMockWebServerRule
import com.flowcrypt.email.rules.GrantPermissionRuleChooser
import com.flowcrypt.email.rules.RetryRule
import com.flowcrypt.email.rules.ScreenshotTestRule
import com.flowcrypt.email.ui.base.BaseComposeScreenTest
import com.flowcrypt.email.ui.base.BaseComposeScreenNoKeyAvailableTest
import com.flowcrypt.email.util.PrivateKeysManager
import com.flowcrypt.email.util.TestGeneralUtil
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.RecordedRequest
import org.hamcrest.CoreMatchers.not
import org.junit.ClassRule
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.runner.RunWith
import java.net.HttpURLConnection

/**
* @author Denys Bondarenko
*/
@MediumTest
@RunWith(AndroidJUnit4::class)
@FlowCryptTestSettings(useCommonIdling = false)
class ComposeScreenNoKeyAvailableFlowTest : BaseComposeScreenTest() {
class ComposeScreenNoKeyAvailableSingleKeyWithPassphraseInDatabaseFlowTest : BaseComposeScreenNoKeyAvailableTest() {
private val addPrivateKeyToDatabaseRule = AddPrivateKeyToDatabaseRule(
keyPath = "pgp/[email protected]_prv_strong_primary.asc"
)
Expand Down Expand Up @@ -116,28 +109,10 @@ class ComposeScreenNoKeyAvailableFlowTest : BaseComposeScreenTest() {
.check(matches(not(hasTextColor(R.color.gray))))
}

companion object {
@get:ClassRule
@JvmStatic
val mockWebServerRule = FlowCryptMockWebServerRule(TestConstants.MOCK_WEB_SERVER_PORT,
object : Dispatcher() {
override fun dispatch(request: RecordedRequest): MockResponse {
if (request.path?.startsWith("/attester/pub", ignoreCase = true) == true) {
val lastSegment = request.requestUrl?.pathSegments?.lastOrNull()

when {
TestConstants.RECIPIENT_WITH_PUBLIC_KEY_ON_ATTESTER.equals(
lastSegment, true
) -> {
return MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(TestGeneralUtil.readResourceAsString("3.txt"))
}
}
}

return MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND)
}
})
@Test
fun testAddEmailToExistingSingleKeyPassphraseInDatabase() {
doTestAddEmailToExistingKey {
//no more additional actions
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* © 2016-present FlowCrypt a.s. Limitations apply. Contact [email protected]
* Contributors: DenBond7
*/

package com.flowcrypt.email.ui

import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.action.ViewActions.replaceText
import androidx.test.espresso.assertion.ViewAssertions.doesNotExist
import androidx.test.espresso.matcher.RootMatchers
import androidx.test.espresso.matcher.ViewMatchers.withId
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import com.flowcrypt.email.R
import com.flowcrypt.email.TestConstants
import com.flowcrypt.email.database.entity.KeyEntity
import com.flowcrypt.email.junit.annotations.FlowCryptTestSettings
import com.flowcrypt.email.rules.AddPrivateKeyToDatabaseRule
import com.flowcrypt.email.rules.ClearAppSettingsRule
import com.flowcrypt.email.rules.GrantPermissionRuleChooser
import com.flowcrypt.email.rules.RetryRule
import com.flowcrypt.email.rules.ScreenshotTestRule
import com.flowcrypt.email.ui.base.BaseComposeScreenNoKeyAvailableTest
import org.junit.Rule
import org.junit.Test
import org.junit.rules.RuleChain
import org.junit.rules.TestRule
import org.junit.runner.RunWith

/**
* @author Denys Bondarenko
*/
@MediumTest
@RunWith(AndroidJUnit4::class)
@FlowCryptTestSettings(useCommonIdling = false)
class ComposeScreenNoKeyAvailableSingleKeyWithPassphraseInRamFlowTest : BaseComposeScreenNoKeyAvailableTest() {
private val addPrivateKeyToDatabaseRule = AddPrivateKeyToDatabaseRule(
keyPath = "pgp/[email protected]_keyA_strong.asc",
passphraseType = KeyEntity.PassphraseType.RAM
)

@get:Rule
var ruleChain: TestRule = RuleChain
.outerRule(RetryRule.DEFAULT)
.around(ClearAppSettingsRule())
.around(GrantPermissionRuleChooser.grant(android.Manifest.permission.POST_NOTIFICATIONS))
.around(addAccountToDatabaseRule)
.around(addPrivateKeyToDatabaseRule)
.around(activeActivityRule)
.around(ScreenshotTestRule())

@Test
fun testAddEmailToExistingKey() {
doTestAddEmailToExistingKey {
onView(withId(R.id.buttonOk))
.check(doesNotExist())

waitForObjectWithText(getResString(R.string.provide_passphrase), 2000)

onView(withId(R.id.eTKeyPassword))
.inRoot(RootMatchers.isDialog())
.perform(
ViewActions.clearText(),
replaceText(TestConstants.DEFAULT_STRONG_PASSWORD),
ViewActions.pressImeActionButton()
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ class MessageDetailsFlowTest : BaseMessageDetailsFlowTest() {
}

@Test
@Ignore("Should be fixed before the next release")
fun testMissingKeyErrorChooseFromFewPubKeys() {
val msgInfo = getMsgInfo(
path = "messages/info/encrypted_msg_info_text_with_missing_key.json",
Expand Down
Loading

0 comments on commit da407eb

Please sign in to comment.