From e9f3a4a205ed43020ad430bd57988aef53bfcdbc Mon Sep 17 00:00:00 2001 From: Matt Fellows Date: Tue, 19 Sep 2017 08:52:56 +1000 Subject: [PATCH] feat(karma): relax consumer/provider requirement in MockService - For pact-web use cases, where mock service is started independently of the test cases themselves, we allow consumer and provider to be specified in underlying mock service directly. - Logs warning to console if details aren't provided to assist in debugging issues - Addresses pact-foundation/karma-pact/pull/4 - Addresses #59 --- src/common/logger.js | 5 +++ src/dsl/mockService.d.ts | 4 +-- src/dsl/mockService.js | 10 +++--- src/pact-web.js | 15 +++------ test/common/logger.spec.js | 7 ++++ test/dsl/mockService.spec.js | 64 +++++++++++++++++++++++------------- 6 files changed, 67 insertions(+), 38 deletions(-) diff --git a/src/common/logger.js b/src/common/logger.js index 92a1a11cc..083b1f5fa 100644 --- a/src/common/logger.js +++ b/src/common/logger.js @@ -13,5 +13,10 @@ module.exports = { if (config.logging) { console.log(msg) } + }, + warn: (msg) => { + if (config.logging) { + console.warn(msg) + } } } diff --git a/src/dsl/mockService.d.ts b/src/dsl/mockService.d.ts index f216cadac..2f6623eaf 100644 --- a/src/dsl/mockService.d.ts +++ b/src/dsl/mockService.d.ts @@ -4,8 +4,8 @@ export type PactfileWriteMode = "overwrite" | "update" | "none"; export class MockService { constructor( - consumer: string, - provider: string, + consumer?: string, + provider?: string, port?: number, host?: string, ssl?: boolean, diff --git a/src/dsl/mockService.js b/src/dsl/mockService.js index 4223a6861..7d59bd26f 100644 --- a/src/dsl/mockService.js +++ b/src/dsl/mockService.js @@ -9,6 +9,7 @@ const isNil = require('lodash.isnil') const Request = require('../common/request') +const logger = require('../common/logger') module.exports = class MockService { @@ -22,7 +23,8 @@ module.exports = class MockService { */ constructor (consumer, provider, port, host, ssl, pactfileWriteMode) { if (isNil(consumer) || isNil(provider)) { - throw new Error('Please provide the names of the provider and consumer for this Pact.') + logger.warn('Warning: Consumer\Provider details not provided, ensure ' + + 'that the mock service has been started with this information') } port = port || 1234 @@ -33,9 +35,9 @@ module.exports = class MockService { this._request = new Request() this._baseURL = `${ssl ? 'https' : 'http'}://${host}:${port}` this._pactDetails = { - consumer: { name: consumer }, - provider: { name: provider }, - pactfile_write_mode: pactfileWriteMode + pactfile_write_mode: pactfileWriteMode, + consumer: (consumer) ? { name: consumer } : undefined, + provider: (provider) ? { name: provider } : undefined } } diff --git a/src/pact-web.js b/src/pact-web.js index d1b2b3c0e..35f8ce655 100644 --- a/src/pact-web.js +++ b/src/pact-web.js @@ -29,21 +29,16 @@ var Interaction = require('./dsl/interaction') module.exports = (opts) => { var consumer = opts.consumer var provider = opts.provider - - if (isNil(consumer)) { - throw new Error('You must provide a Consumer for this pact.') - } - - if (isNil(provider)) { - throw new Error('You must provide a Provider for this pact.') - } - var port = opts.port || 1234 var host = opts.host || '127.0.0.1' var ssl = opts.ssl || false var pactfileWriteMode = opts.pactfileWriteMode || 'overwrite' - logger.info(`Setting up Pact with Consumer "${consumer}" and Provider "${provider}" using mock service on Port: "${port}"`) + if (isNil(consumer) || isNil(provider)) { + logger.info(`Setting up Pact using mock service on port: "${port}"`) + } else { + logger.info(`Setting up Pact with Consumer "${consumer}" and Provider "${provider}" using mock service on port: "${port}"`) + } const mockService = new MockService(consumer, provider, port, host, ssl, pactfileWriteMode) diff --git a/test/common/logger.spec.js b/test/common/logger.spec.js index cb8a96124..f6d3091b6 100644 --- a/test/common/logger.spec.js +++ b/test/common/logger.spec.js @@ -4,28 +4,35 @@ var proxyquire = require('proxyquire') describe('Logger#info', () => { const consoleLogSpy = sinon.spy(console, 'log') + const consoleWarnSpy = sinon.spy(console, 'warn') context('with logging configuration turned on', () => { beforeEach(() => { consoleLogSpy.reset() + consoleWarnSpy.reset() var logger = proxyquire('../../src/common/logger', { './config': { logging: true } }) logger.info('this will be logged') + logger.warn('this will be logged at warn') }) it('logs a message', () => { expect(consoleLogSpy).to.have.been.calledWith('this will be logged') + expect(consoleWarnSpy).to.have.been.calledWith('this will be logged at warn') }) }) context('with logging configuration turned off', () => { beforeEach(() => { consoleLogSpy.reset() + consoleWarnSpy.reset() var logger = proxyquire('../../src/common/logger', { './config': { logging: false } }) logger.info('this will be ignored') + logger.warn('this will be logged at warn') }) it('ignores a message to be logged', function () { expect(consoleLogSpy).to.not.have.been.called + expect(consoleWarnSpy).to.not.have.been.called }) }) }) diff --git a/test/dsl/mockService.spec.js b/test/dsl/mockService.spec.js index 4bcfd17d0..4f0781310 100644 --- a/test/dsl/mockService.spec.js +++ b/test/dsl/mockService.spec.js @@ -31,12 +31,12 @@ describe('MockService', () => { it('does not create a MockService when consumer is not informed', () => { expect(() => { new MockService() }) - .to.throw(Error, 'Please provide the names of the provider and consumer for this Pact.') + .not.to.throw(Error) }) it('does not create a MockService when provider is not informed', () => { expect(() => { new MockService('consumer') }) - .to.throw(Error, 'Please provide the names of the provider and consumer for this Pact.') + .not.to.throw(Error) }) }) @@ -48,13 +48,12 @@ describe('MockService', () => { it('when Interaction added successfully', (done) => { nock(mock._baseURL).post(/interactions$/).reply(200) - expect(mock.addInteraction(interaction)).to.eventually.notify(done) + expect(mock.addInteraction(interaction)).to.eventually.be.fulfilled.notify(done) }) it('when Interaction fails to be added', (done) => { nock(mock._baseURL).post(/interactions$/).reply(500) - expect(mock.addInteraction(interaction)).to.eventually.be.rejected - done() + expect(mock.addInteraction(interaction)).to.eventually.be.rejected.notify(done) }) }) @@ -63,13 +62,12 @@ describe('MockService', () => { it('when interactions are removed successfully', (done) => { nock(mock._baseURL).delete(/interactions$/).reply(200) - expect(mock.removeInteractions()).to.eventually.notify(done) + expect(mock.removeInteractions()).to.eventually.be.fulfilled.notify(done) }) it('when interactions fail to be removed', (done) => { nock(mock._baseURL).delete(/interactions$/).reply(500) - expect(mock.removeInteractions()).to.eventually.be.rejected - done() + expect(mock.removeInteractions()).to.eventually.be.rejected.notify(done) }) }) @@ -78,29 +76,51 @@ describe('MockService', () => { it('when verification is successful', (done) => { nock(mock._baseURL).get(/interactions\/verification$/).reply(200) - expect(mock.verify()).to.eventually.notify(done) + expect(mock.verify()).to.eventually.be.fulfilled.notify(done) }) it('when verification fails', (done) => { nock(mock._baseURL).get(/interactions\/verification$/).reply(500) - expect(mock.verify()).to.eventually.be.rejected - done() + expect(mock.verify()).to.eventually.be.rejected.notify(done) }) }) describe('#writePact', () => { - const mock = new MockService('consumer', 'provider', 1234) - - it('when writing is successful', (done) => { - nock(mock._baseURL).post(/pact$/).reply(200) - expect(mock.writePact()).to.eventually.notify(done) + describe('when consumer and provider details provided', () => { + const mock = new MockService('aconsumer', 'aprovider', 1234) + + describe('and writing is successful', () => { + it('should write the consumer and provider details into the pact', (done) => { + nock(mock._baseURL) + .post(/pact$/, { + pactfile_write_mode: 'overwrite', + consumer: { name: 'aconsumer' }, + provider: { name: 'aprovider' } + }) + .reply(200) + expect(mock.writePact()).to.eventually.be.fulfilled.notify(done) + }) + }) + + describe('and writing fails', () => { + it('should return a rejected promise', (done) => { + nock(mock._baseURL) + .post(/pact$/).reply(500) + expect(mock.writePact()).to.eventually.be.rejected.notify(done) + }) + }) }) - - it('when writing fails', (done) => { - nock(mock._baseURL).post(/pact$/).reply(500) - expect(mock.writePact()).to.eventually.be.rejected - done() + describe('when consumer and provider details are not provided', () => { + const mock = new MockService(null, null, 1234) + it('should not write the consumer and provider details into the pact', (done) => { + nock(mock._baseURL) + .post(/pact$/, { + pactfile_write_mode: 'overwrite', + consumer: undefined, + provider: undefined + }).reply(200) + expect(mock.writePact()).to.eventually.be.fulfilled.notify(done) + }) }) }) - })