//package location $PACKAGE_ROOT/tests/{{{version}}}.js Promise = require('bluebird'); var sinon = require('sinon'); var chai = require('chai'); var chaiAsPromised = require('chai-as-promised'); var sinonChai = require("sinon-chai"); var sdkInterface = require('bi-service-sdk'); var sdk = require('../{{{version}}}.js'); var moduleIndexJs = require('../index.js'); //this makes sinon-as-promised available in sinon: require('sinon-as-promised'); var expect = chai.expect; chai.use(sinonChai); chai.use(chaiAsPromised); chai.should(); var context = {{{context}}}; var HAS_HOST = context.host ? true : false; describe('index.js', function() { it(`should export SDK verion ${context.version}`, function() { moduleIndexJs.should.have.property(context.version, sdk); }); }); describe(context.moduleName, function() { before(function() { this.buildSDK = function() { if (HAS_HOST) { return new sdk; } return new sdk({baseURL: 'localhost'}); }; if (!HAS_HOST) { context.host = 'localhost'; } }); if (!HAS_HOST) { it('should throw an Error when `baseURL` option is not set', function() { expect(function() { new sdk({baseURL: undefined}); }).to.throw(Error); }); } it('should export constructor object which inherits from BIServiceSDK interface', function() { sdk.should.be.instanceof(Function); (this.buildSDK()).should.be.instanceof(sdkInterface.BIServiceSDK); }); it(`should have "version" property equal to ${context.version}`, function() { (this.buildSDK()).version.should.be.equal(context.version); }); it('should call parent BIServiceSDK constructor with already prepared `options` object', function() { //we must test this explicitly this way as spy.calledWith API stores references //to the object arguments, thus if a function is called with an object that does NOT //contain all required properties (which are then added after the function call), //the `calledWith` assertion would have still passed through successfully var sdkInterfaceConstructorStub = sinon.stub(sdkInterface.BIServiceSDK, 'call', function(thisContext, options) { options.should.be.eql({ baseURL: context.host + context.basePath }); }); var client = this.buildSDK(); sdkInterfaceConstructorStub.should.have.been.calledOnce; sdkInterfaceConstructorStub.restore(); }); describe('SDK methods', function() { beforeEach(function() { this.sdk = this.buildSDK(); this.requestStub = sinon.stub(this.sdk.axios, 'request').returns(Promise.resolve({})); }); context.paths.forEach(function(path) { describe(path.sdkMethodName, function() { beforeEach(function() { this.path = path; this.methodArgs = range(path.pathParams.length); }); it('should be a method of the SDK', function() { this.sdk.should.have.property(path.sdkMethodName).that.is.a('function'); }); it('should return a promise', function() { return this.sdk[path.sdkMethodName].apply(this.sdk, this.methodArgs).should.be.fulfilled; }); it('should be called with correct http method', function() { var self = this; return this.sdk[path.sdkMethodName].apply(this.sdk, this.methodArgs). should.be.fulfilled.then(function() { self.requestStub.should.have.been.calledOnce; self.requestStub.should.have.been.calledWith(sinon.match(function(val) { val.should.have.property('method', self.path.method); return true; })); }); }); it('should be called with correct url', function() { var self = this; return this.sdk[path.sdkMethodName].apply(this.sdk, this.methodArgs). should.be.fulfilled.then(function() { var url = self.path.url; self.methodArgs.forEach(function(arg) { url = url.replace(/{\w+}/, arg); }); self.requestStub.should.have.been.calledOnce; self.requestStub.should.have.been.calledWith(sinon.match(function(val) { val.should.have.property('url', url); return true; })); }); }); it('should be called with correct url (2)', function() { var self = this; var pathArgs = this.path.pathParams.reduce(function(out, arg, index) { out[arg.name] = self.methodArgs[index]; return out; }, {}); return this.sdk[path.sdkMethodName]({path: pathArgs}). should.be.fulfilled.then(function() { var url = self.path.url; self.methodArgs.forEach(function(arg) { url = url.replace(/{\w+}/, arg); }); self.requestStub.should.have.been.calledOnce; self.requestStub.should.have.been.calledWith(sinon.match(function(val) { val.should.have.property('url', url); return true; })); }); }); it('should set default `data` & `headers` & `params` (aka. query) values to empty objects when we dont provide the options', function() { var self = this; return this.sdk[path.sdkMethodName].apply(this.sdk, this.methodArgs). should.be.fulfilled.then(function() { self.requestStub.should.have.been.calledWith(sinon.match(function(val) { if (~['post', 'put', 'delete'].indexOf(self.path.method)) { val.should.have.property('data').that.is.eql({}); } val.should.have.property('params').that.is.eql({}); val.should.have.property('headers').that.is.eql({}); return true; })); }); }); it('should provide the request method with received req data (headers, body, query)', function() { var self = this; var data = { data: { data: 'param' // query or body param }, query: { query: 'param' }, headers: { header: 'param' } }; var dataClone = JSON.parse(JSON.stringify(data)); this.methodArgs.push(data); return this.sdk[path.sdkMethodName].apply(this.sdk, this.methodArgs). should.be.fulfilled.then(function() { var url = self.path.url; self.methodArgs.forEach(function(arg) { url = url.replace(/{\w+}/, arg); }); self.requestStub.should.have.been.calledOnce; self.requestStub.should.have.been.calledWith(sinon.match(function(val) { if (~['post', 'put', 'delete'].indexOf(self.path.method)) { val.should.have.property('data').that.is.eql(dataClone.data); } else { Object.assign(dataClone.query, dataClone.data); } val.should.have.property('params').that.is.eql(dataClone.query); val.should.have.property('headers').that.is.eql(dataClone.headers); return true; })); }); }); }); }); }); }); function range(num) { var out = []; for (var i = 0, len = num; i < len; i++) { out.push(i + ''); } return out; }