Skip to content

Commit

Permalink
feat(v3): Add draft withPact interface for V3
Browse files Browse the repository at this point in the history
  • Loading branch information
TimothyJones committed Oct 6, 2020
1 parent f437ec3 commit 8ba6e66
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 2 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"devDependencies": {
"@commitlint/cli": "^10.0.0",
"@commitlint/config-conventional": "^10.0.0",
"@pact-foundation/pact": "9.8.0",
"@pact-foundation/pact": "v10.0.0-beta.16",
"@types/supertest": "2.0.8",
"coveralls": "3.0.9",
"cross-env": "7.0.2",
Expand All @@ -57,7 +57,7 @@
"typescript": "3.8.3"
},
"peerDependencies": {
"@pact-foundation/pact": "^8.2.4 || ^9.0.1",
"@pact-foundation/pact": "^v10.0.0-beta.16",
"jest": "^24.0.0 || ^25.0.0 || ^26.0.0"
},
"dependencies": {
Expand Down
126 changes: 126 additions & 0 deletions src/v3/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import * as pactV3 from '@pact-foundation/pact/v3';
import * as path from 'path';

export type JestPactOptionsV3 = Omit<pactV3.PactV3Options, 'dir'> & {
dir?: string;
timeout?: number;
};

type ExecuteTestFn = (mockServer: pactV3.V3MockServer) => Promise<unknown>;

interface DescibeArg {
provider: pactV3.PactV3;
execute: JestPactExecuteTestFn;
}

type JestPactExecuteTestFn = (description: string, fn: ExecuteTestFn) => void;

export type JestProvidedPactFnV3 = (D: DescibeArg) => void;
export type JestDescribePactFnV3 = (
description: string,
fn: JestProvidedPactFnV3,
) => void;

export type JestProvidedDescribeFnV3 = (
pactDescribe: JestDescribePactFnV3,
) => void;

const applyDefaults = (options: JestPactOptionsV3): pactV3.PactV3Options => ({
dir: path.resolve(process.cwd(), 'pact/pacts'),
...options,
});

const setupProvider = (options: pactV3.PactV3Options) => {
const pactDescribe: JestDescribePactFnV3 = (
describeDescription: string,
fn: JestProvidedPactFnV3,
) => {
describe(describeDescription, () => {
const provider = new pactV3.PactV3(options);
const execute = (testDescription: string, executeTest: ExecuteTestFn) => {
it(testDescription, () => provider.executeTest(executeTest));
};
fn({ provider, execute });
});
};
return pactDescribe;
};

const jestPactWrapper = (
options: JestPactOptionsV3,
tests: JestProvidedDescribeFnV3,
): void => {
const pactTestTimeout = options.timeout || 30000;

describe(`with ${pactTestTimeout} ms timeout for Pact`, () => {
let originalTimeout: number;

beforeAll(() => {
// Jest's default timeout is 5000, and jest doesn't provide a way of
// asking what the current timeout is. In Jest 24 and 25, Jasmine was probably
// the test runner, so we can ask Jasmine if it is there. In later versions of
// Jest (eg 26 and up), Jasmine may not be defined.
// See https://github.com/pact-foundation/jest-pact/issues/197 for discussion
//
// For now, we just assume that 5000 was the original timeout.
// The impact is likely to be small, as `jest.setTimeout()` only works for the
// current test file
originalTimeout = global.jasmine
? global.jasmine.DEFAULT_TIMEOUT_INTERVAL
: 5000;
jest.setTimeout(pactTestTimeout);
});

afterAll(() => {
jest.setTimeout(originalTimeout);
});

tests(setupProvider(applyDefaults(options)));
});
};

const describeString = (options: JestPactOptionsV3) =>
`Pact between ${options.consumer} and ${options.provider}`;

export const pactWith = (
options: JestPactOptionsV3,
tests: JestProvidedDescribeFnV3,
) => describe(describeString(options), () => jestPactWrapper(options, tests));

export const xpactWith = (
options: JestPactOptionsV3,
tests: JestProvidedDescribeFnV3,
) => xdescribe(describeString(options), () => jestPactWrapper(options, tests));

export const fpactWith = (
options: JestPactOptionsV3,
tests: JestProvidedDescribeFnV3,
) => fdescribe(describeString(options), () => jestPactWrapper(options, tests));

/*
example:
const options = { dir: '', consumer: '', provider: '' };
const api = (url: string) => ({ getWhatever: () => Promise.resolve(url) });
pactWith(options, (pactDescribe) => {
pactDescribe('some interaction', (provider) => {
beforeEach(() =>
provider
.given('Some state')
.uponReceiving('Some request')
.withRequest({ path: '/whatever/path', method: 'GET' }),
);
it('works', () =>
provider
.executeTest((mockserver) => api(mockserver.url).getWhatever())
.then((response) => {
expect(response).toEqual({ whatever: 'it-should-be' });
}));
});
});
*/
57 changes: 57 additions & 0 deletions src/v3/pactwith.v3.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { V3MockServer } from '@pact-foundation/pact/v3/pact';
import * as supertest from 'supertest';
import { pactWith } from './index';

const getClient = (mock: V3MockServer) => supertest(mock.url);

pactWith({ consumer: 'MyConsumer', provider: 'pactWith v3' }, (interaction) => {
interaction('pact integration', ({ provider, execute }) => {
beforeEach(() =>
provider
.given('A pet 1845563262948980200 exists')
.uponReceiving('A get request to get a pet 1845563262948980200')
.withRequest({
method: 'GET',
path: '/v2/pet/1845563262948980200',
headers: { api_key: '[]' },
})
.willRespondWith({
status: 200,
}),
);

execute(
'should be be able to hide the pact stuff behind the scenes with a port of the users choosing',
(mock) =>
getClient(mock)
.get('/v2/pet/1845563262948980200')
.set('api_key', '[]')
.expect(200),
);
});

interaction('another pact integration', ({ provider, execute }) => {
beforeEach(() =>
provider
.given('No pets exist')
.uponReceiving('A get request to get a pet 1845563262948980200')
.withRequest({
method: 'GET',
path: '/v2/pet/1845563262948980200',
headers: { api_key: '[]' },
})
.willRespondWith({
status: 404,
}),
);

execute(
'should be be able to hide the pact stuff behind the scenes with a port of the users choosing',
(mock) =>
getClient(mock)
.get('/v2/pet/1845563262948980200')
.set('api_key', '[]')
.expect(404),
);
});
});

0 comments on commit 8ba6e66

Please sign in to comment.