Skip to content

Commit

Permalink
feat(types): allow builder usage in Pact tests
Browse files Browse the repository at this point in the history
- pact.addInteraction() now accepts union type InteractionObject | Interaction
- Builder pattern as first-class citizen (exported as Interaction)
- Add TypeScript example demonstrating both builder and literal examples
  • Loading branch information
mefellows committed Feb 8, 2018
1 parent 1c1506d commit cb6305b
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 50 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,7 @@ Learn everything in Pact JS in 60 minutes: https://github.com/DiUS/pact-workshop
* [Complete Example (Node env)](https://github.com/pact-foundation/pact-js/tree/master/examples/e2e)
* [Pact with AVA (Node env)](https://github.com/pact-foundation/pact-js/tree/master/examples/ava)
* [Pact with Jest (Node env)](https://github.com/pact-foundation/pact-js/tree/master/examples/jest)
* [Pact with TypeScript + Mocha](https://github.com/pact-foundation/pact-js/tree/master/examples/typescript)
* [Pact with Mocha](https://github.com/pact-foundation/pact-js/tree/master/examples/mocha)
* [Pact with Karma + Jasmine](https://github.com/pact-foundation/pact-js/tree/master/karma/jasmine)
* [Pact with Karma + Mocha](https://github.com/pact-foundation/pact-js/tree/master/karma/mocha)
Expand Down
81 changes: 48 additions & 33 deletions examples/typescript/test/get-dog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ import path = require("path");
import * as sinon from "sinon";
import * as sinonChai from "sinon-chai";
import pact = require("../../../dist/pact");
import { InteractionObject, Interaction } from "../../../dist/pact";
import { Interaction, InteractionObject } from "../../../dist/pact";

const Pact = pact.Pact;
const expect = chai.expect;
const proxyquire = require("proxyquire").noCallThru();
import { HTTPMethod } from "../../../dist/common/request";
import { DogService } from "../index";

chai.use(sinonChai);
Expand All @@ -36,7 +37,9 @@ describe("The Dog API", () => {

after(() => provider.finalize());

describe("get /dogs", () => {
afterEach(() => provider.verify());

describe("get /dogs using builder pattern", () => {
before(() => {
const interaction = new Interaction()
.given("I have a list of dogs")
Expand All @@ -55,39 +58,51 @@ describe("The Dog API", () => {
},
body: EXPECTED_BODY,
});

return provider.addInteraction(interaction);
// before(() => {
// const interaction = {
// state: "i have a list of dogs",
// uponReceiving: "a request for all dogs",
// withRequest: {
// method: "GET",
// path: "/dogs",
// headers: {
// Accept: "application/json",
// },
// },
// willRespondWith: {
// status: 200,
// headers: {
// "Content-Type": "application/json",
// },
// body: EXPECTED_BODY,
// },
// } as InteractionObject;
// return provider.addInteraction(interaction);
// });
});

it("returns the correct response", (done) => {
dogService
.getMeDogs()
.then((response: any) => {
expect(response.data).to.eql(EXPECTED_BODY);
done();
}, done);
});
});

it("returns the correct response", (done) => {
dogService
.getMeDogs()
.then((response: any) => {
expect(response.data).to.eql(EXPECTED_BODY);
done();
}, done);
});
describe("get /dogs using object pattern", () => {
before(() => {
const interaction = {
state: "i have a list of dogs",
uponReceiving: "a request for all dogs",
withRequest: {
method: "GET" as HTTPMethod,
path: "/dogs",
headers: {
Accept: "application/json",
},
},
willRespondWith: {
status: 200,
headers: {
"Content-Type": "application/json",
},
body: EXPECTED_BODY,
},
};

return provider.addInteraction(interaction);
});

// verify with Pact, and reset expectations
afterEach(() => provider.verify());
it("returns the correct response", (done) => {
dogService
.getMeDogs()
.then((response: any) => {
expect(response.data).to.eql(EXPECTED_BODY);
done();
}, done);
});
});
});
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@
"prerelease": "npm i && rm package-lock.json",
"release": "standard-version",
"test": "nyc --check-coverage --reporter=html --reporter=text-summary mocha",
"test:examples": "npm run test:e2e-examples && npm run test:jest-examples && npm run test:mocha-examples && npm run test:ava-examples",
"test:examples": "npm run test:e2e-examples && npm run test:jest-examples && npm run test:mocha-examples && npm run test:ava-examples && npm run test:ts-examples",
"test:e2e-examples": "cd examples/e2e && npm i && npm t",
"test:ava-examples": "cd examples/ava && npm i && npm t",
"test:jest-examples": "cd examples/jest && npm i && npm t",
"test:mocha-examples": "cd examples/mocha && npm i && npm t",
"test:ts-examples": "cd examples/typescript && npm i && npm t",
"test:karma": "npm run test:karma:jasmine && npm run test:karma:mocha",
"test:karma:jasmine": "karma start ./karma/jasmine/karma.conf.js",
"test:karma:mocha": "karma start ./karma/mocha/karma.conf.js",
"travis": "./scripts/build.sh",
"appveyor": "./scripts/build.ps1",
"webpack": "webpack --config ./config/webpack.web.config.js"
},
"repository": {
Expand All @@ -45,8 +47,7 @@
"consumer driven testing"
],
"author": "Beth Skurrie <beth@bethesque.com> (https://github.com/bethesque)",
"contributors": [
{
"contributors": [{
"name": "Tarcio Saraiva",
"email": "tarcio@gmail.com",
"url": "http://twitter.com/tarciosaraiva"
Expand Down
1 change: 0 additions & 1 deletion src/dsl/interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ export class Interaction {
headers: responseOpts.headers || undefined,
status: responseOpts.status,
}, isNil) as ResponseOptions;

return this;
}

Expand Down
25 changes: 25 additions & 0 deletions src/pact.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,31 @@ describe("Pact", () => {
interactionWithNoState.state = undefined;
expect(pact.addInteraction(interaction)).to.eventually.not.have.property("providerState").notify(done);
});

describe("when given an Interaction as a builder", () => {
it("creates interaction", (done) => {
const interaction2 = new Interaction()
.given("i have a list of projects")
.uponReceiving("a request for projects")
.withRequest({
method: "GET",
path: "/projects",
headers: { Accept: "application/json" },
})
.willRespondWith({
status: 200,
headers: { "Content-Type": "application/json" },
body: {},
});

const pact = Object.create(Pact.prototype) as any as PactType;
pact.opts = fullOpts;
pact.mockService = {
addInteraction: (int: Interaction): Promise<Interaction> => Promise.resolve(int),
} as any as MockService;
expect(pact.addInteraction(interaction2)).to.eventually.have.property("given").notify(done);
});
});
});
});

Expand Down
23 changes: 10 additions & 13 deletions src/pact.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,18 @@ export class Pact {
* @returns {Promise}
*/
public addInteraction(interactionObj: InteractionObject | Interaction): Promise<string> {
let interaction: Interaction;

// tslint:disable:no-angle-bracket-type-assertion
if (<InteractionObject>(<any>interactionObj).state) {
interaction = new Interaction();
if (interactionObj.state) {
interaction.given(interactionObj.state);
}

interaction
.uponReceiving(interactionObj.uponReceiving)
.withRequest(interactionObj.withRequest)
.willRespondWith(interactionObj.willRespondWith);
if (interactionObj instanceof Interaction) {
return this.mockService.addInteraction(interactionObj);
}
const interaction = new Interaction();
if (interactionObj.state) {
interaction.given(interactionObj.state);
}

interaction
.uponReceiving(interactionObj.uponReceiving)
.withRequest(interactionObj.withRequest)
.willRespondWith(interactionObj.willRespondWith);

return this.mockService.addInteraction(interaction);
}
Expand Down

0 comments on commit cb6305b

Please sign in to comment.