From 07084e33c3eaa3d19bb0cefacdec673751a87bbe Mon Sep 17 00:00:00 2001 From: DenBond7 Date: Wed, 8 Mar 2023 14:32:26 +0200 Subject: [PATCH] Updated FesDuringSetupEnterpriseFlowTest.| #2162 --- .../ui/FesDuringSetupEnterpriseFlowTest.kt | 281 +++++++++++------- 1 file changed, 177 insertions(+), 104 deletions(-) diff --git a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt index b3ee489ea2..fc1d5fcbee 100644 --- a/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt +++ b/FlowCrypt/src/androidTest/java/com/flowcrypt/email/ui/FesDuringSetupEnterpriseFlowTest.kt @@ -5,84 +5,50 @@ package com.flowcrypt.email.ui -import androidx.test.ext.junit.rules.activityScenarioRule +import androidx.test.espresso.Espresso.onView +import androidx.test.espresso.assertion.ViewAssertions.matches +import androidx.test.espresso.matcher.RootMatchers.withDecorView +import androidx.test.espresso.matcher.ViewMatchers.isDisplayed +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.api.retrofit.ApiHelper import com.flowcrypt.email.api.retrofit.response.api.ClientConfigurationResponse +import com.flowcrypt.email.api.retrofit.response.api.EkmPrivateKeysResponse +import com.flowcrypt.email.api.retrofit.response.api.FesServerResponse +import com.flowcrypt.email.api.retrofit.response.base.ApiError import com.flowcrypt.email.api.retrofit.response.model.ClientConfiguration +import com.flowcrypt.email.api.retrofit.response.model.Key +import com.flowcrypt.email.extensions.exceptionMsg 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.activity.MainActivity -import com.flowcrypt.email.ui.base.BaseSignTest +import com.flowcrypt.email.ui.base.BaseFesDuringSetupFlowTest import com.flowcrypt.email.util.TestGeneralUtil -import com.google.api.client.googleapis.json.GoogleJsonError -import com.google.api.client.googleapis.json.GoogleJsonErrorContainer -import com.google.api.client.json.Json -import com.google.api.client.json.gson.GsonFactory +import com.flowcrypt.email.util.exception.ApiException +import com.flowcrypt.email.util.exception.CommonConnectionException import com.google.gson.Gson -import okhttp3.mockwebserver.Dispatcher import okhttp3.mockwebserver.MockResponse import okhttp3.mockwebserver.RecordedRequest -import org.junit.Before -import org.junit.Ignore +import org.hamcrest.Matchers.containsString +import org.hamcrest.Matchers.`is` +import org.hamcrest.Matchers.not import org.junit.Rule import org.junit.Test import org.junit.rules.RuleChain -import org.junit.rules.TestName import org.junit.rules.TestRule import org.junit.runner.RunWith import java.net.HttpURLConnection +import java.net.SocketTimeoutException +import java.util.concurrent.TimeUnit /** * @author Denys Bondarenko */ @MediumTest @RunWith(AndroidJUnit4::class) -@Ignore("not completed") -class FesDuringSetupEnterpriseFlowTest : BaseSignTest() { - override val useIntents: Boolean = true - override val activityScenarioRule = activityScenarioRule( - TestGeneralUtil.genIntentForNavigationComponent( - destinationId = R.id.mainSignInFragment - ) - ) - - private val testNameRule = TestName() - private val mockWebServerRule = - FlowCryptMockWebServerRule(TestConstants.MOCK_WEB_SERVER_PORT, object : Dispatcher() { - override fun dispatch(request: RecordedRequest): MockResponse { - val gson = ApiHelper.getInstance(getTargetContext()).gson - - when { - request.path.equals("/api/v1/client-configuration?domain=flowcrypt.test") -> { - return handleClientConfigurationAPI(gson) - } - - request.requestUrl?.encodedPath == "/gmail/v1/users/me/messages" - && request.requestUrl?.queryParameterNames?.contains("q") == true -> { - val q = requireNotNull(request.requestUrl?.queryParameter("q")) - return when { - q.startsWith("from:${EMAIL_GMAIL}") -> - prepareMockResponseForPublicDomains(EMAIL_GMAIL) - - q.startsWith("from:${EMAIL_GOOGLEMAIL}") -> - prepareMockResponseForPublicDomains(EMAIL_GOOGLEMAIL) - - else -> MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) - } - } - } - - return MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) - } - }) - +class FesDuringSetupEnterpriseFlowTest : BaseFesDuringSetupFlowTest() { @get:Rule var ruleChain: TestRule = RuleChain .outerRule(RetryRule.DEFAULT) @@ -93,72 +59,179 @@ class FesDuringSetupEnterpriseFlowTest : BaseSignTest() { .around(activityScenarioRule) .around(ScreenshotTestRule()) - @Before - fun waitWhileToastWillBeDismissed() { - Thread.sleep(1000) + override fun handleAPI(request: RecordedRequest, gson: Gson): MockResponse { + return when { + request.path?.startsWith("/ekm") == true -> handleEkmAPI(request, gson) + else -> MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) + } + } + + override fun handleCheckIfFesIsAvailableAtCustomerFesUrl(gson: Gson): MockResponse { + return if ("testFesAvailableRequestTimeOutHasConnection" == testNameRule.methodName) { + MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setHeadersDelay(6, TimeUnit.SECONDS) + } else when (testNameRule.methodName) { + + "testFesAvailableHasConnectionHttpCode404" -> { + MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) + } + + "testFesAvailableHasConnectionHttpCodeNot200" -> { + MockResponse().setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR) + } + + "testFesAvailableWrongServiceName" -> { + MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(gson.toJson(FES_SUCCESS_RESPONSE.copy(service = "hello"))) + } + + else -> { + MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(gson.toJson(FES_SUCCESS_RESPONSE)) + } + } + } + + override fun handleClientConfigurationAPI(gson: Gson): MockResponse { + return MockResponse() + .setResponseCode(HttpURLConnection.HTTP_OK) + .setBody( + gson.toJson( + ClientConfigurationResponse( + clientConfiguration = ClientConfiguration( + flags = ACCEPTED_FLAGS, + keyManagerUrl = EMAIL_EKM_URL_SUCCESS, + ) + ) + ) + ) + } + + override fun handleClientConfigurationAPIForSharedTenantFes( + account: String?, + gson: Gson + ): MockResponse { + return when (account) { + //shared-tenant-fes allowed only for http code = 404 + EMAIL_FES_HTTP_404 -> MockResponse() + .setResponseCode(HttpURLConnection.HTTP_FORBIDDEN) + + else -> MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) + } } - /** - * Users of gmail.com just - */ @Test - fun testFlowForPublicEmailDomainsGmail() { - setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_GMAIL)) - checkIsSnackBarDisplayed(EMAIL_GMAIL) + fun testFesAvailableWrongServiceName() { + setupAndClickSignInButton(genMockGoogleSignInAccountJson(email = EMAIL_FES_NOT_ALLOWED_SERVER)) + isDialogWithTextDisplayed(decorView, getResString(R.string.fes_server_has_wrong_settings)) } @Test - fun testFlowForPublicEmailDomainsGoogleMail() { - setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_GOOGLEMAIL)) - checkIsSnackBarDisplayed(EMAIL_GOOGLEMAIL) + fun testFesAvailableRequestTimeOutHasConnection() { + setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_FES_REQUEST_TIME_OUT)) + isDialogWithTextDisplayed( + decorView, + getResString( + R.string.check_fes_error_with_retry, + com.flowcrypt.email.api.retrofit.response.base.Result.exception( + CommonConnectionException(SocketTimeoutException("timeout")) + ).exceptionMsg + ) + ) } - private fun handleClientConfigurationAPI(gson: Gson): MockResponse { - val responseCode = when (testNameRule.methodName) { - "testFesServerAvailableGetClientConfigurationFailed" -> HttpURLConnection.HTTP_FORBIDDEN - "testFesServerExternalServiceAlias" -> HttpURLConnection.HTTP_NOT_ACCEPTABLE - "testFesServerEnterpriseServerAlias" -> HttpURLConnection.HTTP_CONFLICT - "testCallFesUrlToGetClientConfigurationForEnterpriseUser" -> HttpURLConnection.HTTP_UNAUTHORIZED - else -> HttpURLConnection.HTTP_OK - } + @Test + fun testFesAvailableHasConnectionHttpCode404() { + setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_FES_HTTP_404)) + isDialogWithTextDisplayed( + decorView, + "ApiException:" + ApiException( + ApiError( + code = HttpURLConnection.HTTP_FORBIDDEN, + msg = "" + ) + ).message + ) + } - val body = when (testNameRule.methodName) { - "testFesServerAvailableGetClientConfigurationFailed", - "testFesServerExternalServiceAlias", - "testFesServerEnterpriseServerAlias", - "testCallFesUrlToGetClientConfigurationForEnterpriseUser" -> null - else -> gson.toJson( - ClientConfigurationResponse( - clientConfiguration = ClientConfiguration( - flags = emptyList() + @Test + fun testFesAvailableHasConnectionHttpCodeNot200() { + setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_FES_HTTP_NOT_404_NOT_SUCCESS)) + isDialogWithTextDisplayed( + decorView, + getResString( + R.string.fes_server_error, + com.flowcrypt.email.api.retrofit.response.base.Result.exception( + ApiException( + ApiError( + code = HttpURLConnection.HTTP_INTERNAL_ERROR, + msg = "" + ) ) - ) + ).exceptionMsg ) - } + ) + } - return MockResponse().setResponseCode(responseCode).apply { - body?.let { setBody(it) } - } + @Test + fun testFesAvailableSuccess() { + setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_FES_SUCCESS)) + Thread.sleep(2000) + onView(withText(R.string.set_pass_phrase)) + .check(matches(isDisplayed())) } - private fun prepareMockResponseForPublicDomains(string: String) = - MockResponse().setResponseCode(HttpURLConnection.HTTP_NOT_FOUND) - .setHeader("Content-Type", Json.MEDIA_TYPE) - .setBody(GoogleJsonErrorContainer().apply { - factory = GsonFactory.getDefaultInstance() - error = GoogleJsonError().apply { - code = HttpURLConnection.HTTP_NOT_FOUND - message = string - errors = listOf(GoogleJsonError.ErrorInfo().apply { - message = string - domain = "local" - reason = "notFound" - }) - } - }.toString()) + @Test + fun testFesAvailableSSLError() { + setupAndClickSignInButton(genMockGoogleSignInAccountJson(EMAIL_FES_SSL_ERROR)) + //as our mock server support only flowcrypt.test and flowcrypt.example we will receive + onView(withText(containsString("Hostname fes.wrongssl.test not verified"))) + .inRoot(withDecorView(not(`is`(decorView)))) + .check(matches(isDisplayed())) + } + + private fun handleEkmAPI(request: RecordedRequest, gson: Gson): MockResponse { + return when { + request.path.equals("/ekm/v1/keys/private") -> + MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(gson.toJson(EKM_FES_RESPONSE)) + + else -> MockResponse().setResponseCode(HttpURLConnection.HTTP_OK) + .setBody(gson.toJson(EkmPrivateKeysResponse(privateKeys = emptyList()))) + } + } companion object { - private const val EMAIL_GMAIL = "gmail@gmail.com" - private const val EMAIL_GOOGLEMAIL = "googlemail@googlemail.com" + private const val EMAIL_EKM_URL_SUCCESS = "https://flowcrypt.test/ekm/" + private const val EMAIL_FES_REQUEST_TIME_OUT = "fes_request_timeout@flowcrypt.test" + private const val EMAIL_FES_HTTP_404 = "fes_404@flowcrypt.test" + private const val EMAIL_FES_HTTP_NOT_404_NOT_SUCCESS = "fes_not404_not_success@flowcrypt.test" + private const val EMAIL_FES_NOT_ALLOWED_SERVER = "fes_not_allowed_server@flowcrypt.test" + private const val EMAIL_FES_SUCCESS = "fes_success@flowcrypt.test" + private const val EMAIL_FES_SSL_ERROR = "fes_ssl_error@wrongssl.test" + + private val ACCEPTED_FLAGS = listOf( + ClientConfiguration.ConfigurationProperty.PRV_AUTOIMPORT_OR_AUTOGEN, + ClientConfiguration.ConfigurationProperty.FORBID_STORING_PASS_PHRASE, + ClientConfiguration.ConfigurationProperty.NO_PRV_CREATE + ) + + private val EKM_FES_RESPONSE = EkmPrivateKeysResponse( + privateKeys = listOf( + Key( + TestGeneralUtil.readFileFromAssetsAsString("pgp/fes@flowcrypt.test_prv_decrypted.asc") + ) + ) + ) + + private val FES_SUCCESS_RESPONSE = FesServerResponse( + apiError = null, + vendor = "FlowCrypt", + service = "enterprise-server", + orgId = "localhost", + version = "2021", + endUserApiVersion = "v1", + adminApiVersion = "v1" + ) } }