Hi @All, can someone help me with the below error....
# pact-js
s
Hi @All, can someone help me with the below error. I am quiet confused with the response. I have followed the below WIKI age for setting up the consumer based contract. https://docs.pact.io/implementation_guides/javascript/docs/consumer
Copy code
yarn test:consumer
yarn run v1.22.17
$ jest __tests__/contract/consumer --runInBand --setupFiles ./__tests__/helpers/pactSetup.js --setupTestFrameworkScriptFile=./__tests__/helpers/pactTestWrapper.js

 RUNS  __tests__/contract/consumer/ClientsConsumer.spec.js
[14:40:14.473] ERROR (23284): pact@11.0.2: Test failed for the following reasons:

  Mock server failed with the following mismatches:

        0) The following request was expected but not received:
            Method: GET
            Path: /api/employees
            Headers:
              Accept: application/json
\__tests__\contract\consumer\ClientsConsumer.spec.js:81
      expect(response.headers['Content-Type']).toBe("application/json");                           ^

TypeError: Cannot read properties of undefined (reading 'Content-Type')
👋 1
j
Hi! How
response
is instantiated? Is it something from Pact or your code? Could you share the test file?
s
Copy code
describe("GET All Employees", () => {

        provider
            .given('I have a list of empoyees')
            .uponReceiving('a request for getting all employees')
            .withRequest({
                method: 'GET',
                path: '/api/employees',
                headers: { Accept: 'application/json' },
            })
            .willRespondWith({
                status: 200,
                headers: { 'Content-Type': 'application/json' },
                body: GET_EMPLOYEES_EXPECTED_BODY,
            });

   
        return provider.executeTest((mockserver) => {
            console.log("mockserver.url: " + mockserver.url);
            console.log("mockserver.port: " + mockserver.port);
            const employeeService = new EmployeeService(mockserver.url, mockserver.port);
            const response = employeeService.getEmployees();
            console.log("response: " + response);
            expect(response.headers['Content-Type']).toBe("application/json");
            expect(response.data).toEqual(GET_EMPLOYEES_EXPECTED_BODY);
            expect(response.status).toEqual(200);
        });
    });
Copy code
class EmployeeService {

  constructor(baseUrl, port) {
      this.baseUrl = baseUrl;
      this.port = port;
  }

  getEmployees = async () => {
    const response = await axios.get(`${this.baseUrl}:${this.port}/api/employees`).then((res) => {
        return res
      })
      .catch((error) => {
        console.log("Exception while fetching the employees");
        return error.res
      })
    //  console.log("response header: " + response.headers['content-type']);
    return response
  };
Pactsetup.js
Copy code
global.port = 8081
global.provider = new PactV3({
  port: global.port,
  log: path.resolve(process.cwd(), "__tests__/contract/logs", "mockserver-integration.log"),
  dir: path.resolve(process.cwd(), "__tests__/contract/pacts"),
  spec: 2,
  logLevel: 'INFO',
  pactfileWriteMode: "overwrite",
  consumer: "Frontend",
  provider: "EmployeeService",
})
j
you lack
await
before calling
getEmployees
s
ok, let me try that @Jan Królikowski Thanks for your support 🙂
✅ 1
@Jan KrĂłlikowski Even If i use Async wait, facing the same issue.
Copy code
return provider.executeTest(async(mockserver) => {
            const employeeService = new EmployeeService(mockserver.url, mockserver.port);
            const response = await employeeService.getEmployees();
            expect(await response.headers['Content-Type']).toBe("application/json");
            expect(await response.data).toEqual(GET_EMPLOYEES_EXPECTED_BODY);
            expect(await response.status).toEqual(200);
        });
j
could you
console.log
the response in the test? Maybe the request isn’t fired at all.
s
I tried doing that @Jan KrĂłlikowski It was strange that it didn't print any value
I might be missing something, but not able to find it.
j
you added
await
to the response in the
except
methods? That’s not how it should work 🙂 it should be plain javascript object here, so no need for
await
here
s
Copy code
const employeeService = new EmployeeService(mockserver.url, mockserver.port);
            const response = await employeeService.getEmployees();
            expect(response.headers['Content-Type']).toBe("application/json");
            expect(response.data).toEqual(GET_EMPLOYEES_EXPECTED_BODY);
            expect(response.status).toEqual(200);
Removed, but still its the same response @Jan KrĂłlikowski
j
and you still get the same message?
Copy code
TypeError: Cannot read properties of undefined (reading 'Content-Type')
s
Yes @Jan KrĂłlikowski
Copy code
expect(response.headers['Content-Type']).toBe("application/json");
                              ^

TypeError: Cannot read properties of undefined (reading 'headers')
j
so the response is undefined here
let’s go back to your service
s
ok..
Copy code
//import axios from "axios";
import axios from "axios";

//const baseURL = "<http://localhost:8080>";

class EmployeeService {

  constructor(baseUrl, port) {
      this.baseUrl = baseUrl;
      this.port = port;
  }

  getEmployees = async () => {
    const response = await axios.get(`${this.baseUrl}:${this.port}/api/employees`).then((res) => {
        return res
      })
      .catch((error) => {
        console.log("Exception while fetching the employees");
        return error.res
      })
    //  console.log("response header: " + response.headers['content-type']);
    return response
  };

}

export default EmployeeService;
This is my complete file
j
if you remove
then
and
catch
parts from the call:
Copy code
getEmployees = async () => {
    const response = await axios.get(`${this.baseUrl}:${this.port}/api/employees`)
    return response
  };
what’s the return value of the
getEmployees
method?
s
Let me check
I replaced the getEmployee method with the below one.
Copy code
getEmployees = async () => {
    return axios.request({
      baseURL: this.url,
      headers: { Accept: 'application/json' },
      method: 'GET',
      url: '/api/employees',
    });
  };
Now when I run, getting the below error.
Copy code
Test suite failed to run

    Your test suite must contain at least one test.

      at onResult (node_modules/@jest/core/build/TestScheduler.js:173:18)

  console.log
      ● Test suite failed to run

        Returning a Promise from "describe" is not supported. Tests must be defined synchronously.
        Returning a value from "describe" will fail the test in a future version of Jest.

          42 |    // afterEach(() => provider.verify())
          43 |
        > 44 |     describe("GET All Employees", async () => {
             |     ^
          45 |
          46 |         provider
          47 |             .given('I have a list of empoyees')
j
that’s better, and it’s true, you cannot. You have to add a
test
method here, within
describe
. Or rename
describe
to
test
, that should work as well.
s
I replaced the describe with test and ran again, the response is,
Copy code
Test suite failed to run

    TypeError: provider.finalize is not a function

      5 | afterEach(() => provider.verify()); // Ensure the mock provider verifies expected interactions for each test       
      6 |
    > 7 | afterAll(() => provider.finalize())
        |                         ^

      at Object.<anonymous> (__tests__/helpers/pactTestWrapper.js:7:25)
j
s
I have commented the below piece of code,
Copy code
// beforeAll(() => provider.setup())

// afterEach(() => provider.verify());

// afterAll(() => provider.finalize())
Then I am getting the below error,
Copy code
Employee Clients Service

    Tests cannot be nested.
I replaced the main test block with describe and ran again,
Copy code
Employee Clients Service â€ș GET All Employees

    AxiosError: Network Error

      at XMLHttpRequest.handleError (node_modules/axios/lib/adapters/xhr.js:154:14)
      at XMLHttpRequest.<anonymous> (node_modules/jsdom/lib/jsdom/living/helpers/create-event-accessor.js:33:32)
      at innerInvokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:316:27)
      at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:267:3)
      at XMLHttpRequestEventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:214:9)      
      at fireAnEvent (node_modules/jsdom/lib/jsdom/living/helpers/events.js:17:36)
      at requestErrorSteps (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:121:3)
      at Object.dispatchError (node_modules/jsdom/lib/jsdom/living/xhr-utils.js:51:3)
      at Request.<anonymous> (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:675:20)
      at Request.onRequestError (node_modules/request/request.js:877:8)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        10.534s
Ran all test suites matching /__tests__\\contract\\consumer/i.
  console.error
    Error: Error: connect ECONNREFUSED ::1:80
j
ok, it seems like it’s not something related with the Pact itself
gotta go for now, please refer to the examples in pact-js Github
✅ 1
s
Thank you @Jan KrĂłlikowski for your support
y
Can you create a repro in a github repo to share?
✅ 1
Nice one for the support Jan 🙌
✅ 1
t
Taco for @Jan Królikowski 🌼 !
I’m not sure what’s going on here, but you may want to check your test structure
I don’t think this is a Pact problem. Probably there are at least three things happening: 1) As Jan pointed out, you need to await the appropriate parts of the test. Anything that returns a promise must be `await`ed, and you must either make your `test`/
it
function
async
or return a promise from the test function. 2) You can’t currently make that change, as the order of `test`/`it` and
describe
blocks is not correct. Without seeing your full code, it’s hard to advise, but in general: you can have multiple describes (even nested), but you must only have one
test
or
it
, and it must not have
describe
inside it. Check the documentation for your test runner (Jest or Mocha, probably?) for more information. 3) Your code is not calling the mock correctly, and you’re getting an error response back, which was originally returning
undefined
because of the
catch
block returning
error.res
, which doesn’t exist on an
AxiosError: Network Error
. This is why Jan suggested removing the
catch
- long term, you’ll want to improve the error handler in your code. Check the axios error handling docs for an example. As to why it is getting a network error, I would try printing out
${this.baseUrl}:${this.port}/api/employees
in your EmployeeService to check that it is reasonable - although I suspect it will start working once your `await`s are in the right place.
✅ 2
s
I noticed that baseUrl is having already the port number and I am appending port number again. After removing the portnumber its worked. Thank you all for your support 🙂
j
wow, it was right in front of our eyes all the time! 😉 nice job figuring it out.
🙌 1
🙂 1