pact-foundation/pact-js

View on GitHub
src/pact.integration.spec.ts

Summary

Maintainability
A
0 mins
Test Coverage
/* tslint:disable:no-unused-expression no-empty */
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import sinonChai from 'sinon-chai';
import axios from 'axios';
import net = require('net');

process.env.ENABLE_FEATURE_V4 = 'true';

// eslint-disable-next-line import/first
import { PactV4 } from './v4';

const { expect } = chai;

chai.use(sinonChai);
chai.use(chaiAsPromised);

describe('V4 Pact', () => {
  let pact: PactV4;

  beforeEach(() => {
    pact = new PactV4({
      consumer: 'v4consumer',
      provider: 'v4provider',
    });
  });

  describe('HTTP req/res contract', () => {
    it('generates a pact', () =>
      pact
        .addInteraction()
        .given('some state')
        .given('a second state')
        .uponReceiving('a standard HTTP req/res')
        .withRequest('POST', '/', (builder) => {
          builder
            .jsonBody({
              foo: 'bar',
            })
            .headers({
              'x-foo': 'x-bar',
            });
        })
        .willRespondWith(200, (builder) => {
          builder
            .jsonBody({
              foo: 'bar',
            })
            .headers({
              'x-foo': 'x-bar',
            });
        })
        .executeTest(async (server) =>
          axios.post(
            server.url,
            {
              foo: 'bar',
            },
            {
              headers: {
                'x-foo': 'x-bar',
              },
            }
          )
        ));
  });

  describe('Plugin test', () => {
    describe('Using the MATT plugin', () => {
      const parseMattMessage = (raw: string): string =>
        raw.replace(/(MATT)+/g, '').trim();

      const generateMattMessage = (raw: string): string => `MATT${raw}MATT`;

      describe('HTTP interface', () => {
        it('generates a pact', async () => {
          const mattRequest = `{"request": {"body": "hello"}}`;
          const mattResponse = `{"response":{"body":"world"}}`;

          await pact
            .addInteraction()
            .given('the Matt protocol exists')
            .uponReceiving('an HTTP request to /matt')
            .usingPlugin({
              plugin: 'matt',
              version: '0.1.1',
            })
            .withRequest('POST', '/matt', (builder) => {
              builder.pluginContents('application/matt', mattRequest);
            })
            .willRespondWith(200, (builder) => {
              builder.pluginContents('application/matt', mattResponse);
            })
            .executeTest((mockserver) =>
              axios
                .request({
                  baseURL: mockserver.url,
                  headers: {
                    'content-type': 'application/matt',
                    Accept: 'application/matt',
                  },
                  data: generateMattMessage('hello'),
                  method: 'POST',
                  url: '/matt',
                })
                .then((res) => {
                  expect(parseMattMessage(res.data)).to.eq('world');
                })
            );
        });
      });

      describe('Synchronous Message (TCP) ', () => {
        describe('with MATT protocol', () => {
          const HOST = '127.0.0.1';

          const sendMattMessageTCP = (
            message: string,
            host: string,
            port: number
          ): Promise<string> => {
            const socket = net.connect({
              port,
              host,
            });

            const res = socket.write(`${generateMattMessage(message)}\n`);

            if (!res) {
              throw Error('unable to connect to host');
            }

            return new Promise((resolve) => {
              socket.on('data', (data) => {
                resolve(parseMattMessage(data.toString()));
              });
            });
          };

          it('generates a pact', () => {
            const mattMessage = `{"request": {"body": "hellotcp"}, "response":{"body":"tcpworld"}}`;

            return pact
              .addSynchronousInteraction('a MATT message')
              .usingPlugin({
                plugin: 'matt',
                version: '0.1.1',
              })
              .withPluginContents(mattMessage, 'application/matt')
              .startTransport('matt', HOST)
              .executeTest(async (tc) => {
                const message = await sendMattMessageTCP(
                  'hellotcp',
                  HOST,
                  tc.port
                );
                expect(message).to.eq('tcpworld');
              });
          });
        });
      });
    });
  });
});