content: package com.pivotallabs.api;
  
  import com.pivotallabs.util.Strings;
  import org.apache.http.HttpRequest;
  import org.apache.http.auth.AuthScope;
  import org.apache.http.client.CredentialsProvider;
  import org.apache.http.client.methods.HttpGet;
  import org.apache.http.client.methods.HttpPost;
  import org.apache.http.client.protocol.ClientContext;
  import org.hamcrest.CoreMatchers;
  import org.junit.Before;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.robolectric.Robolectric;
  import org.robolectric.RobolectricTestRunner;
  import org.robolectric.tester.org.apache.http.HttpRequestInfo;
  
  import java.io.InputStream;
  import java.util.Map;
  
  import static com.pivotallabs.TestResponses.GENERIC_XML;
  import static com.pivotallabs.util.TestUtil.asString;
  import static org.hamcrest.CoreMatchers.not;
  import static org.hamcrest.CoreMatchers.nullValue;
  import static org.hamcrest.CoreMatchers.sameInstance;
  import static org.hamcrest.core.IsEqual.equalTo;
  import static org.junit.Assert.assertThat;
  
  @RunWith(RobolectricTestRunner.class)
  public class ApiGatewayTest {
      private ApiGateway apiGateway;
      private TestApiResponseCallbacks responseCallbacks;
  
      @Before
      public void setUp() throws Exception {
          apiGateway = new ApiGateway();
          responseCallbacks = new TestApiResponseCallbacks();
      }
  
      @Test
      public void dispatch_shouldCallOntoTheSuccessWhenApiResponseIsSuccess() throws Exception {
          XmlApiResponse apiResponse = new XmlApiResponse(200);
          apiGateway.dispatch(apiResponse, responseCallbacks);
  
          assertThat(responseCallbacks.successResponse, sameInstance(apiResponse));
          assertThat(responseCallbacks.failureResponse, nullValue());
          assertThat(responseCallbacks.onCompleteWasCalled, equalTo(true));
      }
  
      @Test
      public void dispatch_shouldCallOnFailureWhenApiResponseIsFailure() throws Exception {
          XmlApiResponse apiResponse = new XmlApiResponse(500);
          apiGateway.dispatch(apiResponse, responseCallbacks);
  
          assertThat(responseCallbacks.failureResponse, sameInstance((ApiResponse) apiResponse));
          assertThat(responseCallbacks.successResponse, nullValue());
          assertThat(responseCallbacks.onCompleteWasCalled, equalTo(true));
      }
  
      @Test
      public void dispatch_shouldCallOnFailureWhenXmlParseErrorOccurs() throws Exception {
          Robolectric.addPendingHttpResponse(200, "Invalid x-shmail");
          apiGateway.makeRequest(new TestGetRequest(), responseCallbacks);
          assertThat(responseCallbacks.successResponse, nullValue());
          assertThat(responseCallbacks.failureResponse, not(nullValue()));
          assertThat(responseCallbacks.onCompleteWasCalled, equalTo(true));
      }
  
      @Test
      public void dispatch_shouldCallOnFailureWhenOnSuccessFails() throws Exception {
          XmlApiResponse apiResponse = new XmlApiResponse(200);
  
          TestApiResponseCallbacks callbacks = new TestApiResponseCallbacks() {
              @Override
              public void onSuccess(XmlApiResponse successResponse) {
                  throw new RuntimeException("boom!");
              }
          };
          apiGateway.dispatch(apiResponse, callbacks);
          assertThat(callbacks.failureResponse, sameInstance((ApiResponse) apiResponse));
          assertThat(callbacks.onCompleteWasCalled, equalTo(true));
      }
  
      @Test
      public void shouldMakeRemoteGetCalls() {
          Robolectric.getBackgroundScheduler().pause();
  
          TestGetRequest apiRequest = new TestGetRequest();
          apiGateway.makeRequest(apiRequest, responseCallbacks);
  
          Robolectric.addPendingHttpResponse(200, GENERIC_XML);
  
          Robolectric.getBackgroundScheduler().runOneTask();
  
          HttpRequestInfo sentHttpRequestData = Robolectric.getSentHttpRequestInfo(0);
          HttpRequest sentHttpRequest = sentHttpRequestData.getHttpRequest();
          assertThat(sentHttpRequest.getRequestLine().getUri(), equalTo("www.example.com"));
          assertThat(sentHttpRequest.getRequestLine().getMethod(), equalTo(HttpGet.METHOD_NAME));
  
          assertThat(sentHttpRequest.getHeaders("foo")[0].getValue(), equalTo("bar"));
  
          CredentialsProvider credentialsProvider =
                  (CredentialsProvider) sentHttpRequestData.getHttpContext().getAttribute(ClientContext.CREDS_PROVIDER);
          assertThat(credentialsProvider.getCredentials(AuthScope.ANY).getUserPrincipal().getName(), CoreMatchers.equalTo("spongebob"));
          assertThat(credentialsProvider.getCredentials(AuthScope.ANY).getPassword(), CoreMatchers.equalTo("squarepants"));
      }
  
      @Test
      public void shouldMakeRemotePostCalls() throws Exception {
          Robolectric.getBackgroundScheduler().pause();
  
          TestPostRequest apiRequest = new TestPostRequest();
          apiGateway.makeRequest(apiRequest, responseCallbacks);
  
          Robolectric.addPendingHttpResponse(200, GENERIC_XML);
  
          Robolectric.getBackgroundScheduler().runOneTask();
  
          HttpRequestInfo sentHttpRequestData = Robolectric.getSentHttpRequestInfo(0);
          HttpRequest sentHttpRequest = sentHttpRequestData.getHttpRequest();
          assertThat(sentHttpRequest.getRequestLine().getUri(), equalTo("www.example.com"));
          assertThat(sentHttpRequest.getRequestLine().getMethod(), equalTo(HttpPost.METHOD_NAME));
  
          assertThat(sentHttpRequest.getHeaders("foo")[0].getValue(), equalTo("bar"));
  
          InputStream contentStream = ((HttpPost) sentHttpRequest).getEntity().getContent();
  
          assertThat(Strings.fromStream(contentStream), CoreMatchers.equalTo("post body content"));
  
          CredentialsProvider credentialsProvider =
                  (CredentialsProvider) sentHttpRequestData.getHttpContext().getAttribute(ClientContext.CREDS_PROVIDER);
          assertThat(credentialsProvider.getCredentials(AuthScope.ANY).getUserPrincipal().getName(), CoreMatchers.equalTo("spongebob"));
          assertThat(credentialsProvider.getCredentials(AuthScope.ANY).getPassword(), CoreMatchers.equalTo("squarepants"));
      }
  
      @Test
      public void shouldDispatchUponReceivingResponse() throws Exception {
          Robolectric.getBackgroundScheduler().pause();
          Robolectric.getUiThreadScheduler().pause();
  
          Robolectric.addPendingHttpResponse(200, GENERIC_XML);
  
          apiGateway.makeRequest(new TestGetRequest(), responseCallbacks);
          Robolectric.getBackgroundScheduler().runOneTask();
  
          assertThat(responseCallbacks.successResponse, nullValue());
  
          Robolectric.getUiThreadScheduler().runOneTask();
  
          assertThat(asString(responseCallbacks.successResponse.getResponseDocument()), equalTo(GENERIC_XML));
      }
  
      private class TestGetRequest extends ApiRequest<XmlApiResponse> {
          @Override
          public String getUrlString() {
              return "www.example.com";
          }
  
          @Override
          public Map<String, String> getParameters() {
              Map<String, String> parameters = super.getParameters();
              parameters.put("baz", "bang");
              return parameters;
          }
  
          @Override
          public Map<String, String> getHeaders() {
              Map<String, String> headers = super.getHeaders();
              headers.put("foo", "bar");
              return headers;
          }
  
          @Override
          public String getMethod() {
              return HttpGet.METHOD_NAME;
          }
  
          @Override
          public String getPostBody() {
              return super.getPostBody();
          }
  
          @Override
          public String getUsername() {
              return "spongebob";
          }
  
          @Override
          public String getPassword() {
              return "squarepants";
          }
  
          @Override
          public XmlApiResponse createResponse(int statusCode) {
              return new XmlApiResponse(statusCode);
          }
      }
  
      private class TestPostRequest extends ApiRequest {
          @Override
          public String getUrlString() {
              return "www.example.com";
          }
  
          @Override
          public Map<String, String> getParameters() {
              Map<String, String> parameters = super.getParameters();
              parameters.put("baz", "bang");
              return parameters;
          }
  
          @Override
          public Map<String, String> getHeaders() {
              Map<String, String> headers = super.getHeaders();
              headers.put("foo", "bar");
              return headers;
          }
  
          @Override
          public String getMethod() {
              return HttpPost.METHOD_NAME;
          }
  
          @Override
          public String getPostBody() {
              return "post body content";
          }
  
          @Override
          public String getUsername() {
              return "spongebob";
          }
  
          @Override
          public String getPassword() {
              return "squarepants";
          }
  
          @Override
          public ApiResponse createResponse(int statusCode) {
              return new XmlApiResponse(statusCode);
          }
      }
  }
  