package org.commcare.android.tests.activities; import android.content.Intent; import android.view.View; import android.widget.Button; import android.widget.TextView; import org.commcare.CommCareApplication; import org.commcare.CommCareTestApplication; import org.commcare.activities.PostRequestActivity; import org.commcare.android.CommCareTestRunner; import org.commcare.android.mocks.HttpURLConnectionMock; import org.commcare.android.mocks.ModernHttpRequesterMock; import org.commcare.android.util.ActivityLaunchUtils; import org.commcare.android.util.TestAppInstaller; import org.commcare.dalvik.R; import org.commcare.models.AndroidSessionWrapper; import org.commcare.modern.util.Pair; import org.commcare.network.HttpRequestEndpointsMock; import org.commcare.network.LocalReferencePullResponseFactory; import org.commcare.session.CommCareSession; import org.commcare.session.RemoteQuerySessionManager; import org.javarosa.core.model.instance.ExternalDataInstance; import org.javarosa.core.services.locale.Localization; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowActivity; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * @author Phillip Mates (pmates@dimagi.com) */ @Config(application = CommCareTestApplication.class) @RunWith(CommCareTestRunner.class) public class PostRequestActivityTest { @Before public void setup() { TestAppInstaller.installAppAndLogin( "jr://resource/commcare-apps/case_search_and_claim/profile.ccpr", "test", "123"); } @Test public void postingToNonHttpsURLTest() { // NOTE PLM: we will eventually support 'http' urls, but won't include authentication credentials in them String urlString = "http://bad.url.com"; PostRequestActivity postRequestActivity = buildPostActivity(urlString); assertErrorMessage(postRequestActivity, true, Localization.get("post.not.using.https", urlString)); } private static void assertErrorMessage(PostRequestActivity postRequestActivity, boolean isVisible, String expectedErrorMessage) { TextView errorMessage = (TextView)postRequestActivity.findViewById(R.id.error_message); if (isVisible) { assertEquals(View.VISIBLE, errorMessage.getVisibility()); } else { assertFalse(View.VISIBLE == errorMessage.getVisibility()); } if (expectedErrorMessage != null) { assertEquals(expectedErrorMessage, errorMessage.getText()); } } private static PostRequestActivity buildPostActivity(String urlString) { URL url = stringToUrl(urlString); Intent postLaunchIntent = new Intent(); if (url != null) { postLaunchIntent.putExtra(PostRequestActivity.URL_KEY, url); postLaunchIntent.putExtra(PostRequestActivity.PARAMS_KEY, new HashMap<String, String>()); } return Robolectric.buildActivity(PostRequestActivity.class).withIntent(postLaunchIntent) .create().start().resume().get(); } @Test public void postingWithoutExtrasTest() { PostRequestActivity postRequestActivity = buildPostActivity(null); assertErrorMessage(postRequestActivity, true, Localization.get("post.generic.error")); } @Test public void unknownResponseFromServerTest() { int unknownResponseCode = 711028100; String expectedErrorMessage = Localization.get("post.unknown.response", unknownResponseCode + ""); assertPostFailureMessage(expectedErrorMessage, 711028100); } private static void assertPostFailureMessage(String expectedErrorMessage, int responseCode) { ModernHttpRequesterMock.setResponseCodes(new Integer[]{responseCode}); PostRequestActivity postRequestActivity = buildPostActivity("https://www.fake.com"); assertErrorMessage(postRequestActivity, true, expectedErrorMessage); } @Test public void redirectErrorResponseFromServerTest() { int responseCode = 320; assertPostFailureMessage(Localization.get("post.redirection.error", responseCode + ""), responseCode); } @Test public void clientErrorResponseFromServerTest() { int responseCode = 400; assertPostFailureMessage(Localization.get("post.client.error", responseCode + ""), responseCode); } @Test public void clientGoneErrorTest() { int responseCode = 410; assertPostFailureMessage(Localization.get("post.gone.error"), responseCode); } @Test public void clientConflicErrorTest() { int responseCode = 409; assertPostFailureMessage(Localization.get("post.conflict.error"), responseCode); } @Test public void serverErrorResponseFromServerTest() { int responseCode = 550; assertPostFailureMessage(Localization.get("post.server.error", responseCode + ""), responseCode); } @Test public void ioErrorInResponseFromServerTest() { ModernHttpRequesterMock.setResponseCodes(new Integer[]{200}); ModernHttpRequesterMock.setRequestPayloads(new String[]{null}); assertPostFailureMessage(Localization.get("post.io.error", HttpURLConnectionMock.ioErrorMessage), 200); } @Test public void retryClaimTest() { ModernHttpRequesterMock.setResponseCodes(new Integer[]{500, 200}); HttpRequestEndpointsMock.setCaseFetchResponseCodes(new Integer[]{200}); LocalReferencePullResponseFactory.setRequestPayloads(new String[]{"jr://resource/commcare-apps/case_search_and_claim/empty_restore.xml"}); PostRequestActivity postRequestActivity = buildPostActivity("https://www.fake.com"); Button retryButton = (Button)postRequestActivity.findViewById(R.id.request_button); assertEquals(View.VISIBLE, retryButton.getVisibility()); retryButton.performClick(); assertErrorMessage(postRequestActivity, false, null); assertTrue(postRequestActivity.isFinishing()); } /** * Launch post request through session dispatch */ @Test public void makeSuccessfulPostRequestTest() { ModernHttpRequesterMock.setResponseCodes(new Integer[]{200}); HttpRequestEndpointsMock.setCaseFetchResponseCodes(new Integer[]{200}); LocalReferencePullResponseFactory.setRequestPayloads(new String[]{"jr://resource/commcare-apps/case_search_and_claim/empty_restore.xml"}); AndroidSessionWrapper sessionWrapper = CommCareApplication.instance().getCurrentSessionWrapper(); CommCareSession session = sessionWrapper.getSession(); session.setCommand("patient-search"); InputStream is = PostRequestActivity.class.getClassLoader().getResourceAsStream("commcare-apps/case_search_and_claim/good-query-result.xml"); RemoteQuerySessionManager remoteQuerySessionManager = RemoteQuerySessionManager.buildQuerySessionManager(sessionWrapper.getSession(), sessionWrapper.getEvaluationContext()); Pair<ExternalDataInstance, String> instanceOrError = remoteQuerySessionManager.buildExternalDataInstance(is); session.setQueryDatum(instanceOrError.first); session.setDatum("case_id", "321"); ShadowActivity shadowActivity = ActivityLaunchUtils.buildHomeActivity(); Intent postActivityIntent = shadowActivity.getNextStartedActivity(); String intentActivityName = postActivityIntent.getComponent().getClassName(); assertTrue(intentActivityName.equals(PostRequestActivity.class.getName())); assertEquals("https://www.fake.com/claim_patient/", postActivityIntent.getSerializableExtra(PostRequestActivity.URL_KEY).toString()); HashMap<String, String> postUrlParams = (HashMap<String, String>)postActivityIntent.getSerializableExtra(PostRequestActivity.PARAMS_KEY); assertEquals("321", postUrlParams.get("selected_case_id")); PostRequestActivity postRequestActivity = Robolectric.buildActivity(PostRequestActivity.class).withIntent(postActivityIntent) .create().start().resume().get(); assertTrue(postRequestActivity.isFinishing()); } private static URL stringToUrl(String urlAsString) { if (urlAsString == null) { return null; } try { return new URL(urlAsString); } catch (MalformedURLException e) { fail(e.getMessage()); return null; } } }