pact-foundation/pact-js

View on GitHub
src/dsl/verifier/verifier.spec.ts

Summary

Maintainability
A
0 mins
Test Coverage
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import sinon from 'sinon';
import { Server } from 'http';
import serviceFactory, { LogLevel } from '@pact-foundation/pact-core';

import * as proxy from './proxy/proxy';
import logger from '../../common/logger';

import { VerifierOptions } from './types';

import { Verifier } from './verifier';

chai.use(chaiAsPromised);

const { expect } = chai;

describe('Verifier', () => {
  afterEach(() => {
    sinon.restore();
  });

  const state = 'thing exists';
  let v: Verifier;
  let opts: VerifierOptions;
  let executed: boolean;
  const providerBaseUrl = 'http://not.exists';

  beforeEach(() => {
    executed = false;
    opts = {
      providerBaseUrl,
      requestFilter: (req, res, next) => {
        next();
      },
      stateHandlers: {
        [state]: () => {
          executed = true;
          return Promise.resolve();
        },
      },
    };
  });

  describe('#constructor', () => {
    describe('when given configuration', () => {
      it('sets the configuration on the object', () => {
        v = new Verifier(opts);

        expect(v).to.have.deep.property('config').includes({
          providerBaseUrl,
        });
        expect(v).to.have.nested.property('config.stateHandlers');
        expect(v).to.have.nested.property('config.requestFilter');
      });
    });
  });

  describe('options handling', () => {
    let spy: sinon.SinonSpy;

    beforeEach(() => {
      spy = sinon.spy(serviceFactory, 'logLevel');
    });

    context('when logLevel is provided', () => {
      it('sets the log level on pact node', () => {
        v = new Verifier({
          ...opts,
          logLevel: 'debug',
        });
        expect(spy.callCount).to.eql(1);
      });
    });

    context('when logLevel is not provided', () => {
      it('does not modify the log setting', () => {
        const { ...rest } = opts;
        v = new Verifier({
          ...rest,
        });
        expect(spy.callCount).to.eql(0);
      });
    });
    context('when a deprecated field is provided', () => {
      it('logs a warning', () => {
        spy = sinon.spy(logger, 'warn');
        v = new Verifier({
          ...opts,
          providerStatesSetupUrl: 'http://foo.com',
        });

        expect(spy.callCount).to.eql(1);
      });
    });
  });

  describe('#verifyProvider', () => {
    beforeEach(() => {
      sinon.stub(proxy, 'createProxy').returns({
        close: (): Server => {
          executed = true;
          return {} as Server;
        },
        address: () => ({
          port: 1234,
          family: 'https',
          address: 'mock.server.example.com',
        }),
      } as Server);
      sinon.stub(proxy, 'waitForServerReady' as any).returns(Promise.resolve());
    });

    describe('when no configuration has been given', () => {
      it('fails with an error', () =>
        expect(
          () => new Verifier(undefined as unknown as VerifierOptions)
        ).to.throw());
    });

    describe('when the verifier has been configured', () => {
      beforeEach(() => {
        v = new Verifier({ ...opts, logLevel: 'trace' as LogLevel });
      });
      context('and the verification runs successfully', () => {
        it('closes the server and returns the result', () => {
          sinon
            .stub(v, 'runProviderVerification' as any)
            .returns(Promise.resolve('done'));

          const res = v.verifyProvider();

          return expect(res).to.eventually.be.fulfilled.then(() => {
            expect(executed).to.be.true;
          });
        });
      });

      context('and the verification fails', () => {
        it('closes the server and returns the result', () => {
          sinon
            .stub(v, 'runProviderVerification' as any)
            .returns(() => Promise.reject(new Error('error')));

          const res = v.verifyProvider();

          return expect(res).to.eventually.be.rejected.then(() => {
            expect(executed).to.be.true;
          });
        });
      });
    });
  });
});