From cb6305b77ba49c26eb75049df0879f8b80beef63 Mon Sep 17 00:00:00 2001 From: Matt Fellows Date: Thu, 8 Feb 2018 16:56:07 +1100 Subject: [PATCH] feat(types): allow builder usage in Pact tests - 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 --- README.md | 1 + examples/typescript/test/get-dog.spec.ts | 81 ++++++++++++++---------- package.json | 7 +- src/dsl/interaction.ts | 1 - src/pact.spec.ts | 25 ++++++++ src/pact.ts | 23 +++---- 6 files changed, 88 insertions(+), 50 deletions(-) diff --git a/README.md b/README.md index fa83cd6a8..1a21944de 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/examples/typescript/test/get-dog.spec.ts b/examples/typescript/test/get-dog.spec.ts index 29ddb9291..36f1650f2 100644 --- a/examples/typescript/test/get-dog.spec.ts +++ b/examples/typescript/test/get-dog.spec.ts @@ -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); @@ -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") @@ -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); }); }); +}); diff --git a/package.json b/package.json index 115c972d7..34b52d935 100644 --- a/package.json +++ b/package.json @@ -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": { @@ -45,8 +47,7 @@ "consumer driven testing" ], "author": "Beth Skurrie (https://github.com/bethesque)", - "contributors": [ - { + "contributors": [{ "name": "Tarcio Saraiva", "email": "tarcio@gmail.com", "url": "http://twitter.com/tarciosaraiva" diff --git a/src/dsl/interaction.ts b/src/dsl/interaction.ts index e9321c6c9..b7978e07f 100644 --- a/src/dsl/interaction.ts +++ b/src/dsl/interaction.ts @@ -118,7 +118,6 @@ export class Interaction { headers: responseOpts.headers || undefined, status: responseOpts.status, }, isNil) as ResponseOptions; - return this; } diff --git a/src/pact.spec.ts b/src/pact.spec.ts index 7457e8d65..03e009999 100644 --- a/src/pact.spec.ts +++ b/src/pact.spec.ts @@ -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 => Promise.resolve(int), + } as any as MockService; + expect(pact.addInteraction(interaction2)).to.eventually.have.property("given").notify(done); + }); + }); }); }); diff --git a/src/pact.ts b/src/pact.ts index 138a9ab54..03cbb69c9 100644 --- a/src/pact.ts +++ b/src/pact.ts @@ -94,21 +94,18 @@ export class Pact { * @returns {Promise} */ public addInteraction(interactionObj: InteractionObject | Interaction): Promise { - let interaction: Interaction; - - // tslint:disable:no-angle-bracket-type-assertion - if ((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); }