Comparing version 1.0.9 to 1.0.10
{ | ||
"name": "pactum", | ||
"version": "1.0.9", | ||
"version": "1.0.10", | ||
"description": "REST API endpoint testing tool with a mock server & compatible with pact.io for contract testing", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
@@ -346,3 +346,3 @@ # pactum | ||
Lets assume you have an order-service which is a RESTFull API service running on port 3000. Consider if order-service depends on a currency-service to fetch the prices. If you make a call to fetch the order details, order-service internally calls the currency-service to fetch price details. | ||
Lets assume you have an order-service which is a RESTFull API service running on port 3000. Consider if order-service depends on a currency-service to fetch the prices. | ||
@@ -640,3 +640,3 @@ Start the order-service & overwrite the endpoint of currency-service to http://localhost:9393 | ||
// The below code will run the pactum server on port 3000 | ||
// with mock interaction & a pac interaction | ||
// with a mock interaction & a pact interaction | ||
const pactum = require('pactum'); | ||
@@ -643,0 +643,0 @@ pactum.mock.setDefaultPort(3000); |
@@ -8,2 +8,7 @@ const Interaction = require('../models/interaction'); | ||
/** | ||
* request method | ||
* @typedef {('GET'|'POST'|'PUT'|'DELETE'|'PATCH'|'HEAD')} RequestMethod | ||
*/ | ||
/** | ||
* interaction details | ||
@@ -16,3 +21,3 @@ * @typedef {object} Interaction | ||
* @property {object} withRequest - interaction request details | ||
* @property {string} withRequest.method - request method | ||
* @property {RequestMethod} withRequest.method - request method | ||
* @property {string} withRequest.path - request path | ||
@@ -22,2 +27,3 @@ * @property {object} [withRequest.headers] - request headers | ||
* @property {object} [withRequest.body] - request body | ||
* @property {boolean} [withRequest.ignoreQuery] - ignores request query while matching | ||
* @property {boolean} [withRequest.ignoreBody] - ignores request body while matching | ||
@@ -24,0 +30,0 @@ * @property {object} willRespondWith - interaction response details |
@@ -0,1 +1,5 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const rp = require('request-promise'); | ||
const config = require('../config'); | ||
@@ -5,2 +9,12 @@ const store = require('../helpers/store'); | ||
/** | ||
* @typedef {object} PublishOptions | ||
* @property {string[]} pactFilesOrDirs - array of pact files or directories | ||
* @property {string} pactBroker - pact broker url | ||
* @property {string} consumerVersion - version of the consumer | ||
* @property {string} pactBrokerUsername - pact broker user name | ||
* @property {string} pactBrokerPassword - pact broker password | ||
* @property {string[]} tags - tags | ||
*/ | ||
class Pact { | ||
@@ -38,5 +52,84 @@ | ||
// publish pacts | ||
/** | ||
* publish pact files to pact broker | ||
* @param {PublishOptions} options - publish options | ||
*/ | ||
publish(options) { | ||
const pactFilesOrDirs = options.pactFilesOrDirs; | ||
const filePaths = new Set(); | ||
for (let i = 0; i < pactFilesOrDirs.length; i++) { | ||
const pactFileOrDir = pactFilesOrDirs[i]; | ||
const stats = fs.lstatSync(pactFileOrDir); | ||
if (stats.isDirectory()) { | ||
const items = fs.readdirSync(pactFileOrDir); | ||
for (let j = 0; j < items.length; j++) { | ||
const item = items[j]; | ||
const itemPath = path.join(pactFileOrDir, item); | ||
const childPathStats = fs.lstatSync(itemPath); | ||
if (childPathStats.isDirectory()) { | ||
const childItems = fs.readdirSync(itemPath); | ||
for (let k = 0; k < childItems.length; k++) { | ||
const childItem = childItems[k]; | ||
const childItemPath = path.join(itemPath, childItem); | ||
const childItemStats = fs.lstatSync(childItemPath); | ||
if (childItemStats.isFile()) { | ||
filePaths.add(childItemPath); | ||
} | ||
} | ||
} else { | ||
filePaths.add(itemPath); | ||
} | ||
} | ||
} else { | ||
filePaths.add(pactFileOrDir); | ||
} | ||
} | ||
return _publish(filePaths, options); | ||
} | ||
} | ||
/** | ||
* internal publish function | ||
* @param {Set<string>} filePaths - all pact file paths | ||
* @param {PublishOptions} options - publish options | ||
*/ | ||
async function _publish(filePaths, options) { | ||
const consumers = new Set(); | ||
const { consumerVersion, pactBrokerUsername, pactBrokerPassword, tags } = options; | ||
let pactBroker = options.pactBroker || process.env.PACT_BROKER_URL; | ||
for (const filePath of filePaths) { | ||
const ext = path.extname(filePath); | ||
if (ext === '.json') { | ||
const pactFile = require(filePath); | ||
const consumer = pactFile.consumer.name || config.pact.consumer || process.env.PACTUM_PACT_CONSUMER_NAME; | ||
const provider = pactFile.provider.name; | ||
consumers.add(consumer); | ||
await rp.put({ | ||
uri: `${pactBroker}/pacts/provider/${provider}/consumer/${consumer}/version/${consumerVersion}`, | ||
auth: { | ||
user: pactBrokerUsername || process.env.PACT_BROKER_USERNAME, | ||
pass: pactBrokerPassword || process.env.PACT_BROKER_PASSWORD | ||
}, | ||
json: pactFile | ||
}); | ||
} | ||
} | ||
for (const consumer of consumers) { | ||
for (let i = 0; i < tags.length; i++) { | ||
const tag = tags[i]; | ||
await rp.put({ | ||
uri: `${pactBroker}/pacticipants/${consumer}/versions/${consumerVersion}/tags/$${tag}`, | ||
auth: { | ||
user: pactBrokerUsername || process.env.PACT_BROKER_USERNAME, | ||
pass: pactBrokerPassword || process.env.PACT_BROKER_PASSWORD | ||
}, | ||
headers: { | ||
'Content-Type': 'application/json' | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
module.exports = Pact; |
@@ -9,2 +9,6 @@ const Spec = require('./models/spec'); | ||
/** | ||
* request method | ||
* @typedef {('GET'|'POST'|'PUT'|'DELETE'|'PATCH'|'HEAD')} RequestMethod | ||
*/ | ||
@@ -19,3 +23,3 @@ /** | ||
* @property {object} withRequest - interaction request details | ||
* @property {string} withRequest.method - request method | ||
* @property {RequestMethod} withRequest.method - request method | ||
* @property {string} withRequest.path - request path | ||
@@ -25,2 +29,3 @@ * @property {object} [withRequest.headers] - request headers | ||
* @property {object} [withRequest.body] - request body | ||
* @property {boolean} [withRequest.ignoreQuery] - ignores request query while matching | ||
* @property {boolean} [withRequest.ignoreBody] - ignores request body while matching | ||
@@ -27,0 +32,0 @@ * @property {object} willRespondWith - interaction response details |
@@ -5,2 +5,4 @@ const helper = require('../helpers/helper'); | ||
const ALLOWED_REQUEST_METHODS = new Set(['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD']); | ||
class InteractionRequest { | ||
@@ -31,3 +33,7 @@ | ||
this.headers = response.headers; | ||
this.rawBody = JSON.parse(JSON.stringify(response.body)); | ||
if (response.body && typeof response.body === 'object') { | ||
this.rawBody = JSON.parse(JSON.stringify(response.body)); | ||
} else { | ||
this.rawBody = response.body; | ||
} | ||
this.body = helper.setValueFromMatcher(response.body); | ||
@@ -77,2 +83,5 @@ } | ||
} | ||
if (!ALLOWED_REQUEST_METHODS.has(withRequest.method)) { | ||
throw new PactumInteractionError(`Invalid interaction request method provided - ${withRequest.method}`); | ||
} | ||
if (typeof withRequest.path !== 'string' || !withRequest.path) { | ||
@@ -79,0 +88,0 @@ throw new PactumInteractionError(`Invalid interaction request path provided - ${withRequest.path}`); |
@@ -155,3 +155,7 @@ const express = require('express'); | ||
res.status(interaction.willRespondWith.status); | ||
res.send(interaction.willRespondWith.body); | ||
if (interaction.willRespondWith.body) { | ||
res.send(interaction.willRespondWith.body); | ||
} else { | ||
res.send(); | ||
} | ||
} | ||
@@ -162,4 +166,5 @@ if (!interactionExercised) { | ||
console.log('PACTUM', req.method, req.path); | ||
console.log('PACTUM', 'Query', req.query); | ||
console.log('PACTUM', 'Body', req.body); | ||
console.log('PACTUM', 'Headers -', req.headers); | ||
console.log('PACTUM', 'Query -', req.query); | ||
console.log('PACTUM', 'Body -', req.body); | ||
res.status(404); | ||
@@ -166,0 +171,0 @@ res.send('Interaction Not Found'); |
@@ -9,2 +9,7 @@ const rp = require('request-promise'); | ||
/** | ||
* request method | ||
* @typedef {('GET'|'POST'|'PUT'|'DELETE'|'PATCH'|'HEAD')} RequestMethod | ||
*/ | ||
/** | ||
* interaction details | ||
@@ -17,3 +22,3 @@ * @typedef {object} Interaction | ||
* @property {object} withRequest - interaction request details | ||
* @property {string} withRequest.method - request method | ||
* @property {RequestMethod} withRequest.method - request method | ||
* @property {string} withRequest.path - request path | ||
@@ -23,2 +28,3 @@ * @property {object} [withRequest.headers] - request headers | ||
* @property {object} [withRequest.body] - request body | ||
* @property {boolean} [withRequest.ignoreQuery] - ignores request query while matching | ||
* @property {boolean} [withRequest.ignoreBody] - ignores request body while matching | ||
@@ -505,3 +511,3 @@ * @property {object} willRespondWith - interaction response details | ||
this._expect.validate(this._response); | ||
return this._response.json; | ||
return this._response; | ||
} | ||
@@ -508,0 +514,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
86198
1946
9