diff --git a/src/lib/connectors/angular.js b/src/lib/connectors/angular.js index 56dba8e6b..69a8e4a08 100644 --- a/src/lib/connectors/angular.js +++ b/src/lib/connectors/angular.js @@ -10,25 +10,37 @@ var _ = require('../utils'); var ConnectionAbstract = require('../connection'); var ConnectionFault = require('../errors').ConnectionFault; +function makeAuthHeader(auth) { + return 'Basic ' + (new Buffer(auth, 'utf8')).toString('base64'); +} + function AngularConnector(host, config) { ConnectionAbstract.call(this, host, config); - var connector = this; + var self = this; + self.headerDefaults = {}; + + if (self.host.auth) { + self.headerDefaults.Authorization = makeAuthHeader(self.host.auth); + } config.$injector.invoke(['$http', '$q', function ($http, $q) { - connector.$q = $q; - connector.$http = $http; - - if (connector.host.auth) { - connector.$http.defaults.headers.common.Authorization = 'Basic ' + (new Buffer(connector.host.auth, 'utf8')).toString('base64'); - } + self.$q = $q; + self.$http = $http; }]); - - } _.inherits(AngularConnector, ConnectionAbstract); -AngularConnector.prototype.request = function (params, cb) { +AngularConnector.prototype.request = function (userParams, cb) { var abort = this.$q.defer(); + var params = _.cloneDeep(userParams); + + params.headers = _.defaults(params.headers || {}, this.headerDefaults); + if (params.auth) { + params.headers.Authorization = makeAuthHeader(params.auth); + } + + // inform the host not to use the auth, by overriding it in the params + params.auth = false; this.$http({ method: params.method, @@ -51,4 +63,4 @@ AngularConnector.prototype.request = function (params, cb) { return function () { abort.resolve(); }; -}; +}; \ No newline at end of file diff --git a/src/lib/host.js b/src/lib/host.js index b4705a5c5..768dfb8e2 100644 --- a/src/lib/host.js +++ b/src/lib/host.js @@ -125,7 +125,7 @@ Host.prototype.makeUrl = function (params) { var auth = ''; if (params.auth) { auth = params.auth + '@'; - } else if (this.auth) { + } else if (this.auth && params.auth !== false) { auth = this.auth + '@'; } diff --git a/test/browser_build_unit_tests.html b/test/browser_build_unit_tests.html index 5d20b0b89..9c3816279 100644 --- a/test/browser_build_unit_tests.html +++ b/test/browser_build_unit_tests.html @@ -18,6 +18,7 @@ + diff --git a/test/unit/browser_builds/angular.js b/test/unit/browser_builds/angular.js index 9e6c507c9..65c7ec637 100644 --- a/test/unit/browser_builds/angular.js +++ b/test/unit/browser_builds/angular.js @@ -1,7 +1,7 @@ -/* jshint browser:true */ -/* global angular */ - +var _ = require('lodash-node'); var expect = require('expect.js'); +var Promise = require('bluebird'); +var sinon = require('sinon'); describe('Angular esFactory', function () { before(function () { @@ -9,110 +9,137 @@ describe('Angular esFactory', function () { }); var uuid = (function () { var i = 0; return function () { return ++i; }; }()); + var esFactory; + var $http; + var $rootScope; + var $httpBackend; - /** - * Perform promise based async code in a way that mocha will understand - * @param {Function} cb - node style callback - * @param {Function} body - function that executes async and returns a promise/value - */ - var prom = function (cb, body) { - expect(cb).to.be.a('function'); - expect(body).to.be.a('function'); + function bootstrap(env) { + beforeEach(function () { + var promiseProvider = _.noop; + if (env.bluebirdPromises) { + promiseProvider = function ($provide) { + $provide.service('$q', function () { + return { + defer: function () { + return _.bindAll(Promise.defer(), ['resolve', 'reject']); + }, + reject: Promise.reject, + when: Promise.resolve, + all: Promise.all + }; + }); + }; + } - var promise = body(); - expect(promise.then).to.be.a('function'); - promise.then(function () { cb(); }, cb); - }; - - function directive(makeDirective) { - var root = document.createElement('div'); - root.setAttribute('ng-controller', 'empty-controller'); - var id = uuid(); - root.setAttribute('test-directive-' + id, 'test-directive'); - document.body.appendChild(root); - - after(function () { - document.body.removeChild(root); - root = null; + angular.mock.module(promiseProvider, 'elasticsearch'); }); - angular - .module('mod' + id, ['elasticsearch']) - .controller('empty-controller', function () {}) - .directive('testDirective' + id, makeDirective); - - angular.bootstrap(root, ['mod' + id]); + beforeEach(angular.mock.inject(function ($injector) { + $http = $injector.get('$http'); + esFactory = $injector.get('esFactory'); + $rootScope = $injector.get('$rootScope'); + $httpBackend = $injector.get('$httpBackend'); + })); } - it('is available in the elasticsearch module', function (done) { - directive(function (esFactory) { - return function () { - expect(esFactory).to.be.a('function'); - done(); - }; + describe('basic', function () { + bootstrap({ + bluebirdPromises: true + }); + + it('is available in the elasticsearch module', function () { + expect(esFactory).to.be.a('function'); + }); + + it('has Transport and ConnectionPool properties', function () { + expect(esFactory).to.have.property('Transport'); + expect(esFactory).to.have.property('ConnectionPool'); + }); + + it('returns a new client when it is called', function () { + var client = esFactory({ + hosts: null + }); + + expect(client).to.have.keys('transport'); + expect(client.transport).to.be.a(esFactory.Transport); + client.close(); + }); + + it('returns an error created by calling a method incorrectly', function () { + var client = esFactory({ hosts: null }); + var err; + + var prom = client.get().then(function () { + throw new Error('expected request to fail'); + }, function (err) { + expect(err).to.have.property('message'); + expect(err.message).to.match(/unable/i); + }); + + $rootScope.$apply(); + return prom; }); }); - it('has Transport and ConnectionPool properties', function (done) { - directive(function (esFactory) { - return function () { - expect(esFactory).to.have.property('Transport'); - expect(esFactory).to.have.property('ConnectionPool'); - done(); - }; + describe('ping', function () { + bootstrap({ + bluebirdPromises: true + }); + + it('works', function () { + $httpBackend.expect('HEAD', 'http://some-es-host.com/').respond(200); + + var client = esFactory({ + host: 'http://some-es-host.com/' + }); + + var connection = client.transport.connectionPool.getConnections().pop(); + var stub = sinon.stub(connection, '$http', function (config) { + process.nextTick($httpBackend.flush); + return $http(config); + }); + + return client.ping(); }); }); - it('returns a new client when it is called', function (done) { - directive(function (esFactory) { - return function () { - try { - var client = esFactory({ - hosts: null - }); + describe('$http', function () { + bootstrap({ + bluebirdPromises: true + }); - expect(client).to.have.keys('transport'); - expect(client.transport).to.be.a(esFactory.Transport); - client.close(); - } catch (e) { - return done(e); + it('uses the auth header provided', function () { + var authString = 'user:password'; + var authHeader = 'Basic ' + (new Buffer(authString, 'utf8')).toString('base64'); + var $httpParams = null; + var client = esFactory({ + host: { + host: 'some-other-es-host.com', + auth: authString } - done(); - }; - }); - }); + }); - it('returns an error created by calling a method incorrectly', function (done) { - directive(function (esFactory) { - return function () { - prom(done, function () { - var client = esFactory({ hosts: null }); - return client.get().then(function () { - expect.fail('promise should have been rejected'); - }, function (err) { - expect(err.message).to.match(/unable/i); - }); + // once the client calls the $http method, flush the requests and trigger an + // error if the expected request was not made + var connection = client.transport.connectionPool.getConnections().pop(); + var stub = sinon.stub(connection, '$http', function (params) { + $httpParams = params; + return Promise.resolve({ + data: null, + status: 200, + headers: function () { + return {}; + } }); - }; - }); - }); + }); - it('ping\'s properly', function (done) { - directive(function (esFactory) { - return function () { - prom(done, function () { - var client = esFactory({ - hosts: 'not-a-valid-es-host.es' - }); - - return client.ping().then(function () { - expect.fail('promise should have been rejected'); - }, function (err) { - // this error should be "NoConnections", but in some browsers it will be a Timeout due to testing proxy or because it's IE - expect(err).to.be.ok(); - }); - }); - }; + var prom = client.ping(); + return prom.then(function () { + expect($httpParams).to.have.property('headers'); + expect($httpParams.headers).to.have.property('Authorization', authHeader); + }); }); }); }); \ No newline at end of file