import {appConfig} from 'appConfig'; import {ISuperdeskGlobalConfig} from 'superdesk-api'; import _ from 'lodash'; function collection(data) { return {_items: data}; } var USER_URL = 'http://localhost/users/1', USER_PATH = '/users/1', USERS_URL = 'http://localhost/users', SERVER_URL = 'http://localhost', ETAG = 'xyz'; function testEtagHeader(headers) { return headers['If-Match'] === ETAG; } var HTTP_API = { type: 'http', service: function() { this.queryLog = []; var query = this.query; this.query = function(criteria) { this.queryLog.push(criteria); return query.call(this, criteria); }; this.ping = function() { return 'pong'; }; }, backend: { rel: 'users', headers: {'X-Filter': 'User.*'}, }, }; function doConfig() { const testConfig: Partial = {server: {url: SERVER_URL, ws: undefined}}; Object.assign(appConfig, testConfig); } describe('API Provider', () => { beforeEach(window.module(doConfig)); beforeEach(window.module('superdesk.core.api')); beforeEach(() => { angular.module('superdesk.core.api') .config(['apiProvider', (apiProvider) => { apiProvider.api('http', HTTP_API); }]); }); it('exists', inject((api) => { expect(api).toBeDefined(); })); it('can register apis', inject((api) => { expect(api.http).toBeDefined(); })); it('can override backend methods', inject((api, $rootScope) => { expect(api.http.queryLog.length).toBe(0); api.http.query(); expect(api.http.queryLog.length).toBe(1); })); it('can define new methods', inject((api) => { expect(api.http.ping()).toBe('pong'); })); describe('HTTP API Endpoint', () => { afterEach(inject(($httpBackend) => { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); })); it('can query', inject((api, urls, $q, $httpBackend, $http) => { var headers = $http.defaults.headers.common; headers['X-Filter'] = 'User.*'; spyOn(urls, 'resource').and.returnValue($q.when(USERS_URL)); $httpBackend.expectGET(USERS_URL, headers).respond(collection([{}])); var users; api.http.query().then((_users) => { users = _users; }); $httpBackend.flush(); expect(users._items.length).toBe(1); expect(urls.resource).toHaveBeenCalledWith('users'); })); it('rejects on query error', inject((api, urls, $q, $httpBackend) => { $httpBackend.expectGET(USERS_URL).respond(400); spyOn(urls, 'resource').and.returnValue($q.when(USERS_URL)); var reject; api.http.query().then(null, (reason) => { reject = true; }); $httpBackend.flush(); expect(reject).toBe(true); })); it('can create new resource', inject((api, urls, $q, $httpBackend) => { var userData = {username: 'test'}, user; spyOn(urls, 'resource').and.returnValue($q.when(USERS_URL)); $httpBackend.expectPOST(USERS_URL, userData).respond(201, {_links: {self: {href: 'user_href'}}}); api.http.save({username: 'test'}).then((_user) => { user = _user; }); $httpBackend.flush(); expect(user._links.self.href).toBe('user_href'); expect(urls.resource).toHaveBeenCalledWith('users'); })); it('can fail creating new resource', inject((api, urls, $q, $httpBackend) => { var userData = {username: 'test'}; spyOn(urls, 'resource').and.returnValue($q.when(USERS_URL)); $httpBackend.expectPOST(USERS_URL, userData).respond(200, { _status: 'ERR', _issues: {first_name: {required: 1}}, }); var test = null; api.http.save({username: 'test'}).then((response) => { test = true; }, (response) => { test = false; }); $httpBackend.flush(); expect(test).toBe(false); })); it('can create new with diff', inject((api, urls, $q, $httpBackend) => { var user: any = {}, data = {username: 'test'}; spyOn(urls, 'resource').and.returnValue($q.when(USERS_URL)); $httpBackend.expectPOST(USERS_URL, data).respond(201, {_links: {self: {href: 'user_href'}}}); api.http.save(user, data); $httpBackend.flush(); expect(user.username).toBe('test'); expect(urls.resource).toHaveBeenCalledWith('users'); })); it('can update endpoint', inject((api, $httpBackend) => { var user; var userData = { _links: {self: {href: USER_PATH}}, _id: 2, username: 'test', Avatar: {href: 'test'}, }; $httpBackend.expectPATCH(USER_URL, {username: 'test', Avatar: {href: 'test'}}).respond(200); api.http.save(userData).then((_user) => { user = _user; }); $httpBackend.flush(); expect(user.username).toBe('test'); expect(user._links.self.href).toBe(USER_PATH); })); it('can update with diff', inject((api, $httpBackend) => { var userData = {_links: {self: {href: USER_PATH}}, _id: 2, username: 'test'}, diff = {Active: false}; $httpBackend.expectPATCH(USER_URL, diff).respond({}); api.http.save(userData, diff); $httpBackend.flush(); })); it('can delete', inject((api, $httpBackend) => { var user = {_links: {self: {href: USER_PATH}}}, then = jasmine.createSpy('then'); $httpBackend.expectDELETE(USER_URL).respond(204); api.http.remove(user).then(then); $httpBackend.flush(); expect(then).toHaveBeenCalled(); })); it('handles delete on deleted resource as success', inject((api, $httpBackend) => { var user = {_links: {self: {href: USER_PATH}}}, then = jasmine.createSpy('then'); $httpBackend.expectDELETE(USER_URL).respond(404); api.http.remove(user).then(then); $httpBackend.flush(); expect(then).toHaveBeenCalled(); })); it('rejects other delete errors as errors', inject((api, $httpBackend) => { var user = {_links: {self: {href: USER_PATH}}}, success = jasmine.createSpy('success'), error = jasmine.createSpy('error'); $httpBackend.expectDELETE(USER_URL).respond(405); api.http.remove(user).then(success, error); $httpBackend.flush(); expect(success).not.toHaveBeenCalled(); expect(error).toHaveBeenCalled(); })); it('can get item by url', inject((api, $httpBackend) => { var user; $httpBackend.expectGET(USER_URL).respond({username: 'foo'}); api.http.getByUrl(USER_PATH).then((_user) => { user = _user; }); $httpBackend.flush(); expect(user.username).toBe('foo'); })); it('can get item by id', inject((api, urls, $q, $httpBackend) => { var user; spyOn(urls, 'resource').and.returnValue($q.when(SERVER_URL + '/users')); $httpBackend.expectGET(SERVER_URL + '/users/1').respond({username: 'foo'}); api.http.getById(1).then((_user) => { user = _user; }); $httpBackend.flush(); expect(user.username).toBe('foo'); expect(urls.resource).toHaveBeenCalledWith('users'); })); it('can replace resource on given dest', inject((api, $httpBackend) => { var data = {username: 'foo'}; $httpBackend.expectPUT(USER_URL, data).respond({}); api.http.replace(USER_PATH, data); $httpBackend.flush(); })); it('rejects non success responses', inject((api, $httpBackend) => { $httpBackend.expectGET(USER_URL).respond(400); var success = jasmine.createSpy('success'), error = jasmine.createSpy('error'); api.http.getByUrl(USER_PATH).then(success, error); $httpBackend.flush(); expect(success).not.toHaveBeenCalled(); expect(error).toHaveBeenCalled(); })); it('can get resource url', inject((api, urls, $q, $rootScope) => { var url; spyOn(urls, 'resource').and.returnValue($q.when(USERS_URL)); api.http.getUrl().then((_url) => { url = _url; }); $rootScope.$digest(); expect(url).toBe(USERS_URL); expect(urls.resource).toHaveBeenCalledWith('users'); })); it('can get resource headers', inject((api) => { expect(api.http.getHeaders()['X-Filter']).toBe('User.*'); })); }); describe('new api service', () => { afterEach(inject(($httpBackend) => { $httpBackend.verifyNoOutstandingExpectation(); $httpBackend.verifyNoOutstandingRequest(); })); beforeEach(inject(($httpBackend) => { $httpBackend.whenGET(SERVER_URL).respond(200, { _links: {child: [ {title: 'users', href: '/users'}, {title: 'workspace', href: '/users//workspace'}, ]}, }); })); it('can create', inject((api, $httpBackend) => { var user: any = {name: 'foo'}; $httpBackend.expectPOST(USERS_URL, user).respond(201, {_id: 1}); api('users').save(user); $httpBackend.flush(); expect(user._id).toBe(1); })); it('can update', inject((api, $httpBackend) => { var user = {_id: 1, _links: {self: {href: USER_PATH}}, name: 'foo', _etag: ETAG}; var diff = {name: 'bar'}; $httpBackend.expectPATCH(USER_URL, diff, testEtagHeader).respond(200, {name: 'bar', _type: 'user'}); api('users').save(user, diff); $httpBackend.flush(); expect(user.name).toBe('bar'); expect(_.has(user, '_type')).toBe(false); $httpBackend.expectPATCH(USER_URL, {foo: 1}, testEtagHeader).respond(200, {}); api('users').save(user, {foo: 1, _type: 'user'}); $httpBackend.flush(); $httpBackend.verifyNoOutstandingExpectation(); })); it('can query resource', inject((api, $httpBackend) => { $httpBackend.expectGET(USERS_URL + '?limit=1').respond(200, {_items: []}); var users; api('users').query({limit: 1}) .then((_users) => { users = _users; }); $httpBackend.flush(); expect(users._items.length).toBe(0); })); it('can query subresource', inject((api, $httpBackend) => { var user = {_id: 1}; $httpBackend.expectGET(USER_URL + '/workspace').respond(200, {}); api('workspace', user).query(); $httpBackend.flush(); })); it('rejects on status error', inject((api, $httpBackend) => { $httpBackend.expectGET(USERS_URL).respond(400); var success = jasmine.createSpy('success'), error = jasmine.createSpy('error'); api('users').query() .then(success, error); $httpBackend.flush(); expect(success).not.toHaveBeenCalled(); expect(error).toHaveBeenCalled(); })); it('rejects on data error', inject((api, $httpBackend) => { $httpBackend.expectPOST(USERS_URL).respond(200, {_status: 'ERR'}); var success = jasmine.createSpy('success'), error = jasmine.createSpy('error'); api('users') .save({}) .then(success, error); $httpBackend.flush(); expect(success).not.toHaveBeenCalled(); expect(error).toHaveBeenCalled(); })); it('cleans data before saving it', inject((api, $httpBackend) => { $httpBackend.expectPOST(USERS_URL, {name: 'foo', _id: 1}).respond(200, {}); api('users').save({name: 'foo', _created: 'now', _updated: 'now', _id: 1}); $httpBackend.flush(); })); it('can fetch an item by id', inject((api, $httpBackend) => { var data = {_id: 1}, user; $httpBackend.expectGET(USER_URL).respond(200, data); api('users').getById(1) .then((_user) => { user = _user; }); $httpBackend.flush(); expect(user._id).toBe(1); })); it('can remove an item', inject((api, $httpBackend) => { var user = {_links: {self: {href: USER_PATH}}, _etag: ETAG}; $httpBackend.expectDELETE(USER_URL, testEtagHeader).respond(200); api('users').remove(user); $httpBackend.flush(); })); it('can get a given url', inject((api, $httpBackend) => { $httpBackend.expectGET(USER_URL).respond(200, {}); api.get(USER_PATH); $httpBackend.flush(); })); it('can update given resource', inject((api, $httpBackend) => { var data = {name: 'foo'}; $httpBackend.expectPATCH(USER_URL, data).respond(200); api.update('users', {_id: 1}, data); $httpBackend.flush(); })); it('can clean diff data for update', inject((api, $httpBackend) => { var user = {_links: {self: {href: USER_PATH}}, username: 'foo'}; var diff = Object.create(user); diff.last_name = false; $httpBackend.expectPATCH(USER_URL, {last_name: false}).respond(200, {}); api.save('users', user, diff); $httpBackend.flush(); })); }); });