Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect matching of string #278

Closed
parasvora opened this issue Mar 8, 2019 · 13 comments
Closed

Incorrect matching of string #278

parasvora opened this issue Mar 8, 2019 · 13 comments
Assignees

Comments

@parasvora
Copy link

parasvora commented Mar 8, 2019

Software versions

  • OS: Mac OS HighSiera 10.13.6
  • Library version:
  • Node Version: node --version 11.6.0

Expected behaviour

Expected api response set from pact-jvm

private DslPart getResponseBody()  {
     return new PactDslJsonBody()
                     .stringType("content")
                     .stringValue("contentType","application/pdf")
}

Below is updated in the pact-broker

provider will respond with:

{
  "status": 200,
  "headers": {
    "Content-Type": "application/json; charset=UTF-8"
  },
  "body": {
    "content": "string",
    "contentType": "application/pdf"
   }
}

Below is the provider script in pact-node:

const { Verifier } = require('@pact-foundation/pact');
var package = require('../../package.json');
const { app } = require('../../app.js');

app.listen(8081, () => {
    console.log("itg-pdf-generator service listening on http://localhost:8081")
})


describe("Pact provider verification", () => {
    it("Validates the response", () => {
        let opts = {
            provider: "provider",
            logLevel: "DEBUG",
            providerBaseUrl: "http://localhost:8081",
            stateHandlers: {
                "Return response": () => {
                    return Promise.resolve(`Return response`);
                },
            },
            // Fetch pacts from broker
            pactBrokerUrl: "https://pactbroker-snapshot.kops-ci.company.tools",
            // Fetch from broker with given tags
            tags: ["master"],
            publishVerificationResult: true,
            providerVersion: package.version,
        }
        // Validates the pact & uploads the verification results to pact broker
        return new Verifier(opts).verifyProvider().then(output => {
            console.log(output);
        }).catch((error) => {
            console.log('error:', JSON.stringify(error.message))
        })
    })
})

The matching on the response for node content in the expected response should pass any string.

Actual behaviour

The word string is compared with the actual response.

Steps to reproduce

Provide a repository, gist or reproducible code snippet so that we can test the problem.

Consider forking the project and modifying the E2E test

Relevant log files

Please ensure you set logging to DEBUG and attach any relevant log files here (or link from a gist).

@mefellows
Copy link
Member

Thanks. This probably belongs in pact-js, not here.

Also, please attach your pact file and any relevant logs.

It looks like the matcher is not being serialised into the pact file, as it seems to be matching verbatim.

@mefellows mefellows transferred this issue from pact-foundation/pact-js-core Mar 8, 2019
@mefellows
Copy link
Member

Moved to pact js

@parasvora
Copy link
Author

parasvora commented Mar 8, 2019

Pact file attached
itg-composition-itg-pdf-generator.txt

log file below

log.log

@mefellows
Copy link
Member

mefellows commented Mar 9, 2019

@parasvora there appear to be multiple things wrong here. Firstly, your provider seems to be returning a bunch of base64 encoded things, but your test is expecting this much smaller object:

                "body": {
                    "content": "string",
                    "contentType": "application/pdf"
                }

I think you perhaps have the request/response backwards? Are you indeed expecting to get back a base64 encoded object when you are sending the base64 object in the first place?

Secondly, there are no matchers in the pact file, so any response is going to be matched exactly as you specified it - which is probably not what you want.

Thirdly, the state also seems a bit strange: "Return Base64 ecoded pdf stream". That seems to be more about the behaviour you want to see, rather than the "state" the provider should be in. The state should be some thing like "Document 1234 exists".

So for us to be able to help you, we're going to need to see the actual test code that you've written.

@parasvora
Copy link
Author

@mefellows

"body": {
                    "content": "string",
                    "contentType": "application/pdf"
                }

The content node contains a Base64 encoded string.

The snippet pasted above is exactly what I see in the pack broker upon using the below code,

private DslPart getRequestBody()  {
        JSONObject jSonRequest = null;
        try {
            InputStream is = getClass()
                    .getResourceAsStream(PATH_TO_TEST_DATA + FILE_HTML_REQUEST_BASE64);
            checkNotNull(is, String.format("File %s not found", FILE_HTML_REQUEST_BASE64));
            jSonRequest = GetFileContent.getFileContent(is);
        } catch (Exception e){
            e.printStackTrace();
        }

        return new PactDslJsonBody()
                .stringValue("header", jSonRequest.getString("header"))
                .stringValue("footer", jSonRequest.getString("footer"))
                .stringValue("body", jSonRequest.getString("body"))
                .object("page")
                .stringValue("format", "A4")
                .stringValue("height", "11in")
                .stringValue("width", "8.5in")
                .closeObject();
    }

private DslPart getResponseBody()  {
     return new PactDslJsonBody()
                     .stringType("content")
                     .stringValue("contentType","application/pdf")
}

public PactDslResponse buildPact(PactDslWithProvider builder) {
        final Map<String, String> header = ImmutableMap.<String, String>builder()
                .put("Content-Type", "application/json; charset=utf-8")
                .build();

        return builder
                .given("Return Base64 ecoded pdf stream")
                .uponReceiving("Request to fetch the Base64 ecoded pdf stream")
                .headers(header)
                .body(this.getRequestBody().asBody())
                .path(END_POINT)
                .method("POST")
                .willRespondWith()
                .headers(header)
                .body(this.getResponseBody().asBody())
                .status(200);
    }

My intention here is to check if there is a string that the node content contains in my response. I wont be bothering what is the content of the string.

Please let me know incase further information is needed.

@mefellows
Copy link
Member

mefellows commented Mar 11, 2019 via email

@parasvora
Copy link
Author

@mefellows String literals here is the value of the node content in the below json,

"body": {
                    "content": "string",
                    "contentType": "application/pdf"
                }

I am using the StringType("name") method to generate the expected response here.

For further clarity, I am attaching the actual request & response.

response.txt
request.txt

@mefellows
Copy link
Member

Thanks @parasvora. The problem is, that in your consumer test you're matching on string literals, and not the general string type. What this means is that when the provider responds, the values must match exactly as they are in the pact file. Which of course they aren't, because "content" does not match the 50k+ character base64 encoded string that it's returning.

At the very least, you need to change your matchers from stringValue to stringType as per those docs.

Unless I'm mistaking something greatly, at which point we'd love to have a reproducible project that we can download and run to validate this issue.

@parasvora
Copy link
Author

@mefellows
As you mentioned, I am using the method stringValue to generate the response body. Please refer the code below,

private DslPart getResponseBody()  {
     return new PactDslJsonBody()
                     .stringType("content")
                     .stringValue("contentType","application/pdf")
}

@mefellows
Copy link
Member

Apologies, you are right there.

@uglyog it seems no matchers are being generated for the content field which is using the stringType field - does anything seem out of the ordinary here? What's happening is that on the verification (in the JS project) the provider is sending a gigantic base64 encoded string which is obviously not a direct match for the literal string.

@parasvora
Copy link
Author

@mefellows
Yes, and in-spite of checking for presence a string value, it checks for the presence of a literal string in the node content.

@uglyog
Copy link
Member

uglyog commented Apr 13, 2019

@parasvora don't call .getBody() on your request and response bodies. That will return the actual body object, and the matchers will be dropped.

Instead:

        return builder
                .given("Return Base64 ecoded pdf stream")
                .uponReceiving("Request to fetch the Base64 ecoded pdf stream")
                .headers(header)
                .body(this.getRequestBody()) // <--
                .path(END_POINT)
                .method("POST")
                .willRespondWith()
                .headers(header)
                .body(this.getResponseBody()) // <--
                .status(200);

@mefellows
Copy link
Member

Closing due to inactivity. I believe there is a working solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants