Comparing version 1.0.18 to 1.0.19
{ | ||
"name": "pactum", | ||
"version": "1.0.18", | ||
"version": "1.0.19", | ||
"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", |
const Interaction = require('../models/interaction'); | ||
const { PactumConfigurationError } = require('../helpers/errors'); | ||
const log = require('../helpers/logger'); | ||
@@ -67,2 +68,3 @@ const config = require('../config'); | ||
setDefaultPort(port) { | ||
log.debug('Setting default port number for mock server', port); | ||
if (typeof port !== 'number') { | ||
@@ -82,2 +84,3 @@ throw new PactumConfigurationError(`Invalid default port number - ${port}`); | ||
this.interactionIds.add(interactionObj.id); | ||
log.debug('Added default mock interaction with id', interactionObj.id); | ||
return interactionObj.id; | ||
@@ -102,2 +105,3 @@ } | ||
} | ||
log.debug('Added default mock interactions with ids', ids); | ||
return ids; | ||
@@ -114,2 +118,3 @@ } | ||
this.interactionIds.add(interactionObj.id); | ||
log.debug('Added default pact interactions with id', interactionObj.id); | ||
return interactionObj.id; | ||
@@ -134,2 +139,3 @@ } | ||
} | ||
log.debug('Added default pact interactions with ids', ids); | ||
return ids; | ||
@@ -161,2 +167,3 @@ } | ||
} | ||
log.debug('Cleared default interactions with ids', ids); | ||
} | ||
@@ -163,0 +170,0 @@ |
const fs = require('fs'); | ||
const path = require('path'); | ||
const phin = require('phin'); | ||
const config = require('../config'); | ||
const helper = require('../helpers/helper'); | ||
const store = require('../helpers/store'); | ||
@@ -56,31 +56,3 @@ const { PactumConfigurationError } = require('../helpers/errors'); | ||
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); | ||
} | ||
} | ||
const filePaths = helper.getLocalPactFiles(options.pactFilesOrDirs); | ||
return _publish(filePaths, options); | ||
@@ -103,17 +75,15 @@ } | ||
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 phin({ | ||
url: `${pactBroker}/pacts/provider/${provider}/consumer/${consumer}/version/${consumerVersion}`, | ||
method: 'PUT', | ||
core: { | ||
auth: `${pactBrokerUsername}:${pactBrokerPassword}` | ||
}, | ||
data: pactFile | ||
}); | ||
} | ||
const rawData = fs.readFileSync(filePath); | ||
const pactFile = JSON.parse(rawData); | ||
const consumer = pactFile.consumer.name || config.pact.consumer || process.env.PACTUM_PACT_CONSUMER_NAME; | ||
const provider = pactFile.provider.name; | ||
consumers.add(consumer); | ||
await phin({ | ||
url: `${pactBroker}/pacts/provider/${provider}/consumer/${consumer}/version/${consumerVersion}`, | ||
method: 'PUT', | ||
core: { | ||
auth: `${pactBrokerUsername}:${pactBrokerPassword}` | ||
}, | ||
data: pactFile | ||
}); | ||
} | ||
@@ -120,0 +90,0 @@ for (const consumer of consumers) { |
const phin = require('phin'); | ||
const fs = require('fs'); | ||
const helper = require('../helpers/helper'); | ||
const Compare = require('../helpers/compare'); | ||
const log = require('../helpers/logger'); | ||
const { PactumConfigurationError } = require('../helpers/errors'); | ||
/** | ||
* provider options | ||
* @typedef {object} ProviderOptions | ||
* @property {string} providerBaseUrl - running API provider host endpoint. | ||
* @property {string} provider - name of the provider. | ||
* @property {string} [providerVersion] - provider version, required to publish verification results to a broker | ||
* @property {any} [stateHandlers] - provider state handlers. A map of 'string -> () => Promise', where each string is the state to setup, and the function is used to configure the state in the Provider. | ||
* @property {any} [customProviderHeaders] - Header(s) to add to any requests to the provider service. eg { 'Authorization': 'Basic cGFjdDpwYWN0'}. | ||
* @property {string[]} [pactFilesOrDirs] - array of local pact files or directories | ||
* @property {string} [pactBrokerUrl] - URL of the Pact Broker to retrieve pacts from. Required if not using pactUrls. | ||
* @property {string} [pactBrokerUsername] - username for Pact Broker basic authentication. | ||
* @property {string} [pactBrokerPassword] - password for Pact Broker basic authentication. | ||
* @property {string} [pactBrokerToken] - bearer token for Pact Broker authentication. | ||
* @property {boolean} [publishVerificationResult] - publish verification result to Broker | ||
* @property {string[]} [tags] - array of tags, used to filter pacts from the Broker. | ||
*/ | ||
class Provider { | ||
/** | ||
* constructor | ||
* @param {ProviderOptions} options - provider options | ||
*/ | ||
constructor(options) { | ||
if (!helper.isValidObject(options)) { | ||
throw new PactumConfigurationError(`Invalid provider options provided - ${options}`); | ||
} | ||
this.pactBrokerUrl = options.pactBrokerUrl; | ||
this.pactBrokerUsername = options.pactBrokerUsername; | ||
this.pactBrokerPassword = options.pactBrokerPassword; | ||
this.tags = options.tag || []; | ||
this.pactBrokerToken = options.pactBrokerToken; | ||
this.pactFilesOrDirs = options.pactFilesOrDirs; | ||
// @property {string[]} [pactUrls] - array of HTTP-based URLs (e.g. from a broker). Required if not using a Broker. | ||
this.tags = options.tags || []; | ||
this.publishVerificationResult = options.publishVerificationResult; | ||
@@ -17,27 +46,77 @@ this.stateHandlers = options.stateHandlers || {}; | ||
this.providerBaseUrl = options.providerBaseUrl; | ||
this.providerVersion = options.providerVersion; | ||
this.providerVersion = options.providerVersion; | ||
this.customProviderHeaders = options.customProviderHeaders; | ||
this.validateOptions(); | ||
this.testCount = 0; | ||
this.testPassedCount = 0; | ||
this.testFailedCount = 0; | ||
this.testSkipped = 0; | ||
} | ||
validateOptions() { | ||
if (!helper.isValidString(this.providerBaseUrl)) { | ||
throw new PactumConfigurationError(`Invalid provider base url provided - ${this.providerBaseUrl}`); | ||
} | ||
if (!helper.isValidString(this.provider)) { | ||
throw new PactumConfigurationError(`Invalid provider name provided - ${this.provider}`); | ||
} | ||
if (!this.pactBrokerUrl && !this.pactFilesOrDirs) { | ||
throw new PactumConfigurationError(`Invalid pact-broker url (${this.pactBrokerUrl}) provided & invalid pact local files (${this.pactFilesOrDirs}) provided`); | ||
} | ||
if (this.customProviderHeaders && !helper.isValidObject(this.customProviderHeaders)) { | ||
throw new PactumConfigurationError(`Invalid custom headers provided - ${this.customProviderHeaders}`); | ||
} | ||
if (this.stateHandlers) { | ||
if (!helper.isValidObject(this.stateHandlers)) { | ||
throw new PactumConfigurationError(`Invalid state handlers provided - ${this.stateHandlers}`); | ||
} | ||
for (const prop in this.stateHandlers) { | ||
if (typeof this.stateHandlers[prop] !== 'function') { | ||
throw new PactumConfigurationError(`Invalid state handlers function provided for - ${prop}`); | ||
} | ||
} | ||
} | ||
if (this.publishVerificationResult) { | ||
if (!this.pactBrokerUrl) { | ||
throw new PactumConfigurationError(`Invalid pact broker url provided - ${this.pactBrokerUrl}`); | ||
} | ||
if (!this.providerVersion) { | ||
throw new PactumConfigurationError(`Invalid provider version provided - ${this.providerVersion}`); | ||
} | ||
} | ||
if (this.pactFilesOrDirs) { | ||
if (!Array.isArray(this.pactFilesOrDirs)) { | ||
throw new PactumConfigurationError(`Invalid array of pact files or folders (${this.pactFilesOrDirs}) provided`); | ||
} | ||
if (this.pactFilesOrDirs.length === 0) { | ||
throw new PactumConfigurationError(`Empty array of pact files or folders provided`); | ||
} | ||
} | ||
} | ||
async validate() { | ||
log.info(`Provider Verification: `); | ||
const providerPacts = await this._getLatestProviderPacts(); | ||
for (let i = 0; i < providerPacts.length; i++) { | ||
const providerPact = providerPacts[i]; | ||
const versionString = providerPact.href.match(/\/version\/.*/g); | ||
const consumerVersion = versionString[0].replace('/version/', ''); | ||
const consumerPactDetails = await this._getProviderConsumerPactDetails(providerPact.name, consumerVersion); | ||
log.info(); | ||
log.info(` Consumer: ${providerPact.name} - ${consumerVersion}`); | ||
const interactions = consumerPactDetails.interactions; | ||
for (let j = 0; j < interactions.length; j++) { | ||
const interaction = interactions[j]; | ||
const isValid = await this._validateInteraction(interaction); | ||
log.info(` ${isValid.equal ? '√'.green : 'X'.red } Description: ${interaction.description}`); | ||
if (isValid.message) { | ||
log.warn(` ${isValid.message}`); | ||
} | ||
await this.validatePactsFromPactBroker(); | ||
await this.validatePactsFromLocal(); | ||
this.printSummary(); | ||
} | ||
async validatePactsFromPactBroker() { | ||
if (this.pactBrokerUrl) { | ||
const providerPacts = await this._getLatestProviderPacts(); | ||
for (let i = 0; i < providerPacts.length; i++) { | ||
const providerPact = providerPacts[i]; | ||
const versionString = providerPact.href.match(/\/version\/.*/g); | ||
const consumerVersion = versionString[0].replace('/version/', ''); | ||
const consumerPactDetails = await this._getProviderConsumerPactDetails(providerPact.name, consumerVersion); | ||
log.info(); | ||
log.info(` Consumer: ${providerPact.name} - ${consumerVersion}`); | ||
const interactions = consumerPactDetails.interactions; | ||
const success = await this.validateInteractions(interactions); | ||
if (this.publishVerificationResult) { | ||
const url = consumerPactDetails['_links']['pb:publish-verification-results']['href']; | ||
const path = url.match(/\/pacts\/provider.*/g)[0]; | ||
await this._publishVerificationResults(path, isValid.equal); | ||
await this._publishVerificationResults(path, success); | ||
} | ||
@@ -48,30 +127,69 @@ } | ||
async validatePactsFromLocal() { | ||
if (this.pactFilesOrDirs) { | ||
const filePaths = helper.getLocalPactFiles(this.pactFilesOrDirs); | ||
for (const filePath of filePaths) { | ||
const rawData = fs.readFileSync(filePath); | ||
const pactFile = JSON.parse(rawData); | ||
const consumer = pactFile.consumer.name; | ||
const provider = pactFile.provider.name; | ||
if (this.provider === provider) { | ||
log.info(); | ||
log.info(` Consumer: ${consumer}`); | ||
const interactions = pactFile.interactions; | ||
await this.validateInteractions(interactions); | ||
} else { | ||
log.warn(`Invalid provider ${provider} in ${filePath}`); | ||
} | ||
} | ||
} | ||
} | ||
async validateInteractions(interactions) { | ||
let success = true; | ||
for (let j = 0; j < interactions.length; j++) { | ||
this.testCount = this.testCount + 1; | ||
const interaction = interactions[j]; | ||
const isValid = await this._validateInteraction(interaction); | ||
if (isValid.equal) { | ||
this.testPassedCount = this.testPassedCount + 1; | ||
log.info(` ${'√'.green} ${interaction.description.gray}`); | ||
} else { | ||
success = false; | ||
this.testFailedCount = this.testFailedCount + 1; | ||
log.info(` ${'X'.red} ${interaction.description.gray}`); | ||
log.error(` ${isValid.message.red}`); | ||
} | ||
} | ||
return success; | ||
} | ||
async _getLatestProviderPacts() { | ||
const response = await phin({ | ||
url: `${this.pactBrokerUrl}/pacts/provider/${this.provider}/latest`, | ||
core: { | ||
auth: `${this.pactBrokerUsername}:${this.pactBrokerPassword}` | ||
}, | ||
method: 'GET' | ||
}); | ||
const requestOptions = this._getPactBrokerRequestOptions(); | ||
requestOptions.url = `${this.pactBrokerUrl}/pacts/provider/${this.provider}/latest`; | ||
requestOptions.method = 'GET'; | ||
log.debug('Fetching latest provider pacts', requestOptions); | ||
const response = await phin(requestOptions); | ||
if (response.statusCode === 200) { | ||
const body = helper.getJson(response.body); | ||
return body['_links']['pb:pacts']; | ||
} else { | ||
log.error(`Failed to fetch latest provider pacts. | Response: ${response.statusCode} - ${response.statusMessage}`); | ||
return null; | ||
} | ||
return null; | ||
} | ||
async _getProviderConsumerPactDetails(consumer, consumerVersion) { | ||
const response = await phin({ | ||
url: `${this.pactBrokerUrl}/pacts/provider/${this.provider}/consumer/${consumer}/version/${consumerVersion}`, | ||
core: { | ||
auth: `${this.pactBrokerUsername}:${this.pactBrokerPassword}` | ||
}, | ||
method: 'GET' | ||
}); | ||
const requestOptions = this._getPactBrokerRequestOptions(); | ||
requestOptions.url = `${this.pactBrokerUrl}/pacts/provider/${this.provider}/consumer/${consumer}/version/${consumerVersion}`; | ||
requestOptions.method = 'GET'; | ||
log.debug('Fetching provider-consumer pacts', requestOptions); | ||
const response = await phin(requestOptions); | ||
if (response.statusCode === 200) { | ||
const body = helper.getJson(response.body); | ||
return body; | ||
} else { | ||
log.error(`Failed to fetch consumer pact details. | Response: ${response.statusCode} - ${response.statusMessage}`); | ||
return null; | ||
} | ||
return null; | ||
} | ||
@@ -86,29 +204,132 @@ | ||
} | ||
const actualResponse = await phin({ | ||
url: `${this.providerBaseUrl}${request.path}`, | ||
method: request.method | ||
}); | ||
const actualBody = helper.getJson(actualResponse.body); | ||
const expectedBody = response.body; | ||
let matchingRules = response.matchingRules; | ||
if (!matchingRules) { | ||
matchingRules = {}; | ||
const actualResponse = await phin(this._getInteractionRequestOptions(request)); | ||
return this._validateResponse(actualResponse, response); | ||
} | ||
async _publishVerificationResults(path, success) { | ||
const requestOptions = this._getPactBrokerRequestOptions(); | ||
requestOptions.url = `${this.pactBrokerUrl}${path}`; | ||
requestOptions.method = 'POST'; | ||
requestOptions.data = { | ||
success, | ||
providerApplicationVersion: this.providerVersion | ||
}; | ||
log.debug('Publishing verification results.', requestOptions); | ||
const response = await phin(requestOptions); | ||
if (response.statusCode !== 200) { | ||
log.error(`Failed to publish verification results. | Response: ${response.statusCode} - ${response.statusMessage}`); | ||
} | ||
const compare = new Compare(); | ||
return compare.jsonMatch(actualBody, expectedBody, matchingRules, '$.body'); | ||
} | ||
_publishVerificationResults(path, success) { | ||
return phin({ | ||
url: `${this.pactBrokerUrl}${path}`, | ||
method: 'POST', | ||
data: { | ||
success, | ||
providerApplicationVersion: this.providerVersion | ||
_validateResponse(actual, expected) { | ||
const isValidStatus = this._validateStatus(actual.statusCode, expected.status); | ||
if (!isValidStatus.equal) { | ||
return isValidStatus; | ||
} | ||
const isValidHeaders = this._validateHeaders(actual, expected); | ||
if (!isValidHeaders.equal) { | ||
return isValidHeaders; | ||
} | ||
return this._validateBody(actual, expected); | ||
} | ||
_validateStatus(actualStatus, expectedStatus) { | ||
if (expectedStatus && actualStatus !== expectedStatus) { | ||
return { | ||
equal: false, | ||
message: `HTTP status ${actualStatus} !== ${expectedStatus}` | ||
}; | ||
} else { | ||
return { | ||
equal: true | ||
}; | ||
} | ||
} | ||
_validateHeaders(actual, expected) { | ||
if (expected.headers) { | ||
let matchingRules = expected.matchingRules; | ||
if (!matchingRules) { | ||
matchingRules = {}; | ||
} | ||
}); | ||
const compare = new Compare(); | ||
return compare.jsonMatch(actual.headers, expected.headers, matchingRules, '$.headers'); | ||
} | ||
return { | ||
equal: true | ||
}; | ||
} | ||
_validateBody(actual, expected) { | ||
if (expected.body) { | ||
const actualBody = helper.getJson(actual.body); | ||
let matchingRules = expected.matchingRules; | ||
if (!matchingRules) { | ||
matchingRules = {}; | ||
} | ||
const compare = new Compare(); | ||
return compare.jsonMatch(actualBody, expected.body, matchingRules, '$.body'); | ||
} | ||
return { | ||
equal: true | ||
}; | ||
} | ||
_getInteractionRequestOptions(request) { | ||
const options = { | ||
url: request.query ? `${this.providerBaseUrl}${request.path}?${request.query}` : `${this.providerBaseUrl}${request.path}`, | ||
method: request.method, | ||
headers: request.headers, | ||
data: request.body | ||
}; | ||
if (this.customProviderHeaders) { | ||
if (!options.headers) { | ||
options.headers = {}; | ||
} | ||
for (const prop in this.customProviderHeaders) { | ||
options.headers[prop] = this.customProviderHeaders[prop]; | ||
} | ||
} | ||
return options; | ||
} | ||
_getPactBrokerRequestOptions() { | ||
const requestOptions = {}; | ||
if (this.pactBrokerUsername) { | ||
requestOptions.core = { | ||
auth: `${this.pactBrokerUsername}:${this.pactBrokerPassword}` | ||
}; | ||
} | ||
if (this.pactBrokerToken) { | ||
requestOptions.headers = { | ||
'authorization': `Basic ${this.pactBrokerToken}` | ||
}; | ||
} | ||
return requestOptions; | ||
} | ||
printSummary() { | ||
log.info(); | ||
log.info(` ${this.testPassedCount} passing`.green); | ||
if (this.testFailedCount > 0) { | ||
log.info(` ${this.testFailedCount} failing`.red); | ||
throw 'Provider Verification Failed'; | ||
} | ||
} | ||
} | ||
module.exports = Provider; | ||
const provider = { | ||
/** | ||
* validate provider | ||
* @param {ProviderOptions} options - provider options | ||
*/ | ||
validate(options) { | ||
const providerObj = new Provider(options); | ||
return providerObj.validate(); | ||
} | ||
}; | ||
module.exports = provider; |
@@ -0,1 +1,6 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const log = require('./logger'); | ||
const helper = { | ||
@@ -132,2 +137,42 @@ | ||
return value !== null && typeof value === 'object' && !Array.isArray(value); | ||
}, | ||
/** | ||
* returns set of all pact files | ||
* @param {string[]} pactFilesOrDirs - array of pact files & directories | ||
*/ | ||
getLocalPactFiles(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 childItemStats = fs.lstatSync(itemPath); | ||
if (childItemStats.isFile()) { | ||
const ext = path.extname(itemPath); | ||
if (ext === '.json') { | ||
filePaths.add(itemPath); | ||
} else { | ||
log.warn(`Invalid file type - ${ext} provided in pactFilesOrDirs: ${itemPath}`); | ||
} | ||
} else { | ||
log.warn(`Invalid file provided in pactFilesOrDirs: ${itemPath}`); | ||
} | ||
} | ||
} else if (stats.isFile()) { | ||
const ext = path.extname(pactFileOrDir); | ||
if (ext === '.json') { | ||
filePaths.add(pactFileOrDir); | ||
} else { | ||
log.warn(`Invalid file type - ${ext} provided in pactFilesOrDirs: ${pactFileOrDir}`); | ||
} | ||
} else { | ||
log.warn(`Invalid file provided in pactFilesOrDirs: ${pactFileOrDir}`); | ||
} | ||
} | ||
return filePaths; | ||
} | ||
@@ -134,0 +179,0 @@ |
@@ -14,13 +14,13 @@ const colors = require('colors'); | ||
function getLevelValue(level) { | ||
const lowerCaseLevel = level.toLowerCase(); | ||
const lowerCaseLevel = level.toUpperCase(); | ||
switch (lowerCaseLevel) { | ||
case 'trace': | ||
case 'TRACE': | ||
return LEVEL_TRACE; | ||
case 'debug': | ||
case 'DEBUG': | ||
return LEVEL_DEBUG; | ||
case 'info': | ||
case 'INFO': | ||
return LEVEL_INFO; | ||
case 'warn': | ||
case 'WARN': | ||
return LEVEL_WARN; | ||
case 'error': | ||
case 'ERROR': | ||
return LEVEL_ERROR; | ||
@@ -37,3 +37,3 @@ default: | ||
// validate log level | ||
this.level = process.env.PACTUM_LOG_LEVEL || 'info'; | ||
this.level = process.env.PACTUM_LOG_LEVEL || 'INFO'; | ||
this.levelValue = getLevelValue(this.level); | ||
@@ -45,2 +45,11 @@ if (process.env.PACTUM_DISABLE_LOG_COLORS === 'true') { | ||
/** | ||
* sets log level | ||
* @param {('TRACE'|'DEBUG'|'INFO'|'WARN'|'ERROR')} level - log level | ||
*/ | ||
setLevel(level) { | ||
this.level = level; | ||
this.levelValue = getLevelValue(this.level); | ||
} | ||
trace(...msg) { | ||
@@ -47,0 +56,0 @@ if (this.levelValue <= LEVEL_TRACE) { |
@@ -8,3 +8,3 @@ const Spec = require('./models/spec'); | ||
const request = require('./exports/request'); | ||
const Provider = require('./exports/provider'); | ||
const provider = require('./exports/provider'); | ||
@@ -52,3 +52,3 @@ /** | ||
request, | ||
Provider, | ||
provider, | ||
@@ -55,0 +55,0 @@ /** |
@@ -36,3 +36,3 @@ const assert = require('assert'); | ||
validateInteractions(interactions) { | ||
for (let [id, interaction] of interactions) { | ||
for (const [id, interaction] of interactions) { | ||
assert.ok(interaction.exercised, `Interaction not Exercised: ${interaction.withRequest.method} - ${interaction.withRequest.path}`); | ||
@@ -39,0 +39,0 @@ } |
@@ -24,2 +24,3 @@ const polka = require('polka'); | ||
this.app = polka(); | ||
this.app.use(logger); | ||
this.app.use(bodyParser); | ||
@@ -43,2 +44,3 @@ registerPactumRemoteRoutes(this); | ||
this.app.server.close(() => { | ||
this.app = null; | ||
log.info(`Mock server stopped on port ${config.mock.port}`); | ||
@@ -69,3 +71,3 @@ resolve(); | ||
} else { | ||
// error | ||
log.warn('Unable to remove interaction. Interaction not found with id', id); | ||
} | ||
@@ -77,2 +79,3 @@ | ||
this.mockInteractions.delete(id); | ||
log.trace('Removed mock interaction with id', id); | ||
} | ||
@@ -82,2 +85,3 @@ | ||
this.pactInteractions.delete(id); | ||
log.trace('Removed pact interaction with id', id); | ||
} | ||
@@ -87,2 +91,3 @@ | ||
this.mockInteractions.clear(); | ||
log.trace('Cleared mock interactions'); | ||
} | ||
@@ -92,7 +97,8 @@ | ||
this.pactInteractions.clear(); | ||
log.trace('Cleared pact interactions'); | ||
} | ||
clearAllInteractions() { | ||
this.mockInteractions.clear(); | ||
this.pactInteractions.clear(); | ||
this.clearMockInteractions(); | ||
this.clearPactInteractions(); | ||
} | ||
@@ -132,4 +138,3 @@ | ||
if (!interactionExercised) { | ||
log.warn('Interaction not found'); | ||
log.warn({ | ||
log.warn('Interaction not found', { | ||
method: req.method, | ||
@@ -192,3 +197,4 @@ path: req.path, | ||
} else { | ||
for (let [id, interaction] of interactions) { | ||
for (const [id, interaction] of interactions) { | ||
log.trace('Fetching remote interaction', id); | ||
rawInteractions.push(interaction.rawInteraction); | ||
@@ -229,2 +235,3 @@ } | ||
req.body = helper.getJson(body); | ||
log.trace('Request Body', req.body); | ||
next(); | ||
@@ -234,2 +241,9 @@ }); | ||
function logger(req, res, next) { | ||
log.trace('Request', req.method, req.path); | ||
log.trace('Request Query', req.query); | ||
log.trace('Request Headers', req.headers); | ||
next(); | ||
} | ||
class ExpressResponse { | ||
@@ -236,0 +250,0 @@ constructor(res) { |
@@ -527,6 +527,6 @@ const phin = require('phin'); | ||
} | ||
for (let [id, interaction] of this.mockInteractions) { | ||
for (const [id, interaction] of this.mockInteractions) { | ||
this.server.addMockInteraction(id, interaction); | ||
} | ||
for (let [id, interaction] of this.pactInteractions) { | ||
for (const [id, interaction] of this.pactInteractions) { | ||
this.server.addPactInteraction(id, interaction); | ||
@@ -550,6 +550,6 @@ } | ||
this._response.responseTime = Date.now() - requestStartTime; | ||
for (let [id, interaction] of this.mockInteractions) { | ||
for (const [id, interaction] of this.mockInteractions) { | ||
this.server.removeInteraction(id); | ||
} | ||
for (let [id, interaction] of this.pactInteractions) { | ||
for (const [id, interaction] of this.pactInteractions) { | ||
this.server.removeInteraction(id); | ||
@@ -556,0 +556,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
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
99752
2784
10