Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

consumer-contracts

Package Overview
Dependencies
Maintainers
1
Versions
11
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

consumer-contracts - npm Package Compare versions

Comparing version 1.5.0 to 3.0.1

.eslintignore

8

lib/cli.js
#! /usr/bin/env node
var program = require('commander');
var package = require('../package');
var runner = require('./runner');
const program = require('commander');
const package = require('../package');
const runner = require('./runner');

@@ -15,2 +15,2 @@ program

if (!program.args.length) program.help();
if (!program.args.length) program.help();

@@ -1,9 +0,11 @@

var Joi = require('joi');
var util = require('util');
var debug = require('debug')('consumer-contracts');
var _ = require('lodash');
var async = require('async');
var package = require('../package');
'use strict';
var requiredOptions = [
const _ = require('lodash');
const async = require('async');
const debug = require('debug')('consumer-contracts');
const Joi = require('joi');
const pkg = require('../package');
const requiredOptions = [
'name',

@@ -15,3 +17,3 @@ 'consumer',

var joiOptions = {
const joiOptions = {
allowUnknown: true,

@@ -23,5 +25,5 @@ presence: 'required'

options = options || {};
requiredOptions.forEach(function (key) {
requiredOptions.forEach((key) => {
if (!options.hasOwnProperty(key)) {
throw new Error('Invalid contract: Missing required property [' + key + ']');
throw new Error(`Invalid contract: Missing required property [${key}]`);
}

@@ -31,59 +33,64 @@ });

function Contract(options) {
validateOptions(options);
this.name = options.name;
this.consumer = options.consumer;
this.request = options.request;
this.response = options.response;
this.client = (options.client || require('request')).defaults({
json: true,
headers: {
'user-agent': 'consumer-contracts/' + package.version
}
});
this.before = options.before;
this.after = options.after;
if (options.joiOptions) {
this.joiOptions = joiOptions = _.merge(joiOptions, options.joiOptions);
}
function createError(detail, path, res) {
const err = new Error(`Contract failed: ${detail.message}`);
err.detail = `at res.${path} got [${_.get(res, path)}]`;
return err;
}
Contract.prototype.validate = function (cb) {
var schema = Joi.object().keys(this.response);
var client = this.client;
var request = this.request;
var tasks = [];
class Contract {
constructor(options) {
validateOptions(options);
this.name = options.name;
this.consumer = options.consumer;
this.before = options.before;
this.after = options.after;
if (this.before) {
tasks.push(this.before);
this._request = options.request;
this._response = options.response;
this._client = (options.client || require('request')).defaults({
json: true,
headers: {
'user-agent': 'consumer-contracts/' + pkg.version
}
});
if (options.joiOptions) {
this.joiOptions = _.merge(joiOptions, options.joiOptions);
}
}
tasks.push(function (done) {
client(request, function (err, res) {
if (err) return done(new Error(util.format('Request failed: %s', err.message)));
validate(cb) {
const schema = Joi.object().keys(this._response);
const tasks = [];
debug(util.format('%s %s %s', res.request.method, res.request.href, res.statusCode));
if (this.before) {
tasks.push(this.before);
}
var result = Joi.validate(res, schema, joiOptions);
var path;
var detail;
tasks.push((done) => {
this._client(this._request, (err, res) => {
if (err) return done(new Error(`Request failed: ${err.message}`));
if (result.error) {
detail = result.error.details[0];
path = detail.path;
err = new Error(util.format('Contract failed: %s', detail.message));
err.detail = util.format('at res.%s got [%s]', path, _.get(res, path));
}
debug(`${res.request.method} ${res.request.href} ${res.statusCode}`);
done(err);
const result = Joi.validate(res, schema, joiOptions);
if (result.error) {
const detail = result.error.details[0];
const path = detail.path;
return done(createError(detail, path, res));
}
done();
});
});
});
if (this.after) {
tasks.push(this.after);
if (this.after) {
tasks.push(this.after);
}
async.series(tasks, cb);
}
}
async.series(tasks, cb);
};
module.exports = Contract;

@@ -1,8 +0,11 @@

var colors = require('chalk');
var util = require('util');
'use strict';
/* eslint-disable no-console */
const colors = require('chalk');
function addErrIndicies(results) {
var errIndex = 1;
let errIndex = 1;
results.forEach(function (result) {
results.forEach((result) => {
if (result.err) {

@@ -15,9 +18,9 @@ result.errIndex = errIndex++;

function printResult(result) {
var consumer = result.contract.consumer;
var name = result.contract.name;
const consumer = result.contract.consumer;
const name = result.contract.name;
if (result.err) {
console.log(' ', colors.red(result.errIndex + ')', consumer, '–', name));
console.log(` ${colors.red(result.errIndex + ')', consumer, '–', name)}`);
} else {
console.log(' ', colors.green('✓'), colors.reset(consumer, '–', name));
console.log(` ${colors.green('✓')} ${colors.reset(consumer, '–', name)}`);
}

@@ -27,9 +30,9 @@ }

function printFailure(failure, i) {
var contract = failure.contract;
var error = failure.err;
const contract = failure.contract;
const error = failure.err;
console.log(' ', colors.reset(i + 1 + ')', contract.consumer, '–', contract.name));
console.log(' ', colors.red(error.message));
console.log(` ${colors.reset(i + 1 + ')', contract.consumer, '–', contract.name)}`);
console.log(` ${colors.red(error.message)}`);
if (error.detail) {
console.log(' ', colors.gray(error.detail));
console.log(` ${colors.gray(error.detail)}`);
}

@@ -40,4 +43,4 @@ console.log('');

module.exports.print = function (data) {
var failures = data.failures;
var results = data.results;
const failures = data.failures;
const results = data.results;

@@ -50,6 +53,6 @@ addErrIndicies(results);

console.log('\n');
console.log(colors.green(util.format(' %d passing', data.totalPassed)));
console.log(colors.green(` ${data.totalPassed} passing`));
if (failures.length > 0) {
console.log(colors.red(util.format(' %d failing', data.totalFailed)));
console.log(colors.red(` ${data.totalFailed} failing`));
console.log('');

@@ -56,0 +59,0 @@ failures.forEach(printFailure);

@@ -1,13 +0,29 @@

var _ = require('lodash');
var FileHound = require('filehound');
var path = require('path');
var fs = require('fs');
var formatter = require('./formatter');
var validateContracts = require('./validator');
'use strict';
/* eslint-disable no-console */
const _ = require('lodash');
const FileHound = require('filehound');
const path = require('path');
const fs = require('fs');
const formatter = require('./formatter');
const validateContracts = require('./validator');
function isEmpty(obj) {
return Object.keys(obj).length === 0;
}
function loadContracts(file) {
const contract = require(file);
if (isEmpty(contract)) {
throw new Error(`No contract defined for '${file}'`);
}
return contract;
}
function validateFiles(files) {
var contracts;
let contracts;
try {
contracts = files.map(require);
contracts = files.map(loadContracts);
} catch (err) {

@@ -19,8 +35,8 @@ err.message = 'Failed to load contract: ' + err.message;

validateContracts(contracts, function (err, results) {
var failures = _(results).filter('err').compact().value();
var totalCompleted = contracts.length;
var totalFailed = failures.length;
var totalPassed = totalCompleted - totalFailed;
var exitCode = (failures.length > 0) ? 1 : 0;
validateContracts(contracts, (err, results) => {
const failures = _(results).filter('err').compact().value();
const totalCompleted = contracts.length;
const totalFailed = failures.length;
const totalPassed = totalCompleted - totalFailed;
const exitCode = (failures.length > 0) ? 1 : 0;

@@ -41,3 +57,3 @@ formatter.print({

if (files.length > 0) {
files = files.map(function (file) {
files = files.map((file) => {
return path.join(process.cwd(), file);

@@ -49,7 +65,4 @@ });

var dir = path.join(process.cwd(), 'contracts');
try {
fs.statSync(dir);
} catch (err) {
const dir = path.join(process.cwd(), 'contracts');
if (!fs.existsSync(dir)) {
console.error('No contracts directory found in the current working directory.');

@@ -62,3 +75,3 @@ return process.exit(1);

.ext('js')
.find(function (err, files) {
.find((err, files) => {
if (err) {

@@ -68,4 +81,4 @@ console.error(err.message);

}
validateFiles(files);
});
return validateFiles(files);
});
};

@@ -1,5 +0,5 @@

var async = require('async');
const async = require('async');
function validateContract(contract, cb) {
contract.validate(function (err) {
contract.validate((err) => {
cb(null, {

@@ -12,4 +12,4 @@ contract: contract,

module.exports = function (contracts, cb) {
module.exports = (contracts, cb) => {
async.mapSeries(contracts, validateContract, cb);
};
{
"name": "consumer-contracts",
"version": "1.5.0",
"version": "3.0.1",
"description": "Consumer driven contracts for Node.js",

@@ -8,3 +8,3 @@ "main": "index.js",

"test": "mocha",
"lint": "jshint .",
"lint": "eslint .",
"posttest": "npm run lint",

@@ -16,2 +16,5 @@ "coverage": "istanbul cover _mocha -- -R dot"

},
"engines": {
"node": ">4.0.0"
},
"preferGlobal": true,

@@ -26,3 +29,3 @@ "repository": {

],
"author": "robin@robinmurphy.co.uk",
"author": "ibl-team@lists.forge.bbc.co.uk",
"license": "MIT",

@@ -46,4 +49,6 @@ "bugs": {

"codeclimate-test-reporter": "^0.4.0",
"eslint": "^2.10.2",
"eslint-config-iplayer-es6": "^2.0.0",
"eslint-plugin-mocha": "^2.2.0",
"istanbul": "^0.4.2",
"jshint": "^2.8.0",
"mocha": "^3.0.1",

@@ -53,16 +58,5 @@ "nock": "^9.0.2",

},
"jshintConfig": {
"quotmark": "single",
"unused": true,
"undef": true,
"node": true,
"globals": {
"describe": false,
"it": false,
"before": false,
"beforeEach": false,
"after": false,
"afterEach": false
}
"eslintConfig": {
"extends": "iplayer-es6"
}
}

@@ -1,10 +0,10 @@

var Contract = require('../lib/contract');
var Joi = require('joi');
var assert = require('chai').assert;
var nock = require('nock');
var sinon = require('sinon');
const Contract = require('../lib/contract');
const Joi = require('joi');
const assert = require('chai').assert;
const nock = require('nock');
const sinon = require('sinon');
describe('Contract', function () {
it('throws an error when the name is missing', function () {
assert.throws(function () {
describe('Contract', () => {
it('throws an error when the name is missing', () => {
assert.throws(() => {
new Contract({

@@ -22,4 +22,4 @@ consumer: 'Consumer',

it('throws an error when the consumer is missing', function () {
assert.throws(function () {
it('throws an error when the consumer is missing', () => {
assert.throws(() => {
new Contract({

@@ -37,4 +37,4 @@ name: 'Name',

it('throws an error when the request is missing', function () {
assert.throws(function () {
it('throws an error when the request is missing', () => {
assert.throws(() => {
new Contract({

@@ -50,4 +50,4 @@ name: 'Name',

it('throws an error when the response is missing', function () {
assert.throws(function () {
it('throws an error when the response is missing', () => {
assert.throws(() => {
new Contract({

@@ -62,4 +62,4 @@ name: 'Name',

it('supports passing custom Joi options', function () {
var options = {
it('supports passing custom Joi options', () => {
const options = {
name: 'Name',

@@ -80,3 +80,3 @@ consumer: 'Consumer',

};
var contract = new Contract(options);
const contract = new Contract(options);

@@ -87,8 +87,8 @@ assert.equal(contract.joiOptions.just, options.joiOptions.just);

describe('.validate', function () {
beforeEach(function () {
describe('.validate', () => {
beforeEach(() => {
nock.cleanAll();
});
it('does not return an error when the contract is valid', function (done) {
it('does not return an error when the contract is valid', (done) => {
nock('http://api.example.com').get('/').reply(200, {

@@ -98,3 +98,3 @@ foo: 'bar'

var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -116,3 +116,3 @@ consumer: 'Consumer',

it('returns an error when the contract is broken', function (done) {
it('returns an error when the contract is broken', (done) => {
nock('http://api.example.com').get('/').reply(200, {

@@ -122,3 +122,3 @@ bar: 'baz'

var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -137,3 +137,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ok(err);

@@ -146,6 +146,6 @@ assert.equal(err.message, 'Contract failed: "bar" must be a number');

it('returns an error when the request fails', function (done) {
it('returns an error when the request fails', (done) => {
nock('http://api.example.com').get('/').socketDelay(1000).reply(200, {});
var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -162,3 +162,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ok(err);

@@ -170,3 +170,3 @@ assert.equal(err.message, 'Request failed: ESOCKETTIMEDOUT');

it('sets a user-agent header', function (done) {
it('sets a user-agent header', (done) => {
nock('http://api.example.com', {

@@ -178,3 +178,3 @@ reqheaders: {

var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -193,3 +193,3 @@ consumer: 'Consumer',

it('supports passing a custom request client', function (done) {
it('supports passing a custom request client', (done) => {
nock('http://api.example.com', {

@@ -202,3 +202,3 @@ reqheaders: {

var client = require('request').defaults({
const client = require('request').defaults({
headers: {

@@ -209,3 +209,3 @@ authorization: 'Bearer xxx'

var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -222,3 +222,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ifError(err);

@@ -229,8 +229,8 @@ done();

it('runs the before function before validating the contact', function (done) {
var before = sinon.stub().yields();
it('runs the before before validating the contact', (done) => {
const before = sinon.stub().yields();
nock('http://api.example.com').get('/').reply(200);
var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -247,3 +247,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ifError(err);

@@ -255,8 +255,8 @@ sinon.assert.called(before);

it('returns an error when the before function fails', function (done) {
var before = sinon.stub().yields(new Error('Setup error'));
it('returns an error when the before function fails', (done) => {
const before = sinon.stub().yields(new Error('Setup error'));
nock('http://api.example.com').get('/').reply(200);
var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -273,3 +273,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ok(err);

@@ -281,9 +281,8 @@ assert.equal(err.message, 'Setup error');

it('runs the after function after validating the contact', (done) => {
const after = sinon.stub().yields();
it('runs the after function after validating the contact', function (done) {
var after = sinon.stub().yields();
nock('http://api.example.com').get('/').reply(200);
var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -300,3 +299,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ifError(err);

@@ -308,8 +307,8 @@ sinon.assert.called(after);

it('returns an error when the after function fails', function (done) {
var after = sinon.stub().yields(new Error('Cleanup error'));
it('returns an error when the after function fails', (done) => {
const after = sinon.stub().yields(new Error('Cleanup error'));
nock('http://api.example.com').get('/').reply(200);
var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -326,3 +325,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ok(err);

@@ -334,3 +333,3 @@ assert.equal(err.message, 'Cleanup error');

it('applies any custom Joi options', function (done) {
it('applies any custom Joi options', (done) => {
nock('http://api.example.com').get('/').reply(200, {

@@ -341,3 +340,3 @@ bar: 'baz',

var contract = new Contract({
const contract = new Contract({
name: 'Name',

@@ -359,3 +358,3 @@ consumer: 'Consumer',

contract.validate(function (err) {
contract.validate((err) => {
assert.ok(err);

@@ -362,0 +361,0 @@ assert.equal(err.message, 'Contract failed: "baz" is not allowed');

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc