package com.prateekj.snooper.networksnooper.activity; import android.app.Instrumentation; import android.content.ClipboardManager; import android.content.Intent; import android.support.test.espresso.intent.rule.IntentsTestRule; import com.google.common.collect.ImmutableMap; import com.prateekj.snooper.R; import com.prateekj.snooper.networksnooper.model.HttpCall; import com.prateekj.snooper.networksnooper.repo.SnooperRepo; import com.prateekj.snooper.networksnooper.viewmodel.HttpHeaderViewModel; import com.prateekj.snooper.rules.RealmCleanRule; import com.prateekj.snooper.rules.RunUsingLooper; import com.prateekj.snooper.utils.EspressoIntentMatchers; import org.hamcrest.CustomTypeSafeMatcher; import org.hamcrest.Matcher; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import java.util.List; import java.util.Map; import static android.app.Activity.RESULT_OK; import static android.content.Context.CLIPBOARD_SERVICE; import static android.content.Intent.ACTION_CHOOSER; import static android.content.Intent.ACTION_SEND; import static android.support.test.InstrumentationRegistry.getTargetContext; import static android.support.test.espresso.Espresso.onData; import static android.support.test.espresso.Espresso.onView; import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.intent.Intents.intended; import static android.support.test.espresso.intent.Intents.intending; import static android.support.test.espresso.intent.matcher.IntentMatchers.anyIntent; import static android.support.test.espresso.intent.matcher.IntentMatchers.hasAction; import static android.support.test.espresso.intent.matcher.IntentMatchers.hasExtras; import static android.support.test.espresso.matcher.ViewMatchers.assertThat; import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withId; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static com.prateekj.snooper.networksnooper.activity.HttpCallActivity.HTTP_CALL_ID; import static com.prateekj.snooper.utils.TestUtilities.getDate; import static com.prateekj.snooper.utils.TestUtilities.readFrom; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.Matchers.allOf; public class HttpCallActivityTest { @Rule public RealmCleanRule rule = new RealmCleanRule(); @Rule public RunUsingLooper runUsingLooper = new RunUsingLooper(); @Rule public IntentsTestRule<HttpCallActivity> activityRule = new IntentsTestRule<>(HttpCallActivity.class, true, false); private SnooperRepo snooperRepo; @Before public void setUp() throws Exception { snooperRepo = new SnooperRepo(rule.getRealm()); } @Test public void shouldRenderRequestAndResponseBody() throws Exception { String responseBody = readFrom("person_details_raw_response.json"); String requestPayload = readFrom("person_details_raw_request.json"); saveHttpCall("https://www.abc.com/person/1", "GET", 200, "OK", responseBody, requestPayload); Intent intent = new Intent(); intent.putExtra(HTTP_CALL_ID, 1); activityRule.launchActivity(intent); onView(withText(R.string.title_http_call_activity)).check(matches(isDisplayed())); onView(allOf(withId(R.id.payload_text), isDisplayed())) .check(matches(withText(readFrom("person_details_formatted_response.json")))); onView(withId(R.id.copy_menu)).perform(click()); assertThat(clipBoardText(), is(readFrom("person_details_formatted_response.json"))); onView(withText("REQUEST")).check(matches(isDisplayed())).perform(click()); onView(allOf(withId(R.id.payload_text), isDisplayed())) .check(matches(withText(readFrom("person_details_formatted_request.json")))); onView(withId(R.id.copy_menu)).perform(click()); assertThat(clipBoardText(), is(readFrom("person_details_formatted_request.json"))); onView(withText("HEADERS")).check(matches(isDisplayed())).perform(click()); onView(withText("https://www.abc.com/person/1")).check(matches(isDisplayed())); onView(withText("GET")).check(matches(isDisplayed())); onView(withText("200")).check(matches(isDisplayed())); onView(withText("OK")).check(matches(isDisplayed())); onView(withText("06/02/2017 11:22:33")).check(matches(isDisplayed())); onView(withText(R.string.response_headers)).perform(click()); verifyResponseHeader("content-type", "application/json"); verifyResponseHeader("cache-control", "no-cache"); verifyResponseHeader("content-disposition", "attachment"); verifyResponseHeader("date", "Sun, 02 Apr 2017 08:54:39 GMT"); onView(withText(R.string.request_headers)).perform(click()); verifyRequestHeader("content-type", "application/json"); verifyRequestHeader("content-length", "403"); verifyRequestHeader("accept-language", "en-US,en;q=0.8,hi;q=0.6"); verifyRequestHeader(":scheme", "https"); intending(anyIntent()).respondWith(new Instrumentation.ActivityResult(RESULT_OK, new Intent())); onView(withId(R.id.share_menu)).perform(click()); verifyClickActionOnShareMenu(); } private void verifyResponseHeader(String headerName, String headerValue) { onData(withHeaderData(headerName, headerValue)). inAdapterView(withId(R.id.response_header_list)). check(matches(allOf(hasDescendant(withText(headerName)), hasDescendant(withText(headerValue))))); } private void verifyRequestHeader(String headerName, String headerValue) { onData(withHeaderData(headerName, headerValue)). inAdapterView(withId(R.id.request_header_list)). check(matches(allOf(hasDescendant(withText(headerName)), hasDescendant(withText(headerValue))))); } private Matcher<HttpHeaderViewModel> withHeaderData(final String headerName, final String headerValue) { return new CustomTypeSafeMatcher<HttpHeaderViewModel>("Header with") { @Override protected boolean matchesSafely(HttpHeaderViewModel viewModel) { return viewModel.headerName().equals(headerName) && viewModel.headerValues().equals(headerValue); } }; } private String clipBoardText() { ClipboardManager clipboard = (ClipboardManager) getTargetContext().getSystemService(CLIPBOARD_SERVICE); int lastItemIndex = clipboard.getPrimaryClip().getItemCount() - 1; return clipboard.getPrimaryClip().getItemAt(lastItemIndex).getText().toString(); } private void saveHttpCall(String url, String method, int statusCode, String statusText, String responseBody, String requestPayload) { Map<String, List<String>> requestHeaders = ImmutableMap.of( "content-type", singletonList("application/json"), "content-length", singletonList("403"), "accept-language", asList("en-US,en", "q=0.8,hi", "q=0.6"), ":scheme", singletonList("https") ); Map<String, List<String>> responseHeaders = ImmutableMap.of( "content-type", singletonList("application/json"), "cache-control", singletonList("no-cache"), "content-disposition", singletonList("attachment"), "date", singletonList("Sun, 02 Apr 2017 08:54:39 GMT") ); HttpCall httpCall = new HttpCall.Builder() .withUrl(url) .withMethod(method) .withStatusCode(statusCode) .withStatusText(statusText) .withResponseBody(responseBody) .withPayload(requestPayload) .withRequestHeaders(requestHeaders) .withResponseHeaders(responseHeaders) .build(); httpCall.setDate(getDate(2017, 5, 2, 11, 22, 33)); snooperRepo.save(httpCall); } private void verifyClickActionOnShareMenu() { intended(allOf( hasExtras(EspressoIntentMatchers.forMailChooserIntent(ACTION_SEND, "*/*", "Log details", "2017_06_02_11_22_33.txt")), hasAction(ACTION_CHOOSER))); } }