diff --git a/lib/core/api/api-factory.js b/lib/core/api/api-factory.js index 7c54935e..af30a526 100644 --- a/lib/core/api/api-factory.js +++ b/lib/core/api/api-factory.js @@ -20,14 +20,8 @@ CUSTOMER_ID: 'X-Availity-Customer-ID', RESPONSE_ENCODING: 'X-Response-Encoding-Context' } - } - }); - - // Factory that creates ApiResourcess - var ApiResourcesProvider = function() { - - // Provider default options that can be overridden at config time - var defaultOptions = { + }, + OPTIONS: { // pre-prend the url with a value like `/public` so we can build urls like `public/api/v1/*` prefix: '', // default base url for endpoints @@ -59,6 +53,22 @@ // Turn off content encoding for angular apis 'X-Response-Encoding-Context': 'NONE' } + } + }); + + // Factory that creates ApiResourcess + var ApiResourcesProvider = function(AV_API) { + + // Provider default options that can be overridden at config time + var defaultOptions = _.merge({}, AV_API.OPTIONS); + + // Allow overrides in config phase + this.setOptions = function(options) { + _.merge(defaultOptions, options); + }; + + this.getOptions = function() { + return angular.copy(defaultOptions); }; /** @@ -327,4 +337,5 @@ }; availity.core.provider('AvApiResource', ApiResourcesProvider); + })(window); diff --git a/lib/core/api/tests/api-factory-spec.js b/lib/core/api/tests/api-factory-spec.js index b6df93c5..61de6dc7 100644 --- a/lib/core/api/tests/api-factory-spec.js +++ b/lib/core/api/tests/api-factory-spec.js @@ -1,39 +1,49 @@ -/*global describe, spyOn, inject, beforeEach, afterEach, it, expect, sinon, jasmine, module*/ +/*global availity, describe, spyOn, inject, beforeEach, afterEach, it, expect, sinon, jasmine, module*/ -describe('AvApiResource', function() { +describe('AvApiResourceProvider', function() { 'use strict'; + var provider; var sandbox; var $httpBackend; var $q; var AvApiResource; var callback; + var AV_API; - var responseData = [{a: 1, b: 2},{a: 1, b: 2}]; + availity.mock.providerSpecHelper(); - beforeEach(function() { + beforeEach(module('availity', function(_AV_API_, _AvApiResourceProvider_, $provide) { - sandbox = sinon.sandbox.create(); - callback = jasmine.createSpy('done'); - module('availity'); - - module(function ($provide) { - var pollingService = { - response: function(response) { - return response || $q.when(response); - } - }; - $provide.value('pollingService', pollingService); - }); + AV_API = _AV_API_; - inject(function(_$httpBackend_, _$q_, _AvApiResource_) { - $httpBackend = _$httpBackend_; - $q = _$q_; - AvApiResource = _AvApiResource_; + provider = _AvApiResourceProvider_; + provider.setOptions({ + headers: { + // Turn off content encoding for angular apis + 'X-Response-Encoding-Context': 'HTML' + } }); - }); + var pollingService = { + response: function(response) { + return response || $q.when(response); + } + }; + $provide.value('pollingService', pollingService); + + })); + + beforeEach(inject(function(_$httpBackend_, _$q_, _AvApiResource_) { + + $httpBackend = _$httpBackend_; + $q = _$q_; + AvApiResource = _AvApiResource_; + sandbox = sinon.sandbox.create(); + callback = jasmine.createSpy('done'); + + })); afterEach(function() { sandbox.restore(); @@ -41,400 +51,418 @@ describe('AvApiResource', function() { $httpBackend.verifyNoOutstandingRequest(); }); - it('should not allow options to be null', function() { - expect(function() { new AvApiResource(); }).toThrow(new Error('[options] cannot be null or undefined')); - }); - describe('urls', function() { + it('should be defined', function() { - it('should build resources url with resources name', function() { + expect(provider.$get).toBeDefined(); + expect(provider.setOptions).toBeDefined(); + expect(provider.getOptions().headers[AV_API.HEADERS.CLIENT.RESPONSE_ENCODING]).toBe('HTML'); + }); - var users = new AvApiResource('users'); + describe('AvApiResource', function() { - expect(users).toBeObject(); - expect(users._getUrl()).toBe('/api/v1/users'); + var responseData = [{a: 1, b: 2},{a: 1, b: 2}]; + it('should not allow options to be null', function() { + expect(function() { new AvApiResource(); }).toThrow(new Error('[options] cannot be null or undefined')); }); - it('should build resources url with resources url', function() { + describe('urls', function() { - var users = new AvApiResource('/users'); + it('should build resources url with resources name', function() { - expect(users._getUrl()).toBe('/api/v1/users'); + var users = new AvApiResource('users'); - }); - - it('should build resources url using options.url', function() { + expect(users).toBeObject(); + expect(users._getUrl()).toBe('/api/v1/users'); - var users = new AvApiResource({ - url: '/users' }); - expect(users._getUrl()).toBe('/api/v1/users'); - }); + it('should build resources url with resources url', function() { - it('should build resources url with options.prefix', function() { + var users = new AvApiResource('/users'); - var users = new AvApiResource({ - prefix: '/public', - url: '/users' - }); + expect(users._getUrl()).toBe('/api/v1/users'); - expect(users._getUrl()).toBe('/public/api/v1/users'); + }); - }); + it('should build resources url using options.url', function() { - it('should build resources url with options.level a.k.a. /internal', function() { + var users = new AvApiResource({ + url: '/users' + }); - var users = new AvApiResource({ - level: '/internal', - url: '/users' + expect(users._getUrl()).toBe('/api/v1/users'); }); - expect(users._getUrl()).toBe('/api/internal/v1/users'); + it('should build resources url with options.prefix', function() { - }); + var users = new AvApiResource({ + prefix: '/public', + url: '/users' + }); - it('should build resources url with suffix', function() { + expect(users._getUrl()).toBe('/public/api/v1/users'); - var users = new AvApiResource({ - url: '/users', - suffix: '.json' }); - expect(users._getUrl()).toBe('/api/v1/users.json'); + it('should build resources url with options.level a.k.a. /internal', function() { - }); + var users = new AvApiResource({ + level: '/internal', + url: '/users' + }); - it('should build resources with `public` and `internal` and resourceGroup `foo` and version 2', function() { + expect(users._getUrl()).toBe('/api/internal/v1/users'); - var users = new AvApiResource({ - prefix: '/public', - url: '/users', - version: '/v2', - level: '/internal', - resourceGroup: '/foo' }); - expect(users._getUrl()).toBe('/public/api/internal/foo/v2/users'); + it('should build resources url with suffix', function() { - }); + var users = new AvApiResource({ + url: '/users', + suffix: '.json' + }); - it('should build resource url with path parameters missing slash "/" character', function() { + expect(users._getUrl()).toBe('/api/v1/users.json'); - var api1 = new AvApiResource({ - version: '/v1', - level: 'utils', - url: 'users' }); - var api2 = new AvApiResource({ - version: 'v1', - level: 'utils', - url: 'users' - }); + it('should build resources with `public` and `internal` and resourceGroup `foo` and version 2', function() { - expect(api1._getUrl()).toBe('/api/utils/v1/users'); - expect(api2._getUrl()).toBe('/api/utils/v1/users'); + var users = new AvApiResource({ + prefix: '/public', + url: '/users', + version: '/v2', + level: '/internal', + resourceGroup: '/foo' + }); - }); + expect(users._getUrl()).toBe('/public/api/internal/foo/v2/users'); - it('should build resources url using relative path that is not API url', function() { - var users = new AvApiResource({ - url: '/availity/JwsServlet', - api: false }); - expect(users._getUrl()).toBe('/availity/JwsServlet'); + it('should build resource url with path parameters missing slash "/" character', function() { - }); - }); + var api1 = new AvApiResource({ + version: '/v1', + level: 'utils', + url: 'users' + }); - describe('rest', function() { + var api2 = new AvApiResource({ + version: 'v1', + level: 'utils', + url: 'users' + }); - var users; + expect(api1._getUrl()).toBe('/api/utils/v1/users'); + expect(api2._getUrl()).toBe('/api/utils/v1/users'); - beforeEach(function() { - users = new AvApiResource('users'); - }); + }); - describe('query()', function() { + it('should build resources url using relative path that is not API url', function() { + var users = new AvApiResource({ + url: '/availity/JwsServlet', + api: false + }); - it('should get list of resources', function() { + expect(users._getUrl()).toBe('/availity/JwsServlet'); - // expectGET to make sure this is called once. - $httpBackend.expectGET('/api/v1/users').respond(200, responseData); + }); + }); - users.query().success(function(data) { - expect(data).toBeEqual(responseData); - }); + describe('rest', function() { - $httpBackend.flush(); + var users; + + beforeEach(function() { + users = new AvApiResource('users'); }); - it('should get list of resources with params', function() { + describe('query()', function() { - // expectGET to make sure this is called once. - $httpBackend.expectGET('/api/v1/users?a=1&b=2').respond(200, responseData); + it('should get list of resources', function() { - users.query({params: {a:1, b:2}}).success(function(data) { - expect(data).toBeEqual(responseData); - callback(); - }); + // expectGET to make sure this is called once. + $httpBackend.expectGET('/api/v1/users').respond(200, responseData); - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); + users.query().success(function(data) { + expect(data).toBeEqual(responseData); + }); - }); + $httpBackend.flush(); + }); - it('should have a cacheBust parameter when cacheBust is true', function() { - $httpBackend.expectGET(/\/api\/v1\/users\?cacheBust=\d+/).respond(200, responseData); + it('should get list of resources with params', function() { - users.query({cacheBust:true}).success(function(data) { - expect(data).toBeEqual(responseData); - callback(); - }); + // expectGET to make sure this is called once. + $httpBackend.expectGET('/api/v1/users?a=1&b=2').respond(200, responseData); - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); - }); + users.query({params: {a:1, b:2}}).success(function(data) { + expect(data).toBeEqual(responseData); + callback(); + }); - it('should have a cacheBust parameter with other parameters', function() { - $httpBackend.expectGET(/\/api\/v1\/users\?a=1&b=2&cacheBust=\d+/).respond(200, responseData); + $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); - users.query({params: {a:1, b:2}, cacheBust:true}).success(function(data) { - expect(data).toBeEqual(responseData); - callback(); }); - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); - }); + it('should have a cacheBust parameter when cacheBust is true', function() { + $httpBackend.expectGET(/\/api\/v1\/users\?cacheBust=\d+/).respond(200, responseData); - }); - - describe('get()', function() { + users.query({cacheBust:true}).success(function(data) { + expect(data).toBeEqual(responseData); + callback(); + }); - it('should get a single resource by id', function() { - $httpBackend.expectGET('/api/v1/users/1').respond(200, responseData); - - users.get(1).success(function(data) { - expect(data).toBeEqual(responseData); - callback(); + $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); }); - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); - }); + it('should have a cacheBust parameter with other parameters', function() { + $httpBackend.expectGET(/\/api\/v1\/users\?a=1&b=2&cacheBust=\d+/).respond(200, responseData); - it('should have a cacheBust parameter when cacheBust is true', function() { - $httpBackend.expectGET(/\/api\/v1\/users\/1\?cacheBust=\d+/).respond(200, responseData); + users.query({params: {a:1, b:2}, cacheBust:true}).success(function(data) { + expect(data).toBeEqual(responseData); + callback(); + }); - users.get(1, {cacheBust: true}).success(function(data) { - expect(data).toBeEqual(responseData); - callback(); + $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); }); - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); }); - }); - describe('update()', function () { + describe('get()', function() { - var updateResponseData = {id: 1, foo: 'bar'}; + it('should get a single resource by id', function() { + $httpBackend.expectGET('/api/v1/users/1').respond(200, responseData); - it('should update a single resource by id', function () { + users.get(1).success(function(data) { + expect(data).toBeEqual(responseData); + callback(); + }); - $httpBackend.expectPUT('/api/v1/users/1').respond(200, updateResponseData); - - users.update(1, {}).success(function (data) { - expect(data).toBeEqual(updateResponseData); - callback(); + $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); }); - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); - }); + it('should have a cacheBust parameter when cacheBust is true', function() { + $httpBackend.expectGET(/\/api\/v1\/users\/1\?cacheBust=\d+/).respond(200, responseData); - it('should update a single entity WITHOUT an id', function () { + users.get(1, {cacheBust: true}).success(function(data) { + expect(data).toBeEqual(responseData); + callback(); + }); - $httpBackend.expectPUT('/api/v1/users').respond(200, updateResponseData); + $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); + }); + }); - var _request = spyOn(users, '_request').and.callThrough(); + describe('update()', function () { - var data = { id: 1 }; - var config = { headers: { 'MyHeader': 'MyValue' } }; - users.update(data, config).success(function(result) { - expect(result).toBeEqual(updateResponseData); - callback(); - }); + var updateResponseData = {id: 1, foo: 'bar'}; - $httpBackend.flush(); - expect(callback).toHaveBeenCalled(); + it('should update a single resource by id', function () { - config = users._config(config); - config.method = 'PUT'; - config.url = users._getUrl(); - config.data = data; + $httpBackend.expectPUT('/api/v1/users/1').respond(200, updateResponseData); - expect(_request).toHaveBeenCalled(); - expect(_request).toHaveBeenCalledWith(config, null); - }); + users.update(1, {}).success(function (data) { + expect(data).toBeEqual(updateResponseData); + callback(); + }); - describe('remove()', function() { + $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); + }); - it('should remove entities WITHOUT an id', function () { + it('should update a single entity WITHOUT an id', function () { - $httpBackend.expectDELETE('/api/v1/users').respond({}); + $httpBackend.expectPUT('/api/v1/users').respond(200, updateResponseData); var _request = spyOn(users, '_request').and.callThrough(); var data = { id: 1 }; var config = { headers: { 'MyHeader': 'MyValue' } }; - users.remove(data, config); + users.update(data, config).success(function(result) { + expect(result).toBeEqual(updateResponseData); + callback(); + }); $httpBackend.flush(); + expect(callback).toHaveBeenCalled(); config = users._config(config); - config.method = 'DELETE'; + config.method = 'PUT'; config.url = users._getUrl(); config.data = data; expect(_request).toHaveBeenCalled(); expect(_request).toHaveBeenCalledWith(config, null); }); + + describe('remove()', function() { + + it('should remove entities WITHOUT an id', function () { + + $httpBackend.expectDELETE('/api/v1/users').respond({}); + + var _request = spyOn(users, '_request').and.callThrough(); + + var data = { id: 1 }; + var config = { headers: { 'MyHeader': 'MyValue' } }; + users.remove(data, config); + + $httpBackend.flush(); + + config = users._config(config); + config.method = 'DELETE'; + config.url = users._getUrl(); + config.data = data; + + expect(_request).toHaveBeenCalled(); + expect(_request).toHaveBeenCalledWith(config, null); + }); + }); + }); }); - }); + describe('callbacks', function() { - describe('callbacks', function() { + var Users; + var users; - var Users; - var users; + var queryCallback = jasmine.createSpy('queryCallback'); + var beforeCreateCallback = jasmine.createSpy('beforeCreateCallback'); + var afterCreateCallback = jasmine.createSpy('afterCreateCallback'); + var updateCallback = jasmine.createSpy('updateCallback'); + var removeCallback = jasmine.createSpy('removeCallback'); - var queryCallback = jasmine.createSpy('queryCallback'); - var beforeCreateCallback = jasmine.createSpy('beforeCreateCallback'); - var afterCreateCallback = jasmine.createSpy('afterCreateCallback'); - var updateCallback = jasmine.createSpy('updateCallback'); - var removeCallback = jasmine.createSpy('removeCallback'); + beforeEach(function() { - beforeEach(function() { + Users = function() { + AvApiResource.call(this,{ + url: '/users' + }); + }; - Users = function() { - AvApiResource.call(this,{ - url: '/users' + angular.extend(Users.prototype, AvApiResource.prototype, { + afterQuery: queryCallback, + beforeCreate: beforeCreateCallback, + afterCreate: afterCreateCallback, + beforeUpdate: updateCallback, + afterUpdate: updateCallback, + afterRemove: removeCallback }); - }; - - angular.extend(Users.prototype, AvApiResource.prototype, { - afterQuery: queryCallback, - beforeCreate: beforeCreateCallback, - afterCreate: afterCreateCallback, - beforeUpdate: updateCallback, - afterUpdate: updateCallback, - afterRemove: removeCallback + + + users = new Users(); }); + it('should call afterGet() after promise returns from resource.get()', function() { - users = new Users(); - }); + Users.prototype.afterGet = function(response) { + response.data[0].a = 2; + return response; + }; - it('should call afterGet() after promise returns from resource.get()', function() { + spyOn(users, 'afterGet').and.callThrough(); - Users.prototype.afterGet = function(response) { - response.data[0].a = 2; - return response; - }; + $httpBackend.expectGET('/api/v1/users/1').respond(200, responseData); - spyOn(users, 'afterGet').and.callThrough(); + var transformedResponse = [{a: 2, b: 2 },{a: 1, b: 2 }]; - $httpBackend.expectGET('/api/v1/users/1').respond(200, responseData); + users.get(1).success(function(data) { + expect(data).toBeEqual(transformedResponse); + }); + $httpBackend.flush(); - var transformedResponse = [{a: 2, b: 2 },{a: 1, b: 2 }]; + expect(users.afterGet).toHaveBeenCalled(); + expect(users.afterGet.calls.count()).toEqual(1); - users.get(1).success(function(data) { - expect(data).toBeEqual(transformedResponse); + Users.prototype.afterGet = null; }); - $httpBackend.flush(); - expect(users.afterGet).toHaveBeenCalled(); - expect(users.afterGet.calls.count()).toEqual(1); + it('should call afterQuery() after promise returns from resource.query()', function() { - Users.prototype.afterGet = null; - }); + $httpBackend.expectGET('/api/v1/users').respond(200, responseData); - it('should call afterQuery() after promise returns from resource.query()', function() { + expect(queryCallback.calls.count()).toEqual(0); - $httpBackend.expectGET('/api/v1/users').respond(200, responseData); + users.query(); + $httpBackend.flush(); - expect(queryCallback.calls.count()).toEqual(0); + expect(queryCallback).toHaveBeenCalled(); + expect(queryCallback.calls.count()).toEqual(1); + }); - users.query(); - $httpBackend.flush(); + it('should call beforeCreate() and afterCreate() on resource.create()', function() { - expect(queryCallback).toHaveBeenCalled(); - expect(queryCallback.calls.count()).toEqual(1); - }); + $httpBackend.expectPOST('/api/v1/users').respond(200, responseData); - it('should call beforeCreate() and afterCreate() on resource.create()', function() { + expect(beforeCreateCallback.calls.count()).toEqual(0); + expect(afterCreateCallback.calls.count()).toEqual(0); - $httpBackend.expectPOST('/api/v1/users').respond(200, responseData); + var data = { + 'firstName': 'Rob', + 'lastName': 'McGuinness' + }; - expect(beforeCreateCallback.calls.count()).toEqual(0); - expect(afterCreateCallback.calls.count()).toEqual(0); + users.beforeCreate = beforeCreateCallback.and.returnValue(data); - var data = { - 'firstName': 'Rob', - 'lastName': 'McGuinness' - }; + users.create(data); + $httpBackend.flush(); - users.beforeCreate = beforeCreateCallback.and.returnValue(data); + expect(beforeCreateCallback).toHaveBeenCalled(); + expect(beforeCreateCallback).toHaveBeenCalledWith(data); + expect(beforeCreateCallback.calls.count()).toEqual(1); + expect(afterCreateCallback).toHaveBeenCalled(); + expect(afterCreateCallback.calls.argsFor(0).length).toEqual(2); + expect(afterCreateCallback.calls.argsFor(0)[1]).toEqual(data); + expect(afterCreateCallback.calls.count()).toEqual(1); + }); - users.create(data); - $httpBackend.flush(); + it('should call afterRemove() on resource.remove()', function() { - expect(beforeCreateCallback).toHaveBeenCalled(); - expect(beforeCreateCallback).toHaveBeenCalledWith(data); - expect(beforeCreateCallback.calls.count()).toEqual(1); - expect(afterCreateCallback).toHaveBeenCalled(); - expect(afterCreateCallback.calls.argsFor(0).length).toEqual(2); - expect(afterCreateCallback.calls.argsFor(0)[1]).toEqual(data); - expect(afterCreateCallback.calls.count()).toEqual(1); - }); + $httpBackend.expectDELETE('/api/v1/users/1').respond(200, responseData); - it('should call afterRemove() on resource.remove()', function() { + expect(removeCallback.calls.count()).toEqual(0); - $httpBackend.expectDELETE('/api/v1/users/1').respond(200, responseData); + users.remove(1); + $httpBackend.flush(); - expect(removeCallback.calls.count()).toEqual(0); + expect(removeCallback).toHaveBeenCalled(); + expect(removeCallback.calls.count()).toEqual(1); + }); - users.remove(1); - $httpBackend.flush(); + it('should call beforeUpdate() and afterUpdate() during resource.update()', function() { - expect(removeCallback).toHaveBeenCalled(); - expect(removeCallback.calls.count()).toEqual(1); - }); + $httpBackend.whenPUT('/api/v1/users/1').respond(200, responseData); - it('should call beforeUpdate() and afterUpdate() during resource.update()', function() { + expect(updateCallback.calls.count()).toEqual(0); - $httpBackend.whenPUT('/api/v1/users/1').respond(200, responseData); + users.update(1, { + 'firstName': 'Rob', + 'lastName': 'McGuinness' + }); - expect(updateCallback.calls.count()).toEqual(0); + $httpBackend.flush(); - users.update(1, { - 'firstName': 'Rob', - 'lastName': 'McGuinness' + expect(updateCallback).toHaveBeenCalled(); + expect(updateCallback.calls.count()).toEqual(2); }); - $httpBackend.flush(); - - expect(updateCallback).toHaveBeenCalled(); - expect(updateCallback.calls.count()).toEqual(2); }); }); + + + + });