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
Usage
pactWith({ consumer: 'MyConsumer', provider: 'MyProvider' }, provider => {
}
Configuration
pactWith({PactOptions}, provider => {
}
export interface PactOptions {
provider: string;
consumer: string;
port?: number;
pactfileWriteMode?: PactFileWriteMode;
dir? string
}
export declare type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal";
export declare type PactFileWriteMode = "overwrite" | "update" | "merge";
Output
- Log files are written to /pact/logs
- Pact files are written to /pact/pacts
Example
A contrived example using supertest as a client
import {InteractionObject} from "@pact-foundation/pact"
import * as jestpact from "jest-pact";
import * as supertest from "supertest";
jestpact.pactWith(
{ consumer: "test-consumer", provider: "json-provider" },
async (provider: any) => {
const client = () => {
const url = `${provider.mockService.baseUrl}`;
return supertest(url);
};
test("should accept a valid get request to get a pet", async () => {
const postValidRequest: InteractionObject = {
state: "A pet 1845563262948980200 exists",
uponReceiving: "A get request to get a pet",
willRespondWith: {
status: 200
},
withRequest: {
method: "GET",
path: "/v2/pet/1845563262948980200",
headers: { api_key: "[]" }
}
};
await provider.addInteraction(postValidRequest);
await client()
.get("/v2/pet/1845563262948980200")
.set("api_key", "[]")
.expect(200);
await provider.verify();
});
}
);
To use Pact to it's full effect, you should replace the client above with your API call in your code and instantiate with pact mock service base url provider.mockService.baseUrl
So if your calling method is
export const api = (baseURl) => ({
getUser: () => axios(opts).then(processResponse)
})
Then your test may look like
import {InteractionObject} from "@pact-foundation/pact"
import * as jestpact from "jest-pact";
import {api} from "yourCode";
jestpact.pactWith(
{ consumer: "test-consumer", provider: "json-provider" },
async (provider: any) => {
const client = () => {
const url = `${provider.mockService.baseUrl}`;
return api(url);
};
test("should accept a valid get request to get a pet", async () => {
const postValidRequest: InteractionObject = {
state: "A pet 1845563262948980200 exists",
uponReceiving: "A get request to get a pet",
willRespondWith: {
status: 200
},
withRequest: {
method: "GET",
path: "/v2/pet/1845563262948980200",
headers: { api_key: "[]" }
}
};
await provider.addInteraction(postValidRequest);
await client()
.get("/v2/pet/1845563262948980200")
.set("api_key", "[]")
.expect(200);
await provider.verify();
});
}
);
You can make your test shorter, by moving your interaction object into another file
import * as jestpact from "jest-pact";
import * as supertest from "supertest";
import * as interaction from "./expectation/json.expectation";
import * as json from "./requestResponse/json.reqRes";
jestpact.pactWith(
{ consumer: "test-consumer", provider: "json-provider" },
async (provider: any) => {
const client = () => {
const url = `${provider.mockService.baseUrl}`;
return supertest(url);
};
test("should accept a valid get request to get a pet", async () => {
await provider.addInteraction(interaction.postValidRequest);
await client()
.get("/v2/pet/1845563262948980200")
.set("api_key", "[]")
.expect(200, json.getPetValidResponse);
await provider.verify();
});
}
);
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 round this by using the following watchPathIgnorePatterns: ["pact/logs/*","pact/pacts/*"]
in your jest.config.js
Example
module.exports = {
globals: {
"ts-jest": {
tsConfig: "tsconfig.json"
}
},
moduleFileExtensions: ["ts", "js", "json"],
transform: {
"^.+\\.(ts|tsx)$": "ts-jest"
},
testMatch: ["**/*.test.(ts|js)", "**/*.it.(ts|js)", "**/*.pacttest.(ts|js)"],
testEnvironment: "node",
reporters: ["default", "jest-junit"],
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