Search code examples
javascriptnode.jspact

Cannot read property of undefined thrown from running NPM and PACT


I'm trying to follow the PACT workshop example with some alternate data.

This may be more of a Javascript/Node question but I'm a but stumped, as a novice.

Given a consumer.spec.js file of:

const chai = require('chai');
const nock = require('nock');
const chaiAsPromised = require('chai-as-promised');
const expect = chai.expect;
const API_PORT = process.env.API_PORT || 9123;
chai.use(chaiAsPromised);

const API_HOST = `http://localhost:${API_PORT}`;

describe('Consumer', () => {
  describe('when a call to the Provider is made', () => {
    const clothingStatus = 'hello';
    const {emailClothingOfferStatus} = require('../client');

    it('can process the HTML payload from the provider', () => {
      nock(API_HOST)
        .get('/provider')
        .query({validPermStatus:'hello'})
        .reply(200, {
          test:'NO',
          validPermStatus: clothingStatus,
          count: 1000,
        });

      const response = emailClothingOfferStatus(clothingStatus);

      return expect(response.body.clothingStatus).to.eventually.equal('hello')
    })
  })
});

and a client .js file of:

const request = require('superagent');
const API_HOST = process.env.API_HOST || 'http://localhost';
const API_PORT = process.env.API_PORT || 9123;
const API_ENDPOINT = `${API_HOST}:${API_PORT}`;

// Fetch provider data
const emailClothingOfferStatus = emailPermChoice => {
  let withEmailClothing = {};
  const emailClothingGrantedRegex = 'hello';

  if(emailPermChoice){
    console.log(emailPermChoice);
    withEmailClothing = {validPermStatus: emailPermChoice}
  }

  return request
    .get(`${API_ENDPOINT}/provider`)
    .query(withEmailClothing)
    .then(
      res => {
        if (res.body.validPermStatus.match(emailClothingGrantedRegex)) {
          return {
            clothingStatus: (res.body.validPermStatus),
          }
        } else {
          throw new Error('Could not verify email clothing offer status')
        }
      },
      err => {
        throw new Error(`Error from response: ${err.body}`)
      }
    )
};

module.exports = {
  emailClothingOfferStatus,
};

and I have the following in my package.json scripts:

"test:consumer": "./node_modules/.bin/mocha --timeout 150000 pact/consumer/test/consumer.spec.js",

When I run npm run test:consumer, I get:

1) Consumer
       when a call to the Provider is made
         can process the HTML payload from the provider:
     TypeError: Cannot read property 'clothingStatus' of undefined
      at Context.it (pact/consumer/test/consumer.spec.js:29:35)

I'm sure it's something obvious but can anyone help?


Solution

  • Two things stand out to me as a problem:

    1. The test above is a normal unit test designed to show how unit tests won't catch contract issues, and leads you into why Pact is useful (In case this wasn't clear). In short, it's not a Pact test at all - I can tell because it's using Nock, meaning the expected requests will never reach Pact. I can also tell because the Pact package doesn't appear to be imported. You want to model from this file https://github.com/DiUS/pact-workshop-js/blob/master/consumer/test/consumerPact.spec.js
    2. The response value is a Promise, which means you can't do return expect(response.body.clothingStatus).to.eventually.equal('hello') because response is a promise, so body will be undefined and clothingStatus is not a property of that. The chai eventually API is useful for this sort of test, but as I understand, it has to work directly with a Promise - you could do expect(response).to... and then chai can go to work.