0

I'm new to Pact.io and trying to get contract tests set up on our platform. The app is set up in such a way that each customer account has its own database schema which is directly tied to a URL subdomain. When making an API request, that URL subdomain must be provided in addition to the authorization header. I can create a static token to pass in with the consumer tests, but when Pact sends the request, it doesn't know which account to use. I don't see a way to pass in a URL subdomain as part of the consumer test and not sure how to force it to use a specific account on the provider side? Any ideas?

Here is the pact log. We are making a request for users and instead of the JSON body being returned, we get an HTML error page, even though the status code returns 200.

I, [2017-10-25T12:39:24.344559 #91639]  INFO -- : Running example 'Verifying a pact between bridge_perform and bridge_learn Given one user a get request for learn users with GET /api/learner/users returns a response which has a matching body'
I, [2017-10-25T12:41:40.962186 #91639]  INFO -- : Sending GET request to path: "/api/learner/users" with headers: {"HTTP_AUTHORIZATION"=>"Basic xxxxxxxxxxxxxxxxxxxxx"}, see debug logs for body
D, [2017-10-25T12:41:40.962234 #91639] DEBUG -- : body :
I, [2017-10-25T12:41:40.977995 #91639]  INFO -- : Received response with status: 200, headers: {"Content-Type"=>"text/html", "ETag"=>"W/\"1bd857d3e20d3ed50aa6f48b5be15f42\"", "Cache-Control"=>"max-age=0, private, must-revalidate", "X-Request-Id"=>"8dd9a9bf-da21-44b1-8b6b-9de486a7e9ea", "X-Runtime"=>"0.007579", "Content-Length"=>"630"}, see debug logs for body
D, [2017-10-25T12:41:40.978049 #91639] DEBUG -- : body: <!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Account Not Found</title>
    <link rel="stylesheet" href="/stylesheets/application.css" />
  </head>
  <body class="indigo-bg">
    <div role="main" class="large-content-area centered margin-t-xl text-center white">
      <h1 class="h1">Oh, snap!</h1>
      <p class="large">It looks like you've tried to access App without telling us which
  account you belong to.</p>
      <p class="large">To log in, try using your account's URL. Usually that looks
  something like https://myaccount.app.com.</p>
    </div>
  </body>
</html>

Here is an example of one of the consumer tests. As you can see, we create a mock provider that has no URL/Path, so no place to provide a subdomain on the URL which specifies the account needed.

public class AdminImportedUserId  {
  @Rule
  public PactProviderRuleMk2 mockProvider = new PactProviderRuleMk2("provider_app", PactSpecVersion.V2, this);

  @Pact(provider = "provider_app", consumer = "consumer_app")
  public RequestResponsePact createFragment(PactDslWithProvider builder) throws IOException {
    return builder
        .given("an admin with two imported users")
        .uponReceiving("a get request for admin imported user id")
        .path("/api/admin/users/imports/1")
        .method("GET")
        .headers(new ProviderClient().getHeaders())
        .willRespondWith()
        .status(200)
        .body("{\"meta\":{},\"linked\":{\"contexts\":[{\"id\":1,\"class\":\"Domain\"}]},\"imports\":[{\"id\":\"160\","
        + "\"context_id\":\"1\",\"user_name\":\"user10 Royer\",\"context_description\":\"Dev Environment\","
        + "\"context_type\":\"Domain\",\"completed\":17,\"total\":17,\"state\":\"complete\",\"new_user_count\":0,"
        + "\"restored_user_count\":0,\"updated_user_count\":17,\"deleted_user_count\":0,\"ignored_user_count\":0,"
        + "\"deported_user_count\":17,\"invalid_rows\":[],\"created_at\":\"2017-09-23T13:13:21.132-06:00\","
        + "\"user_id\":4078}]}")
        .toPact();
  }

1 Answers1

0

When you say "URL subdomain" are referring to a separate Host header e.g. someaccount.foo.com or a prefix on the URL e.g. `http://foo.com/someaccount'?

Either way, these would go into your consumer test as either the URL/Path or a specific header.

Matthew Fellows
  • 3,669
  • 1
  • 15
  • 18
  • A separate host e.g. `someaccount.foo.com` where `someaccount` is the name of the account. However, the consumer test doesn't specify a URL/Path. It creates a mock provider that has no url and is written in Java. I'll edit the above to include the consumer test. – molteninjabob Oct 26 '17 at 15:24
  • There is a way you can modify the request before it is replayed in the java impl (you'll just have to poke around in the docs because I'm not sure where it is, not being a java person). You could try overwriting the Host header there. – Beth Skurrie Oct 26 '17 at 21:11
  • @molteninjabob why not add the hostname in the `.headers(...)` clause? Hostname and URL are not the same thing – Matthew Fellows Oct 26 '17 at 22:18
  • I was able to do as you suggested and passed in the host through the headers: `"headers": { "Authorization": "Basic cGFjdF91c2VyOnBhY3Rfc2VjcmV0", "Host": "specs.lvh.me:3000" }` However, that still doesn't seem to work. At this point, it must be something missing on the back-end in the set-up, as it seems that the request contains everything needed. I can see that the account is already being seeded, but for some reason, when pact makes the request, it's not using it. I'm using the exact same set up for request specs, which work, but it doesn't for Pact. – molteninjabob Oct 27 '17 at 14:00
  • I'm not sure you can pass the port in the host header. Does it match the same port as the pact test? At this point we're going to need code to repro I think – Matthew Fellows Oct 27 '17 at 21:27