diff --git a/app/soapbox/actions/__tests__/accounts.test.ts b/app/soapbox/actions/__tests__/accounts.test.ts index 2ea60bd80..9e5903f3b 100644 --- a/app/soapbox/actions/__tests__/accounts.test.ts +++ b/app/soapbox/actions/__tests__/accounts.test.ts @@ -6,12 +6,21 @@ import rootReducer from 'soapbox/reducers'; import { normalizeAccount } from '../../normalizers'; import { + authorizeFollowRequest, blockAccount, createAccount, + expandFollowers, + expandFollowing, + expandFollowRequests, fetchAccount, fetchAccountByUsername, + fetchFollowers, + fetchFollowing, + fetchFollowRequests, + fetchRelationships, followAccount, muteAccount, + removeFromFollowers, subscribeAccount, unblockAccount, unfollowAccount, @@ -921,3 +930,709 @@ describe('unsubscribeAccount()', () => { }); }); }); + +describe('removeFromFollowers()', () => { + const id = '1'; + + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(removeFromFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', '123'); + store = mockStore(state); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onPost(`/api/v1/accounts/${id}/remove_from_followers`).reply(200, {}); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'ACCOUNT_REMOVE_FROM_FOLLOWERS_REQUEST', id }, + { + type: 'ACCOUNT_REMOVE_FROM_FOLLOWERS_SUCCESS', + relationship: {}, + }, + ]; + await store.dispatch(removeFromFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onPost(`/api/v1/accounts/${id}/remove_from_followers`).networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'ACCOUNT_REMOVE_FROM_FOLLOWERS_REQUEST', id }, + { type: 'ACCOUNT_REMOVE_FROM_FOLLOWERS_FAIL', id, error: new Error('Network Error') }, + ]; + await store.dispatch(removeFromFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('fetchFollowers()', () => { + const id = '1'; + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', '123'); + store = mockStore(state); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet(`/api/v1/accounts/${id}/followers`).reply(200, [], { + link: `; rel='prev'`, + }); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWERS_FETCH_REQUEST', id }, + { type: 'ACCOUNTS_IMPORT', accounts: [] }, + { + type: 'FOLLOWERS_FETCH_SUCCESS', + id, + accounts: [], + next: null, + }, + ]; + await store.dispatch(fetchFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet(`/api/v1/accounts/${id}/followers`).networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWERS_FETCH_REQUEST', id }, + { type: 'FOLLOWERS_FETCH_FAIL', id, error: new Error('Network Error') }, + ]; + await store.dispatch(fetchFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('expandFollowers()', () => { + const id = '1'; + + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(expandFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('user_lists', ImmutableMap({ + followers: ImmutableMap({ + [id]: ImmutableMap({ + next: 'next_url', + }), + }), + })) + .set('me', '123'); + store = mockStore(state); + }); + + describe('when the url is null', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('user_lists', ImmutableMap({ + followers: ImmutableMap({ + [id]: ImmutableMap({ + next: null, + }), + }), + })) + .set('me', '123'); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(expandFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('next_url').reply(200, [], { + link: `; rel='prev'`, + }); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWERS_EXPAND_REQUEST', id }, + { type: 'ACCOUNTS_IMPORT', accounts: [] }, + { + type: 'FOLLOWERS_EXPAND_SUCCESS', + id, + accounts: [], + next: null, + }, + ]; + await store.dispatch(expandFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('next_url').networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWERS_EXPAND_REQUEST', id }, + { type: 'FOLLOWERS_EXPAND_FAIL', id, error: new Error('Network Error') }, + ]; + await store.dispatch(expandFollowers(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('fetchFollowing()', () => { + const id = '1'; + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', '123'); + store = mockStore(state); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet(`/api/v1/accounts/${id}/following`).reply(200, [], { + link: `; rel='prev'`, + }); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWING_FETCH_REQUEST', id }, + { type: 'ACCOUNTS_IMPORT', accounts: [] }, + { + type: 'FOLLOWING_FETCH_SUCCESS', + id, + accounts: [], + next: null, + }, + ]; + await store.dispatch(fetchFollowing(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet(`/api/v1/accounts/${id}/following`).networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWING_FETCH_REQUEST', id }, + { type: 'FOLLOWING_FETCH_FAIL', id, error: new Error('Network Error') }, + ]; + await store.dispatch(fetchFollowing(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('expandFollowing()', () => { + const id = '1'; + + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(expandFollowing(id)); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('user_lists', ImmutableMap({ + following: ImmutableMap({ + [id]: ImmutableMap({ + next: 'next_url', + }), + }), + })) + .set('me', '123'); + store = mockStore(state); + }); + + describe('when the url is null', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('user_lists', ImmutableMap({ + following: ImmutableMap({ + [id]: ImmutableMap({ + next: null, + }), + }), + })) + .set('me', '123'); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(expandFollowing(id)); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('next_url').reply(200, [], { + link: `; rel='prev'`, + }); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWING_EXPAND_REQUEST', id }, + { type: 'ACCOUNTS_IMPORT', accounts: [] }, + { + type: 'FOLLOWING_EXPAND_SUCCESS', + id, + accounts: [], + next: null, + }, + ]; + await store.dispatch(expandFollowing(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('next_url').networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOWING_EXPAND_REQUEST', id }, + { type: 'FOLLOWING_EXPAND_FAIL', id, error: new Error('Network Error') }, + ]; + await store.dispatch(expandFollowing(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('fetchRelationships()', () => { + const id = '1'; + + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(fetchRelationships([id])); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('me', '123'); + store = mockStore(state); + }); + + describe('without newAccountIds', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('relationships', ImmutableMap({ [id]: {} })) + .set('me', '123'); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(fetchRelationships([id])); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('relationships', ImmutableMap({})) + .set('me', '123'); + store = mockStore(state); + + __stub((mock) => { + mock + .onGet(`/api/v1/accounts/relationships?${[id].map(id => `id[]=${id}`).join('&')}`) + .reply(200, []); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'RELATIONSHIPS_FETCH_REQUEST', ids: [id], skipLoading: true }, + { + type: 'RELATIONSHIPS_FETCH_SUCCESS', + relationships: [], + skipLoading: true, + }, + ]; + await store.dispatch(fetchRelationships([id])); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock + .onGet(`/api/v1/accounts/relationships?${[id].map(id => `id[]=${id}`).join('&')}`) + .networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'RELATIONSHIPS_FETCH_REQUEST', ids: [id], skipLoading: true }, + { type: 'RELATIONSHIPS_FETCH_FAIL', skipLoading: true, error: new Error('Network Error') }, + ]; + await store.dispatch(fetchRelationships([id])); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('fetchFollowRequests()', () => { + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(fetchFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('me', '123'); + store = mockStore(state); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('relationships', ImmutableMap({})) + .set('me', '123'); + store = mockStore(state); + + __stub((mock) => { + mock.onGet('/api/v1/follow_requests').reply(200, [], { + link: '; rel=\'prev\'', + }); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOW_REQUESTS_FETCH_REQUEST' }, + { type: 'ACCOUNTS_IMPORT', accounts: [] }, + { + type: 'FOLLOW_REQUESTS_FETCH_SUCCESS', + accounts: [], + next: null, + }, + ]; + await store.dispatch(fetchFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('/api/v1/follow_requests').networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOW_REQUESTS_FETCH_REQUEST' }, + { type: 'FOLLOW_REQUESTS_FETCH_FAIL', error: new Error('Network Error') }, + ]; + await store.dispatch(fetchFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('expandFollowRequests()', () => { + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(expandFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('user_lists', ImmutableMap({ + follow_requests: ImmutableMap({ + next: 'next_url', + }), + })) + .set('me', '123'); + store = mockStore(state); + }); + + describe('when the url is null', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('user_lists', ImmutableMap({ + follow_requests: ImmutableMap({ + next: null, + }), + })) + .set('me', '123'); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(expandFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('next_url').reply(200, [], { + link: '; rel=\'prev\'', + }); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOW_REQUESTS_EXPAND_REQUEST' }, + { type: 'ACCOUNTS_IMPORT', accounts: [] }, + { + type: 'FOLLOW_REQUESTS_EXPAND_SUCCESS', + accounts: [], + next: null, + }, + ]; + await store.dispatch(expandFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onGet('next_url').networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOW_REQUESTS_EXPAND_REQUEST' }, + { type: 'FOLLOW_REQUESTS_EXPAND_FAIL', error: new Error('Network Error') }, + ]; + await store.dispatch(expandFollowRequests()); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); + +describe('authorizeFollowRequest()', () => { + const id = '1'; + + describe('when logged out', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', null); + store = mockStore(state); + }); + + it('should do nothing', async() => { + await store.dispatch(authorizeFollowRequest(id)); + const actions = store.getActions(); + + expect(actions).toEqual([]); + }); + }); + + describe('when logged in', () => { + beforeEach(() => { + const state = rootReducer(undefined, {}).set('me', '123'); + store = mockStore(state); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onPost(`/api/v1/follow_requests/${id}/authorize`).reply(200); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOW_REQUEST_AUTHORIZE_REQUEST', id }, + { type: 'FOLLOW_REQUEST_AUTHORIZE_SUCCESS', id }, + ]; + await store.dispatch(authorizeFollowRequest(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onPost(`/api/v1/follow_requests/${id}/authorize`).networkError(); + }); + }); + + it('should dispatch the correct actions', async() => { + const expectedActions = [ + { type: 'FOLLOW_REQUEST_AUTHORIZE_REQUEST', id }, + { type: 'FOLLOW_REQUEST_AUTHORIZE_FAIL', id, error: new Error('Network Error') }, + ]; + await store.dispatch(authorizeFollowRequest(id)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + }); +}); diff --git a/app/soapbox/actions/accounts.ts b/app/soapbox/actions/accounts.ts index 60cb6bbe6..31c5c6717 100644 --- a/app/soapbox/actions/accounts.ts +++ b/app/soapbox/actions/accounts.ts @@ -466,15 +466,14 @@ const unsubscribeAccountFail = (error: AxiosError) => ({ const removeFromFollowers = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; - dispatch(muteAccountRequest(id)); + dispatch(removeFromFollowersRequest(id)); - api(getState).post(`/api/v1/accounts/${id}/remove_from_followers`).then(response => { - dispatch(removeFromFollowersSuccess(response.data)); - }).catch(error => { - dispatch(removeFromFollowersFail(id, error)); - }); + return api(getState) + .post(`/api/v1/accounts/${id}/remove_from_followers`) + .then(response => dispatch(removeFromFollowersSuccess(response.data))) + .catch(error => dispatch(removeFromFollowersFail(id, error))); }; const removeFromFollowersRequest = (id: string) => ({ @@ -497,15 +496,18 @@ const fetchFollowers = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch(fetchFollowersRequest(id)); - api(getState).get(`/api/v1/accounts/${id}/followers`).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); + return api(getState) + .get(`/api/v1/accounts/${id}/followers`) + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null)); - dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); - }).catch(error => { - dispatch(fetchFollowersFail(id, error)); - }); + dispatch(importFetchedAccounts(response.data)); + dispatch(fetchFollowersSuccess(id, response.data, next ? next.uri : null)); + dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); + }) + .catch(error => { + dispatch(fetchFollowersFail(id, error)); + }); }; const fetchFollowersRequest = (id: string) => ({ @@ -528,25 +530,28 @@ const fetchFollowersFail = (id: string, error: AxiosError) => ({ const expandFollowers = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; const url = getState().user_lists.followers.get(id)?.next as string; if (url === null) { - return; + return null; } dispatch(expandFollowersRequest(id)); - api(getState).get(url).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); + return api(getState) + .get(url) + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null)); - dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); - }).catch(error => { - dispatch(expandFollowersFail(id, error)); - }); + dispatch(importFetchedAccounts(response.data)); + dispatch(expandFollowersSuccess(id, response.data, next ? next.uri : null)); + dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); + }) + .catch(error => { + dispatch(expandFollowersFail(id, error)); + }); }; const expandFollowersRequest = (id: string) => ({ @@ -571,15 +576,18 @@ const fetchFollowing = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { dispatch(fetchFollowingRequest(id)); - api(getState).get(`/api/v1/accounts/${id}/following`).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); + return api(getState) + .get(`/api/v1/accounts/${id}/following`) + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null)); - dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); - }).catch(error => { - dispatch(fetchFollowingFail(id, error)); - }); + dispatch(importFetchedAccounts(response.data)); + dispatch(fetchFollowingSuccess(id, response.data, next ? next.uri : null)); + dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); + }) + .catch(error => { + dispatch(fetchFollowingFail(id, error)); + }); }; const fetchFollowingRequest = (id: string) => ({ @@ -602,25 +610,28 @@ const fetchFollowingFail = (id: string, error: AxiosError) => ({ const expandFollowing = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; const url = getState().user_lists.following.get(id)!.next; if (url === null) { - return; + return null; } dispatch(expandFollowingRequest(id)); - api(getState).get(url).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); + return api(getState) + .get(url) + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null)); - dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); - }).catch(error => { - dispatch(expandFollowingFail(id, error)); - }); + dispatch(importFetchedAccounts(response.data)); + dispatch(expandFollowingSuccess(id, response.data, next ? next.uri : null)); + dispatch(fetchRelationships(response.data.map((item: APIEntity) => item.id))); + }) + .catch(error => { + dispatch(expandFollowingFail(id, error)); + }); }; const expandFollowingRequest = (id: string) => ({ @@ -643,22 +654,21 @@ const expandFollowingFail = (id: string, error: AxiosError) => ({ const fetchRelationships = (accountIds: string[]) => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; const loadedRelationships = getState().relationships; const newAccountIds = accountIds.filter(id => loadedRelationships.get(id, null) === null); if (newAccountIds.length === 0) { - return; + return null; } dispatch(fetchRelationshipsRequest(newAccountIds)); - api(getState).get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join('&')}`).then(response => { - dispatch(fetchRelationshipsSuccess(response.data)); - }).catch(error => { - dispatch(fetchRelationshipsFail(error)); - }); + return api(getState) + .get(`/api/v1/accounts/relationships?${newAccountIds.map(id => `id[]=${id}`).join('&')}`) + .then(response => dispatch(fetchRelationshipsSuccess(response.data))) + .catch(error => dispatch(fetchRelationshipsFail(error))); }; const fetchRelationshipsRequest = (ids: string[]) => ({ @@ -681,15 +691,18 @@ const fetchRelationshipsFail = (error: AxiosError) => ({ const fetchFollowRequests = () => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; dispatch(fetchFollowRequestsRequest()); - api(getState).get('/api/v1/follow_requests').then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null)); - }).catch(error => dispatch(fetchFollowRequestsFail(error))); + return api(getState) + .get('/api/v1/follow_requests') + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedAccounts(response.data)); + dispatch(fetchFollowRequestsSuccess(response.data, next ? next.uri : null)); + }) + .catch(error => dispatch(fetchFollowRequestsFail(error))); }; const fetchFollowRequestsRequest = () => ({ @@ -709,21 +722,24 @@ const fetchFollowRequestsFail = (error: AxiosError) => ({ const expandFollowRequests = () => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; const url = getState().user_lists.follow_requests.next; if (url === null) { - return; + return null; } dispatch(expandFollowRequestsRequest()); - api(getState).get(url).then(response => { - const next = getLinks(response).refs.find(link => link.rel === 'next'); - dispatch(importFetchedAccounts(response.data)); - dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null)); - }).catch(error => dispatch(expandFollowRequestsFail(error))); + return api(getState) + .get(url) + .then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedAccounts(response.data)); + dispatch(expandFollowRequestsSuccess(response.data, next ? next.uri : null)); + }) + .catch(error => dispatch(expandFollowRequestsFail(error))); }; const expandFollowRequestsRequest = () => ({ @@ -743,11 +759,11 @@ const expandFollowRequestsFail = (error: AxiosError) => ({ const authorizeFollowRequest = (id: string) => (dispatch: AppDispatch, getState: () => RootState) => { - if (!isLoggedIn(getState)) return; + if (!isLoggedIn(getState)) return null; dispatch(authorizeFollowRequestRequest(id)); - api(getState) + return api(getState) .post(`/api/v1/follow_requests/${id}/authorize`) .then(() => dispatch(authorizeFollowRequestSuccess(id))) .catch(error => dispatch(authorizeFollowRequestFail(id, error)));