added pact-node-provider example

This commit is contained in:
Tom Hombergs
2018-10-28 04:17:28 +01:00
parent 5fb2d69ca7
commit 65c49a3ea7
9 changed files with 2441 additions and 29 deletions

View File

@@ -1,21 +1,36 @@
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var logger = require('morgan');
var heroesRouter = require('./routes/heroes');
var app = express();
const createError = require('http-errors');
const express = require('express');
const path = require('path');
const logger = require('morgan');
const heroesRouter = require('./routes/heroes');
const providerStateRouter = require('./routes/provider_state');
const app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.urlencoded({extended: false}));
app.use('/heroes', heroesRouter);
registerPactEndpoint();
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
app.use(function (req, res, next) {
next(createError(404));
});
module.exports = app;
/**
* Registers a special endpoint for pact provider tests that allows to
* set the server into a certain "provider state".
*
* This endpoint is only registered if the environment variable "PACT_MODE"
* is set to "true".
*/
function registerPactEndpoint() {
const pactMode = (process.env.PACT_MODE === 'true');
if (pactMode) {
app.use('/provider-state', providerStateRouter);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,9 @@
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www.js"
"start": "node ./bin/www.js",
"pact:providerTests": "node ./pact/provider_tests.js",
"test:pact": "start-server-and-test start http://localhost:3000/heroes/42 pact:providerTests"
},
"dependencies": {
"cookie-parser": "~1.4.3",
@@ -12,5 +14,9 @@
"http-errors": "~1.6.2",
"jade": "~1.11.0",
"morgan": "~1.9.0"
},
"devDependencies": {
"@pact-foundation/pact": "7.0.1",
"start-server-and-test": "^1.7.5"
}
}

View File

@@ -0,0 +1,17 @@
const { Verifier } = require('@pact-foundation/pact');
const packageJson = require('../package.json');
let opts = {
providerBaseUrl: 'http://localhost:3000',
provider: 'hero-provider',
pactBrokerUrl: 'https://adesso.pact.dius.com.au',
pactBrokerUsername: process.env.PACT_USERNAME,
pactBrokerPassword: process.env.PACT_PASSWORD,
publishVerificationResult: true,
providerVersion: packageJson.version,
providerStatesSetupUrl: 'http://localhost:3000/provider-state'
};
new Verifier().verifyProvider(opts).then(function () {
console.log("Pacts successfully verified!");
});

View File

@@ -1,27 +1,27 @@
var express = require('express');
var router = express.Router();
const express = require('express');
const router = express.Router();
router.route('/:hero_id')
.get(function (req, res) {
var heroId = parseInt(req.params['hero_id']);
const heroId = parseInt(req.params['hero_id']);
res.status(200);
res.json({
id: heroId,
superpower: 'flying',
name: 'Superman',
universe: 'DC'
});
res.status(200);
});
router.route('/')
.post(function (req, res) {
res.status(201);
res.json({
id: 42,
superpower: 'flying',
name: 'Superman',
universe: 'DC'
});
res.status(201);
});
module.exports = router;

View File

@@ -0,0 +1,13 @@
var express = require('express');
var router = express.Router();
router.route('/')
.post(function (req, res) {
const consumer = req.query['consumer'];
const providerState = req.query['state'];
// imagine we're setting the server into a certain state
res.send(`changed to provider state "${providerState}" for consumer "${consumer}"`);
res.status(200);
});
module.exports = router;

View File

@@ -10,7 +10,7 @@ global.provider = new Pact({
dir: path.resolve(process.cwd(), 'pacts'),
spec: 2,
pactfileWriteMode: 'update',
consumer: 'react-consumer',
provider: 'node-provider',
consumer: 'hero-consumer',
provider: 'hero-provider',
host: '127.0.0.1'
});

View File

@@ -1,6 +1,7 @@
import Hero from "./hero";
const axios = require('axios');
import adapter from 'axios/lib/adapters/http';
class HeroService {
@@ -18,9 +19,9 @@ class HeroService {
url: `/heroes/${heroId}`,
baseURL: `${this.baseUrl}:${this.port}`,
headers: {
'Accept': 'application/json'
'Accept': 'application/json; charset=utf-8'
}
}).then((response) => {
}, adapter).then((response) => {
const hero = response.data;
return new Promise((resolve, reject) => {
try {
@@ -40,11 +41,11 @@ class HeroService {
url: `/heroes`,
baseURL: `${this.baseUrl}:${this.port}`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
'Accept': 'application/json; charset=utf-8',
'Content-Type': 'application/json; charset=utf-8'
},
data: hero
}).then((response) => {
}, adapter).then((response) => {
const hero = response.data;
return new Promise((resolve, reject) => {
try {

View File

@@ -6,6 +6,13 @@ describe('HeroService API', () => {
const heroService = new HeroService('http://localhost', global.port);
// a matcher for the content type "application/json" in UTF8 charset
// that ignores the spaces between the ";2 and "charset"
const contentTypeJsonMatcher = Pact.Matchers.term({
matcher: "application\\/json; *charset=utf-8",
generate: "application/json; charset=utf-8"
});
describe('getHero()', () => {
beforeEach((done) => {
@@ -16,13 +23,13 @@ describe('HeroService API', () => {
method: 'GET',
path: '/heroes/42',
headers: {
'Accept': 'application/json'
'Accept': contentTypeJsonMatcher
}
},
willRespondWith: {
status: 200,
headers: {
'Content-Type': 'application/json'
'Content-Type': contentTypeJsonMatcher
},
body: Pact.Matchers.somethingLike(new Hero('Superman', 'flying', 'DC', 42))
}
@@ -54,15 +61,18 @@ describe('HeroService API', () => {
method: 'POST',
path: '/heroes',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
'Accept': contentTypeJsonMatcher,
'Content-Type': contentTypeJsonMatcher
},
body: new Hero('Superman', 'flying', 'DC')
},
willRespondWith: {
status: 201,
headers: {
'Content-Type': 'application/json'
'Content-Type': Pact.Matchers.term({
matcher: "application\\/json; *charset=utf-8",
generate: "application/json; charset=utf-8"
})
},
body: Pact.Matchers.somethingLike(
new Hero('Superman', 'flying', 'DC', 42))