Jest-Pact
Jest Adaptor to help write Pact files with ease
Features
Jest-Pact
Roadmap
Adapter Installation
npm i jest-pact --save-dev
OR
yarn add jest-pact --dev
If you have more than one file with pact tests for the same consumer/provider
pair, you will also need to add --runInBand
to your jest
or react-scripts test
command in your package.json. This avoids race conditions with the mock
server writing to the pact file.
Usage
Say that your API layer looks something like this:
import axios from 'axios';
const defaultBaseUrl = "http://your-api.example.com"
export const api = (baseUrl = defaultBaseUrl) => ({
getHealth: () => axios.get(`${baseUrl}/health`)
.then(response => response.data.status)
})
Then your test might look like:
import { pactWith } from 'jest-pact';
import { Matchers } from '@pact-foundation/pact';
import api from 'yourCode';
pactWith({ consumer: 'MyConsumer', provider: 'MyProvider' }, provider => {
let client;
beforeEach(() => {
client = api(provider.mockService.baseUrl)
});
describe('health endpoint', () => {
beforeEach(() =>
provider.addInteraction({
state: "Server is healthy",
uponReceiving: 'A request for API health',
willRespondWith: {
status: 200,
body: {
status: Matchers.like('up'),
},
},
withRequest: {
method: 'GET',
path: '/health',
},
})
);
it('returns server health', () =>
client.health().then(health => {
expect(health).toEqual('up');
}));
});
Best practices
You can make your tests easier to read by extracting your request and responses:
import { Matchers } from '@pact-foundation/pact';
export const healthRequest = {
uponReceiving: 'A request for API health',
withRequest: {
method: 'GET',
path: '/health',
},
};
export const healthyResponse = {
status: 200,
body: {
status: Matchers.like('up'),
},
}
import { pactWith } from 'jest-pact';
import { healthRequest, healthyResponse } from "./pact.fixtures";
import api from 'yourCode';
pactWith({ consumer: 'MyConsumer', provider: 'MyProvider' }, provider => {
let client;
beforeEach(() => {
client = api(provider.mockService.baseUrl)
});
describe('health endpoint', () => {
beforeEach(() =>
provider.addInteraction({
state: "Server is healthy",
...healthRequest,
willRespondWith: healthyResponse
})
);
it('returns server health', () =>
client.health().then(health => {
expect(health).toEqual('up');
}));
});
API Documentation
Jest-Pact has three functions:
pactWith(JestPactOptions, (providerMock) => { /* tests go here */ })
: a wrapper that sets up a pact mock providerxpactWith(JestPactOptions, (providerMock) => { /* tests go here */ })
: Like xdescribe
in Jest, this skips the pact tests described within.fpactWith(JestPactOptions, (providerMock) => { /* tests go here */ })
: Like fdescribe
in Jest, this sets this test suite to only run this test.
Configuration
You can use all the usual PactOptions
from pact-js, plus a timeout for
telling jest to wait a bit longer for pact to start and run.
pactWith(JestPactOptions, provider => {
}
interface JestPactOptions = PactOptions & {
timeout?: number;
}
Defaults
Jest-Pact sets some helpful defaults for you. You can override any of these by explicitly setting corresponding option.
log
is set so that log files are written to /pact/logs, and named <consumer>-<provider>-mockserver-interaction.log
dir
is set so that pact files are written to /pact/pactslogLevel
is set to warntimeout
is 30,000 milliseconds (30 seconds)pactfileWriteMode
is set to "update"
Most of the time you won't need to change these.
Jest Watch Mode
By default Jest will watch all your files for changes, which means it will run in an infinite loop as your pact tests will generate json pact files and log files.
You can get around this by using the following watchPathIgnorePatterns: ["pact/logs/*","pact/pacts/*"]
in your jest.config.js
Example
module.exports = {
testMatch: ["**/*.test.(ts|js)", "**/*.it.(ts|js)", "**/*.pacttest.(ts|js)"],
watchPathIgnorePatterns: ["pact/logs/*", "pact/pacts/*"]
};
You can now run your tests with jest --watch
and when you change a pact file, or your source code, your pact tests will run
Examples of usage of jest-pact
See Jest-Pact-Typescript which showcases a full consumer workflow written in Typescript with Jest, using this adaptor
Examples Installation
- clone repository
git@github.com:YOU54F/jest-pact-typescript.git
- Run
yarn install
- Run
yarn run pact-test
Generated pacts will be output in pact/pacts
Log files will be output in pact/logs
Credits