diff --git a/static_src/actions/user_actions.js b/static_src/actions/user_actions.js index f574e86a..13a4de62 100644 --- a/static_src/actions/user_actions.js +++ b/static_src/actions/user_actions.js @@ -13,6 +13,10 @@ import OrgStore from '../stores/org_store'; import SpaceStore from '../stores/space_store'; const ORG_NAME = OrgStore.cfName; +const MSG_USER_HAS_SPACE_ROLES = 'This user can\'t be removed because they still have a space ' + + 'role within the organization. Please remove all space ' + + 'associations before removing this user from the organization. ' + + 'To review how, click the "Managing Teammates" link below.'; const userActions = { fetchOrgUsers(orgGuid) { @@ -60,12 +64,55 @@ const userActions = { }); }, + receivedOrgSpacesToExtractSpaceUsers(orgSpaces) { + const orgSpaceUsers = orgSpaces.map((orgSpace) => Promise.resolve( + cfApi.fetchSpaceUserRoles(orgSpace.guid) + )); + return Promise.all(orgSpaceUsers); + }, + + fetchUserAssociationsToOrgSpaces(userGuid, orgGuid) { + return Promise.resolve(cfApi.fetchAllOrgSpaces(orgGuid)) + .then((orgSpaces) => userActions.receivedOrgSpacesToExtractSpaceUsers(orgSpaces)); + }, + + deleteUserOrDisplayNotice(spaceUsers, userGuid, orgGuid) { + const usersSpaces = spaceUsers.filter(spaceUser => spaceUser.guid === userGuid); + if (usersSpaces.length > 0) { + userActions.createUserSpaceAssociationNotification(MSG_USER_HAS_SPACE_ROLES); + } else { + userActions.deleteUser(userGuid, orgGuid); + } + }, + + deleteUserIfNoSpaceAssociation(userGuid, orgGuid) { + return Promise.resolve(userActions.fetchUserAssociationsToOrgSpaces(userGuid, orgGuid)) + .then((spaceUsers) => userActions.deleteUserOrDisplayNotice(spaceUsers, userGuid, orgGuid)); + }, + deleteUser(userGuid, orgGuid) { AppDispatcher.handleViewAction({ type: userActionTypes.USER_DELETE, userGuid, orgGuid }); + + return cfApi.deleteUser(userGuid, orgGuid) + .then(() => userActions.deletedUser(userGuid, orgGuid)) + .catch(error => { + // Check whether we got caught on user roles in spaces + const userHasSpaceRoles = (error && + error.response && + error.response.status === 400 && + error.response.data.error_code === 'CF-AssociationNotEmpty' + ); + if (userHasSpaceRoles) { + this.createUserSpaceAssociationNotification(MSG_USER_HAS_SPACE_ROLES); + } else { + // else use generic error + this.errorRemoveUser(userGuid, error.response.data); + } + }); }, deletedUser(userGuid, orgGuid) { @@ -198,12 +245,24 @@ const userActions = { inviting ${email}`)); }, - clearInviteNotifications() { + clearUserListNotifications() { AppDispatcher.handleViewAction({ - type: userActionTypes.USER_INVITE_STATUS_DISMISSED + type: userActionTypes.USER_LIST_NOTICE_DISMISSED }); }, + createUserListNotification(noticeType, description) { + AppDispatcher.handleViewAction({ + type: userActionTypes.USER_LIST_NOTICE_CREATED, + noticeType, + description + }); + }, + + createUserSpaceAssociationNotification(notification) { + userActions.createUserListNotification('error', notification); + }, + createInviteNotification(verified, email) { let description; const noticeType = 'finish'; @@ -223,14 +282,10 @@ const userActions = { 'be controlled below.'; } - AppDispatcher.handleViewAction({ - type: userActionTypes.USER_INVITE_STATUS_DISPLAYED, - noticeType, - description - }); + userActions.createUserListNotification(noticeType, description); }, - userInviteError(err, contextualMessage) { + userListNoticeError(err, contextualMessage) { AppDispatcher.handleServerAction({ type: userActionTypes.USER_INVITE_ERROR, err, diff --git a/static_src/components/users.jsx b/static_src/components/users.jsx index dc02dad1..7cb1063d 100644 --- a/static_src/components/users.jsx +++ b/static_src/components/users.jsx @@ -55,8 +55,8 @@ function stateSetter() { loading: UserStore.loading, empty: !UserStore.loading && !users.length, users, - inviteNotices: UserStore._inviteNotification, - userInviteError: UserStore.getInviteError() + userListNotices: UserStore._userListNotification, + userListNoticeError: UserStore.getUserListNotificationError() }; } @@ -82,7 +82,7 @@ export default class Users extends React.Component { onNotificationDismiss(ev) { ev.preventDefault(); - userActions.clearInviteNotifications(); + userActions.clearUserListNotifications(); } handleAddPermissions(roleKey, apiKey, userGuid) { @@ -143,14 +143,14 @@ export default class Users extends React.Component { let notification; let userInvite; - if (this.state.inviteNotices.description) { - const notice = this.state.inviteNotices; + if (this.state.userListNotices.description) { + const notice = this.state.userListNotices; notification = ( ); } else { @@ -164,7 +164,7 @@ export default class Users extends React.Component { ); diff --git a/static_src/constants.js b/static_src/constants.js index eee0c63e..d3231549 100644 --- a/static_src/constants.js +++ b/static_src/constants.js @@ -258,6 +258,8 @@ const userActionTypes = keymirror({ USER_INVITE_TRIGGER: null, // Action to trigger when invite status is triggered for front end. USER_INVITE_STATUS_UPDATED: null, + // Action to trigger when user list notice is created. + USER_LIST_NOTICE_CREATED: null, // Action to trigger email sent to user with cloud.gov invite url. USER_ORG_ASSOCIATE: null, // Action to associate user to organization on the server. @@ -266,10 +268,8 @@ const userActionTypes = keymirror({ USER_ASSOCIATED_ORG_DISPLAYED: null, // Action when something goes wrong in user invite and email process. USER_INVITE_ERROR: null, - // Action to display an invite notification - USER_INVITE_STATUS_DISPLAYED: null, - // Action to dismiss an invite notification - USER_INVITE_STATUS_DISMISSED: null, + // Action to dismiss an user list notification. + USER_LIST_NOTICE_DISMISSED: null, // Action to delete a user from an org. USER_DELETE: null, // Action when a user was deleted from an org on the server. diff --git a/static_src/stores/user_store.js b/static_src/stores/user_store.js index ad3e5fdf..18520812 100644 --- a/static_src/stores/user_store.js +++ b/static_src/stores/user_store.js @@ -21,7 +21,7 @@ export class UserStore extends BaseStore { this._error = null; this._saving = false; this._inviteDisabled = false; - this._inviteNotification = {}; + this._userListNotification = {}; this._loading = {}; } @@ -64,7 +64,7 @@ export class UserStore extends BaseStore { case userActionTypes.USER_INVITE_TRIGGER: { this._inviteDisabled = true; - this._inviteError = null; + this._userListNotificationError = null; this.emitChange(); break; } @@ -153,15 +153,7 @@ export class UserStore extends BaseStore { } case userActionTypes.USER_DELETE: { - const orgPermissionsReq = cfApi.deleteOrgUserPermissions( - action.userGuid, - action.orgGuid, - 'users'); - - orgPermissionsReq.then(() => { - cfApi.deleteUser(action.userGuid, action.orgGuid); - }); - + // Nothing should happen. break; } @@ -179,7 +171,7 @@ export class UserStore extends BaseStore { } case userActionTypes.USER_INVITE_ERROR: { - this._inviteError = Object.assign({}, action.err, { + this._userListNotificationError = Object.assign({}, action.err, { contextualMessage: action.contextualMessage }); this._inviteDisabled = false; @@ -197,18 +189,18 @@ export class UserStore extends BaseStore { break; } - case userActionTypes.USER_INVITE_STATUS_DISPLAYED: { + case userActionTypes.USER_LIST_NOTICE_CREATED: { this._inviteDisabled = false; const noticeType = action.noticeType; const description = action.description; const notice = Object.assign({}, { noticeType }, { description }); - this._inviteNotification = notice; + this._userListNotification = notice; this.emitChange(); break; } - case userActionTypes.USER_INVITE_STATUS_DISMISSED: { - this._inviteNotification = {}; + case userActionTypes.USER_LIST_NOTICE_DISMISSED: { + this._userListNotification = {}; this.emitChange(); break; } @@ -285,8 +277,8 @@ export class UserStore extends BaseStore { case errorActionTypes.CLEAR: { this._error = null; this._saving = false; - this._inviteNotification = {}; - this._inviteError = null; + this._userListNotification = {}; + this._userListNotificationError = null; this._loading = {}; this.emitChange(); break; @@ -367,12 +359,12 @@ export class UserStore extends BaseStore { return this._currentUserIsAdmin; } - getInviteNotification() { - return this._inviteNotification; + getUserListNotification() { + return this._userListNotification; } - getInviteError() { - return this._inviteError; + getUserListNotificationError() { + return this._userListNotificationError; } get isSaving() { diff --git a/static_src/test/unit/actions/user_actions.spec.js b/static_src/test/unit/actions/user_actions.spec.js index 545ae726..d91dc573 100644 --- a/static_src/test/unit/actions/user_actions.spec.js +++ b/static_src/test/unit/actions/user_actions.spec.js @@ -119,22 +119,254 @@ describe('userActions', function() { }); }); + describe('receivedOrgSpacesToExtractSpaceUsers()', function() { + let orgSpace; + let orgSpaces; + + beforeEach(function () { + orgSpace = { guid: 'org-guid-this-is'}; + + sandbox.stub(cfApi, 'fetchSpaceUserRoles') + .returns(Promise.resolve({ guid: '' })); + }); + + it('calls receivedOrgSpacesToExtractSpaceUsers once when org has one space', function (done) { + orgSpaces = [orgSpace]; + userActions.receivedOrgSpacesToExtractSpaceUsers(orgSpaces).then(done, done.fail); + expect(cfApi.fetchSpaceUserRoles).toHaveBeenCalledOnce(); + }); + + it('calls receivedOrgSpacesToExtractSpaceUsers three times when org has three spaces', function (done) { + orgSpaces = [orgSpace, orgSpace, orgSpace]; + userActions.receivedOrgSpacesToExtractSpaceUsers(orgSpaces).then(done, done.fail); + expect(cfApi.fetchSpaceUserRoles).toHaveBeenCalledThrice(); + }); + }); + + describe('fetchUserAssociationsToOrgSpaces()', function() { + let userGuid; + let orgGuid; + let user; + let users; + let orgSpace; + let orgSpaces; + + beforeEach(function (done) { + userGuid = 'user-guid'; + orgGuid = 'org-guid'; + user = { guid: 'user-guid-this-is' }; + users = [user, user, user]; + orgSpace = { guid: 'org-guid-this-is' }; + orgSpaces = [orgSpace, orgSpace, orgSpace]; + + sandbox.stub(userActions, 'receivedOrgSpacesToExtractSpaceUsers') + .returns(Promise.resolve(users)); + sandbox.stub(cfApi, 'fetchAllOrgSpaces') + .returns(Promise.resolve(orgSpaces)); + + userActions.fetchUserAssociationsToOrgSpaces(userGuid, orgGuid).then(done, done.fail); + }); + + it(`should call cfApi.fetchAllOrgSpaces`, function() { + expect(cfApi.fetchAllOrgSpaces).toHaveBeenCalledOnce(); + }); + + it(`should call userActions.receivedOrgSpacesToExtractSpaceUsers`, function() { + expect(userActions.receivedOrgSpacesToExtractSpaceUsers).toHaveBeenCalledOnce(); + }); + }); + + describe('deleteUserOrDisplayNotice()', function() { + let userGuid; + let orgGuid; + let user; + let spaceUsers; + let orgSpace; + let orgSpaces; + + beforeEach(function () { + userGuid = 'user-guid'; + orgGuid = 'org-guid'; + user = { guid: userGuid }; + orgSpace = { guid: 'org-guid-this-is' }; + orgSpaces = [orgSpace, orgSpace, orgSpace]; + + sandbox.stub(userActions, 'createUserSpaceAssociationNotification'); + sandbox.stub(userActions, 'deleteUser'); + }); + + it(`should call userActions.createUserSpaceAssociationNotification if there are users`, function() { + spaceUsers = [user, user, user]; + userActions.deleteUserOrDisplayNotice(spaceUsers, userGuid, orgGuid); + expect(userActions.createUserSpaceAssociationNotification).toHaveBeenCalledOnce(); + }); + + it(`should call userActions.deleteUser if there aren't users`, function() { + spaceUsers = []; + userActions.deleteUserOrDisplayNotice(spaceUsers, userGuid, orgGuid); + expect(userActions.deleteUser).toHaveBeenCalledOnce(); + }); + }); + + describe('deleteUserIfNoSpaceAssociation()', function() { + let userGuid; + let orgGuid; + let user; + let spaceUsers; + + beforeEach(function (done) { + userGuid = 'user-guid'; + orgGuid = 'org-guid'; + user = { guid: userGuid }; + spaceUsers = [user, user, user]; + + sandbox.stub(userActions, 'fetchUserAssociationsToOrgSpaces') + .returns(Promise.resolve(spaceUsers)); + + sandbox.stub(userActions, 'deleteUserOrDisplayNotice'); + + userActions.deleteUserIfNoSpaceAssociation(userGuid, orgGuid).then(done, done.fail); + }); + + it(`should call userActions.fetchUserAssociationsToOrgSpaces`, function() { + expect(userActions.fetchUserAssociationsToOrgSpaces).toHaveBeenCalledOnce(); + }); + + it(`should call userActions.deleteUserOrDisplayNotice`, function() { + expect(userActions.deleteUserOrDisplayNotice).toHaveBeenCalledOnce(); + }); + }); + describe('deleteUser()', function() { + let spy; + let expectedParams; + beforeEach(function(done) { + var expectedUserGuid = 'adsklfjanmxcv', + expectedOrgGuid = 'sdkjfcmxxzcxvzz'; + expectedParams = { + userGuid: expectedUserGuid, + orgGuid: expectedOrgGuid + }; + + spy = setupViewSpy(sandbox); + sandbox.spy(userActions, 'deletedUser'); + sandbox.spy(userActions, 'errorRemoveUser'); + sandbox.spy(userActions, 'createUserSpaceAssociationNotification'); + sandbox.spy(cfApi, 'deleteUser'); + moxios.wait(function() { + let request = moxios.requests.mostRecent(); + request.respondWith({ + status: 200 + }).then(function () { + done(); + }); + }); + + userActions.deleteUser(expectedUserGuid, expectedOrgGuid).then(done, done.fail); + }); it('should dispatch a view event of type user delete with user guid', function() { + assertAction(spy, userActionTypes.USER_DELETE, expectedParams); + }); + it('should call the deleteUser cf api', + function() { + expect(cfApi.deleteUser).toHaveBeenCalledOnce(); + }); + it('should only call the deletedUser action upon success', + function() { + expect(userActions.errorRemoveUser).not.toHaveBeenCalledOnce(); + expect(userActions.deletedUser).toHaveBeenCalledOnce(); + expect(userActions.createUserSpaceAssociationNotification).not.toHaveBeenCalledOnce(); + }); + }); + + describe('deleteUser() generic error handling', function() { + let spy; + let expectedParams; + beforeEach(function(done) { var expectedUserGuid = 'adsklfjanmxcv', - expectedOrgGuid = 'sdkjfcmxxzcxvzz', - expectedParams = { - userGuid: expectedUserGuid, - orgGuid: expectedOrgGuid - }; + expectedOrgGuid = 'sdkjfcmxxzcxvzz'; + expectedParams = { + userGuid: expectedUserGuid, + orgGuid: expectedOrgGuid + }; - let spy = setupViewSpy(sandbox) + spy = setupViewSpy(sandbox); + sandbox.spy(userActions, 'deletedUser'); + sandbox.spy(userActions, 'errorRemoveUser'); + sandbox.spy(userActions, 'createUserSpaceAssociationNotification'); + sandbox.spy(cfApi, 'deleteUser'); + moxios.wait(function() { + let request = moxios.requests.mostRecent(); + request.respondWith({ + status: 500 + }).then(function () { + done(); + }); + }); - userActions.deleteUser(expectedUserGuid, expectedOrgGuid); + userActions.deleteUser(expectedUserGuid, expectedOrgGuid).then(done, done.fail); + }); + it('should dispatch a view event of type user delete with user guid', + function() { + assertAction(spy, userActionTypes.USER_DELETE, expectedParams); + }); + it('should call the deleteUser cf api', + function() { + expect(cfApi.deleteUser).toHaveBeenCalledOnce(); + }); + it('should only call the errorRemoveUser action upon generic failure', + function() { + expect(userActions.deletedUser).not.toHaveBeenCalledOnce(); + expect(userActions.errorRemoveUser).toHaveBeenCalledOnce(); + expect(userActions.createUserSpaceAssociationNotification).not.toHaveBeenCalledOnce(); + }); + }); + + describe('deleteUser() existingRole error handling', function() { + let spy; + let expectedParams; + beforeEach(function(done) { + var expectedUserGuid = 'adsklfjanmxcv', + expectedOrgGuid = 'sdkjfcmxxzcxvzz'; + expectedParams = { + userGuid: expectedUserGuid, + orgGuid: expectedOrgGuid + }; + + spy = setupViewSpy(sandbox); + sandbox.spy(userActions, 'deletedUser'); + sandbox.spy(userActions, 'errorRemoveUser'); + sandbox.spy(userActions, 'createUserSpaceAssociationNotification'); + sandbox.spy(cfApi, 'deleteUser'); + moxios.wait(function() { + let request = moxios.requests.mostRecent(); + request.respondWith({ + status: 400, + response: {error_code: 'CF-AssociationNotEmpty'}, + }).then(function () { + done(); + }); + }); + userActions.deleteUser(expectedUserGuid, expectedOrgGuid).then(done, done.fail); + }); + // TODO: Should revisit because assertAction checks for handleViewAction to + // only be called once. This error handling will make it called twice. + xit('should dispatch a view event of type user delete with user guid', + function() { assertAction(spy, userActionTypes.USER_DELETE, expectedParams); - }) + }); + it('should call the deleteUser cf api', + function() { + expect(cfApi.deleteUser).toHaveBeenCalledOnce(); + }); + it('should only call the createUserSpaceAssociationNotification action upon existing role error', + function() { + expect(userActions.deletedUser).not.toHaveBeenCalledOnce(); + expect(userActions.errorRemoveUser).not.toHaveBeenCalledOnce(); + expect(userActions.createUserSpaceAssociationNotification).toHaveBeenCalledOnce(); + }); }); describe('deletedUser()', function() { @@ -207,13 +439,13 @@ describe('userActions', function() { }); }); - describe('clearInviteNotifications()', function() { + describe('clearUserListNotifications()', function() { it('should dispatch a view event of type clear invite notification', function() { let spy = setupViewSpy(sandbox); - userActions.clearInviteNotifications(); + userActions.clearUserListNotifications(); - assertAction(spy, userActionTypes.USER_INVITE_STATUS_DISMISSED); + assertAction(spy, userActionTypes.USER_LIST_NOTICE_DISMISSED); }); }); @@ -240,7 +472,7 @@ describe('userActions', function() { let spy = setupViewSpy(sandbox); sandbox.spy(userActions, 'receivedInviteStatus'); userActions.createInviteNotification(false, email); - assertAction(spy, userActionTypes.USER_INVITE_STATUS_DISPLAYED, expected); + assertAction(spy, userActionTypes.USER_LIST_NOTICE_CREATED, expected); done(); }); @@ -253,12 +485,12 @@ describe('userActions', function() { let spy = setupViewSpy(sandbox); sandbox.spy(userActions, 'receivedInviteStatus'); userActions.createInviteNotification(true, email); - assertAction(spy, userActionTypes.USER_INVITE_STATUS_DISPLAYED, expected); + assertAction(spy, userActionTypes.USER_LIST_NOTICE_CREATED, expected); done(); }); }); - describe('userInviteError()', function() { + describe('userListNoticeError()', function() { let err; let message; @@ -267,7 +499,7 @@ describe('userActions', function() { message = 'something happened when invititing'; sandbox.stub(AppDispatcher, 'handleServerAction'); - userActions.userInviteError(err, message).then(done, done.fail); + userActions.userListNoticeError(err, message).then(done, done.fail); }); it('should dispatch server action of type user error with error and optional message', diff --git a/static_src/test/unit/stores/user_store.spec.js b/static_src/test/unit/stores/user_store.spec.js index 8b9bea72..8bb480a1 100644 --- a/static_src/test/unit/stores/user_store.spec.js +++ b/static_src/test/unit/stores/user_store.spec.js @@ -426,35 +426,10 @@ describe('UserStore', function () { }); describe('on user delete', function() { - it('should remove user permissions from org', function() { - var spy = sandbox.spy(cfApi, 'deleteOrgUserPermissions'), - expectedUserGuid = '19p83fhasjkdhf', - expectedOrgGuid = 'zxncmvduhvad', - expectedCategory = 'users'; - - userActions.deleteUser(expectedUserGuid, expectedOrgGuid); - - expect(spy).toHaveBeenCalledOnce(); - let args = spy.getCall(0).args; - expect(args[0]).toEqual(expectedUserGuid); - expect(args[1]).toEqual(expectedOrgGuid); - expect(args[2]).toEqual(expectedCategory); - }); - it('should delete the user on the server', function() { var spy = sandbox.spy(cfApi, 'deleteUser'), - stub = sandbox.stub(cfApi, 'deleteOrgUserPermissions'), expectedUserGuid = 'znxvmnzvmz', expectedOrgGuid = '029fjaskdjfalskdna'; - - let testPromise = { - then: function(cb) { - cb(); - } - } - - stub.returns(testPromise); - userActions.deleteUser(expectedUserGuid, expectedOrgGuid); expect(spy).toHaveBeenCalledOnce(); @@ -732,21 +707,21 @@ describe('UserStore', function () { }); }); - describe('on USER_INVITE_STATUS_DISPLAYED', function() { + describe('on USER_LIST_NOTICE_CREATED', function() { let notice; beforeEach(function() { notice = { noticeType: "finish", description: "An email invite was sent to undefined. Their account has been associated to this space, and their space roles can be controlled below." }; - UserStore._inviteNotification = notice; + UserStore._userListNotification = notice; sandbox.spy(UserStore, 'emitChange'); userActions.createInviteNotification(); }); it('should create notification for user invite', function() { - expect(UserStore.getInviteNotification()).toBeDefined(); - expect(UserStore.getInviteNotification().description).toEqual(notice.description); - expect(UserStore.getInviteNotification().noticeType).toEqual(notice.noticeType); + expect(UserStore.getUserListNotification()).toBeDefined(); + expect(UserStore.getUserListNotification().description).toEqual(notice.description); + expect(UserStore.getUserListNotification().noticeType).toEqual(notice.noticeType); }); it('should emit a change event', function() { @@ -754,21 +729,21 @@ describe('UserStore', function () { }); }); - describe('on USER_INVITE_STATUS_DISMISSED', function() { + describe('on USER_LIST_NOTICE_DISMISSED', function() { let notice; beforeEach(function() { notice = { noticeType: "finish", description: "message" }; - UserStore._inviteNotification = notice; + UserStore._userListNotification = notice; sandbox.spy(UserStore, 'emitChange'); - userActions.clearInviteNotifications(); + userActions.createUserListNotification(); }); it('should clear notification for user invite', function() { - expect(UserStore.getInviteNotification()).toBeDefined(); - expect(UserStore.getInviteNotification().description).not.toEqual(notice.description); - expect(UserStore.getInviteNotification().noticeType).not.toEqual(notice.noticeType); + expect(UserStore.getUserListNotification()).toBeDefined(); + expect(UserStore.getUserListNotification().description).not.toEqual(notice.description); + expect(UserStore.getUserListNotification().noticeType).not.toEqual(notice.noticeType); }); it('should emit a change event', function() { @@ -781,18 +756,18 @@ describe('UserStore', function () { let message; beforeEach(function() { - UserStore._inviteError = null; + UserStore._userListNotificationError = null; message = 'Inviting user did not work'; error = { status: 500, message: 'CF said this' }; sandbox.spy(UserStore, 'emitChange'); - userActions.userInviteError(error, message); + userActions.userListNoticeError(error, message); }); it('should add a error message to the user invite error field', function() { - expect(UserStore.getInviteError()).toBeDefined(); - expect(UserStore.getInviteError().contextualMessage).toEqual(message); - expect(UserStore.getInviteError().message).toEqual(error.message); + expect(UserStore.getUserListNotificationError()).toBeDefined(); + expect(UserStore.getUserListNotificationError().contextualMessage).toEqual(message); + expect(UserStore.getUserListNotificationError().message).toEqual(error.message); }); it('should emit a change event', function() { @@ -800,8 +775,8 @@ describe('UserStore', function () { }); }); - describe('getInviteNotification()', function () { - describe('user with _inviteNotification', function () { + describe('getUserListNotification()', function () { + describe('user with _userListNotification', function () { let user, space, org, actual, notice; beforeEach(function () { @@ -819,9 +794,9 @@ describe('UserStore', function () { UserStore.push(user); }); - it('returns notice when _inviteNotification has content', function () { - UserStore._inviteNotification = notice; - actual = UserStore.getInviteNotification() + it('returns notice when _userListNotification has content', function () { + UserStore._userListNotification = notice; + actual = UserStore.getUserListNotification() expect(actual).toBe(notice); }); @@ -831,10 +806,10 @@ describe('UserStore', function () { describe('on CLEAR', () => { beforeEach(function() { const notice = { noticeType: "finish", description: "message" }; - UserStore._inviteNotification = notice; + UserStore._userListNotification = notice; UserStore._error = 'something'; UserStore._saving = true; - UserStore._inviteError = 'invite error'; + UserStore._userListNotificationError = 'invite error'; UserStore._loading = {currentUser: true}; sandbox.spy(UserStore, 'emitChange'); AppDispatcher.handleViewAction({ @@ -843,10 +818,10 @@ describe('UserStore', function () { }); it('resets all of the notifications and errors', () => { - expect(UserStore._inviteNotification).toEqual({}); + expect(UserStore._userListNotification).toEqual({}); expect(UserStore._error).toBe(null); expect(UserStore._saving).toEqual(false); - expect(UserStore._inviteError).toBe(null); + expect(UserStore._userListNotificationError).toBe(null); expect(UserStore._loading).toEqual({}); }); }); diff --git a/static_src/test/unit/util/cf_api.spec.js b/static_src/test/unit/util/cf_api.spec.js index 02a80b97..ce8423e9 100644 --- a/static_src/test/unit/util/cf_api.spec.js +++ b/static_src/test/unit/util/cf_api.spec.js @@ -989,24 +989,6 @@ describe('cfApi', function() { done(); }).catch(done.fail); }); - - it('should call org deleted action with guid', function(done) { - var stub = sandbox.stub(http, 'delete'), - spy = sandbox.spy(userActions, 'deletedUser'), - expectedUserGuid = 'aldfskjmcx', - expectedOrgGuid = 'sa09dvjakdnva'; - - let testPromise = createPromise({status: true}); - stub.returns(testPromise); - - cfApi.deleteUser(expectedUserGuid, expectedOrgGuid).then(() => { - expect(spy).toHaveBeenCalledOnce(); - let args = spy.getCall(0).args; - expect(args[0]).toEqual(expectedUserGuid); - expect(args[1]).toEqual(expectedOrgGuid); - done(); - }).catch(done.fail); - }); }); describe('deleteOrgUserCategory()', function() { diff --git a/static_src/util/cf_api.js b/static_src/util/cf_api.js index 03ed025b..d326b294 100644 --- a/static_src/util/cf_api.js +++ b/static_src/util/cf_api.js @@ -213,6 +213,11 @@ export default { return this.fetchOrgDetails(guid); }, + fetchAllOrgSpaces(guid) { + return http.get(`${APIV}/organizations/${guid}/spaces`) + .then((res) => res.data); + }, + fetchOrgDetails(guid) { return http.get(`${APIV}/organizations/${guid}/summary`) .then((res) => res.data); @@ -383,15 +388,8 @@ export default { deleteUser(userGuid, orgGuid) { return http.delete(`${APIV}/organizations/${orgGuid}/users/${userGuid}`) - .then(() => { - userActions.deletedUser(userGuid, orgGuid); - }).catch((err) => { - if (err.response.data) { - userActions.errorRemoveUser(userGuid, err.data); - } else { - handleError(err); - } - }); + .then((res) => res.response); + // TODO. should log catch if unable to parseError. }, // TODO deprecate possibly in favor of deleteOrgUserPermissions.