From 402c99427b0bf25eb0f6692a3a8532c6fa933e92 Mon Sep 17 00:00:00 2001 From: Francislainy Campos Date: Fri, 16 Oct 2020 08:40:08 +0100 Subject: [PATCH] Initial draft for adding pact tests. Failing with error before undefined --- package.json | 18 ++++++++++-- src/api/api.js | 15 ++++++++++ src/model/Category.js | 9 ++++++ src/model/Product.js | 10 +++++++ src/pact/consumer.pact.spec.js | 50 ++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 3 deletions(-) create mode 100644 src/api/api.js create mode 100644 src/model/Category.js create mode 100644 src/model/Product.js create mode 100644 src/pact/consumer.pact.spec.js diff --git a/package.json b/package.json index a491363..6b144a5 100644 --- a/package.json +++ b/package.json @@ -18,13 +18,22 @@ "react-dom": "^16.13.1", "react-dragger": "^1.3.0", "react-scripts": "3.4.3", - "startbootstrap-simple-sidebar": "^5.1.2" + "startbootstrap-simple-sidebar": "^5.1.2", + "cors": "^2.8.5", + "express": "^4.17.1" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", - "eject": "react-scripts eject" + "eject": "react-scripts eject", + "test:consumer": "mocha --exit --timeout 30000 consumer.pact.spec.js", + "test:provider": "mocha --exit --timeout 30000 provider.pact.spec.js", + "publish": "npx pact-broker publish ./pacts --consumer-app-version 1.0.0-someconsumersha --tag master", + "can-deploy:consumer": "npx pact-broker can-i-deploy --pacticipant katacoda-consumer --version 1.0.0-someconsumersha --to prod", + "can-deploy:provider": "npx pact-broker can-i-deploy --pacticipant katacoda-provider --version 1.0.0-someprovidersha --to prod", + "deploy:consumer": "npx pact-broker create-version-tag --pacticipant katacoda-consumer --version 1.0.0-someconsumersha --tag prod", + "deploy:provider": "npx pact-broker create-version-tag --pacticipant katacoda-provider --version 1.0.0-someprovidersha --tag prod" }, "eslintConfig": { "extends": "react-app" @@ -42,6 +51,9 @@ ] }, "devDependencies": { - "react-router-dom": "^5.2.0" + "react-router-dom": "^5.2.0", + "@pact-foundation/pact": "^9.9.12", + "chai": "^4.2.0", + "mocha": "^8.1.3" } } diff --git a/src/api/api.js b/src/api/api.js new file mode 100644 index 0000000..f37ea9e --- /dev/null +++ b/src/api/api.js @@ -0,0 +1,15 @@ +const axios = require('axios'); +const { Product } = require('../model/Product'); + +class ProductApiClient { + constructor(url) { + this.url = url + } + + async getProduct(id) { + return axios.get(`${this.url}/products/${id}`).then(r => new Product(r.data.id, r.data.name, r.data.type)); + } +} +module.exports = { + ProductApiClient +} diff --git a/src/model/Category.js b/src/model/Category.js new file mode 100644 index 0000000..7295df0 --- /dev/null +++ b/src/model/Category.js @@ -0,0 +1,9 @@ +class Category { + constructor(id, name) { + this.id = id + this.name = name + } +} +module.exports = { + Category +} \ No newline at end of file diff --git a/src/model/Product.js b/src/model/Product.js new file mode 100644 index 0000000..d6b171e --- /dev/null +++ b/src/model/Product.js @@ -0,0 +1,10 @@ +class Product { + constructor(id, name, type) { + this.id = id + this.name = name + this.type = type + } +} +module.exports = { + Product +} \ No newline at end of file diff --git a/src/pact/consumer.pact.spec.js b/src/pact/consumer.pact.spec.js new file mode 100644 index 0000000..5076d9d --- /dev/null +++ b/src/pact/consumer.pact.spec.js @@ -0,0 +1,50 @@ +// (1) Import the pact library and matching methods +const { Pact } = require ('@pact-foundation/pact'); +const { ProductApiClient } = require ('../api/api'); +const { Product } = require ('../model/Product'); +const { like, regex } = require ('@pact-foundation/pact/dsl/matchers'); +const chai = require("chai") +const expect = chai.expect + +// (2) Configure our Pact library +const mockProvider = new Pact({ + consumer: 'katacoda-consumer', + provider: 'katacoda-provider', + cors: true // needed for katacoda environment +}); + + +describe('Products API test', () => { + // (3) Setup Pact lifecycle hooks + before(() => mockProvider.setup()); + afterEach(() => mockProvider.verify()); + after(() => mockProvider.finalize()); + + it('get product by ID', async () => { + // (4) Arrange + const expectedProduct = { id: 10, type: 'pizza', name: 'Margharita' } + + await mockProvider.addInteraction({ + state: 'a product with ID 10 exists', + uponReceiving: 'a request to get a product', + withRequest: { + method: 'GET', + path: '/products/10' + }, + willRespondWith: { + status: 200, + headers: { + 'Content-Type': regex({generate: 'application/json; charset=utf-8', matcher: '^application\/json'}), + }, + body: like(expectedProduct), + }, + }); + + // (5) Act + const api = new ProductApiClient(mockProvider.mockService.baseUrl); + const product = await api.getProduct(10); + + // (6) Assert that we got the expected response + expect(product).to.deep.equal(new Product(10, 'Margharita', 'pizza')); + }); +});