From 8433ff70b07aef725dd004aed3bce8f01d4183d5 Mon Sep 17 00:00:00 2001 From: Justin Date: Fri, 27 May 2022 14:08:41 -0400 Subject: [PATCH] Add tests for account-notes action --- .../actions/__tests__/account-notes.test.ts | 106 ++++++++++++++++++ app/soapbox/actions/account-notes.ts | 82 ++++++++++++++ app/soapbox/actions/account_notes.js | 67 ----------- app/soapbox/actions/modals.ts | 2 +- .../containers/header_container.js | 2 +- .../ui/components/account_note_modal.js | 2 +- app/soapbox/reducers/account_notes.ts | 4 +- app/soapbox/reducers/relationships.js | 2 +- 8 files changed, 194 insertions(+), 73 deletions(-) create mode 100644 app/soapbox/actions/__tests__/account-notes.test.ts create mode 100644 app/soapbox/actions/account-notes.ts delete mode 100644 app/soapbox/actions/account_notes.js diff --git a/app/soapbox/actions/__tests__/account-notes.test.ts b/app/soapbox/actions/__tests__/account-notes.test.ts new file mode 100644 index 000000000..e173fd17f --- /dev/null +++ b/app/soapbox/actions/__tests__/account-notes.test.ts @@ -0,0 +1,106 @@ +import { __stub } from 'soapbox/api'; +import { mockStore } from 'soapbox/jest/test-helpers'; +import rootReducer from 'soapbox/reducers'; + +import { normalizeAccount } from '../../normalizers'; +import { changeAccountNoteComment, initAccountNoteModal, submitAccountNote } from '../account-notes'; + +describe('submitAccountNote()', () => { + let store; + + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('account_notes', { edit: { account_id: 1, comment: 'hello' } }); + store = mockStore(state); + }); + + describe('with a successful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onPost('/api/v1/accounts/1/note').reply(200, {}); + }); + }); + + it('post the note to the API', async() => { + const expectedActions = [ + { type: 'ACCOUNT_NOTE_SUBMIT_REQUEST' }, + { type: 'MODAL_CLOSE', modalType: undefined }, + { type: 'ACCOUNT_NOTE_SUBMIT_SUCCESS', relationship: {} }, + ]; + await store.dispatch(submitAccountNote()); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); + + describe('with an unsuccessful API request', () => { + beforeEach(() => { + __stub((mock) => { + mock.onPost('/api/v1/accounts/1/note').networkError(); + }); + }); + + it('should dispatch failed action', async() => { + const expectedActions = [ + { type: 'ACCOUNT_NOTE_SUBMIT_REQUEST' }, + { + type: 'ACCOUNT_NOTE_SUBMIT_FAIL', + error: new Error('Network Error'), + }, + ]; + await store.dispatch(submitAccountNote()); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); + }); +}); + +describe('initAccountNoteModal()', () => { + let store; + + beforeEach(() => { + const state = rootReducer(undefined, {}) + .set('relationships', { 1: { note: 'hello' } }); + store = mockStore(state); + }); + + it('dispatches the proper actions', async() => { + const account = normalizeAccount({ + id: '1', + acct: 'justin-username', + display_name: 'Justin L', + avatar: 'test.jpg', + verified: true, + }); + const expectedActions = [ + { type: 'ACCOUNT_NOTE_INIT_MODAL', account, comment: 'hello' }, + { type: 'MODAL_OPEN', modalType: 'ACCOUNT_NOTE' }, + ]; + await store.dispatch(initAccountNoteModal(account)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); +}); + +describe('changeAccountNoteComment()', () => { + let store; + + beforeEach(() => { + const state = rootReducer(undefined, {}); + store = mockStore(state); + }); + + it('dispatches the proper actions', async() => { + const comment = 'hello world'; + const expectedActions = [ + { type: 'ACCOUNT_NOTE_CHANGE_COMMENT', comment }, + ]; + await store.dispatch(changeAccountNoteComment(comment)); + const actions = store.getActions(); + + expect(actions).toEqual(expectedActions); + }); +}); diff --git a/app/soapbox/actions/account-notes.ts b/app/soapbox/actions/account-notes.ts new file mode 100644 index 000000000..bb1cc72ae --- /dev/null +++ b/app/soapbox/actions/account-notes.ts @@ -0,0 +1,82 @@ +import { AxiosError } from 'axios'; +import { AnyAction } from 'redux'; + +import api from '../api'; + +import { openModal, closeModal } from './modals'; + +import type { Account } from 'soapbox/types/entities'; + +const ACCOUNT_NOTE_SUBMIT_REQUEST = 'ACCOUNT_NOTE_SUBMIT_REQUEST'; +const ACCOUNT_NOTE_SUBMIT_SUCCESS = 'ACCOUNT_NOTE_SUBMIT_SUCCESS'; +const ACCOUNT_NOTE_SUBMIT_FAIL = 'ACCOUNT_NOTE_SUBMIT_FAIL'; + +const ACCOUNT_NOTE_INIT_MODAL = 'ACCOUNT_NOTE_INIT_MODAL'; + +const ACCOUNT_NOTE_CHANGE_COMMENT = 'ACCOUNT_NOTE_CHANGE_COMMENT'; + +const submitAccountNote = () => (dispatch: React.Dispatch, getState: any) => { + dispatch(submitAccountNoteRequest()); + + const id = getState().getIn(['account_notes', 'edit', 'account_id']); + + return api(getState) + .post(`/api/v1/accounts/${id}/note`, { + comment: getState().getIn(['account_notes', 'edit', 'comment']), + }) + .then(response => { + dispatch(closeModal()); + dispatch(submitAccountNoteSuccess(response.data)); + }) + .catch(error => dispatch(submitAccountNoteFail(error))); +}; + +function submitAccountNoteRequest() { + return { + type: ACCOUNT_NOTE_SUBMIT_REQUEST, + }; +} + +function submitAccountNoteSuccess(relationship: any) { + return { + type: ACCOUNT_NOTE_SUBMIT_SUCCESS, + relationship, + }; +} + +function submitAccountNoteFail(error: AxiosError) { + return { + type: ACCOUNT_NOTE_SUBMIT_FAIL, + error, + }; +} + +const initAccountNoteModal = (account: Account) => (dispatch: React.Dispatch, getState: any) => { + const comment = getState().getIn(['relationships', account.get('id'), 'note']); + + dispatch({ + type: ACCOUNT_NOTE_INIT_MODAL, + account, + comment, + }); + + dispatch(openModal('ACCOUNT_NOTE')); +}; + +function changeAccountNoteComment(comment: string) { + return { + type: ACCOUNT_NOTE_CHANGE_COMMENT, + comment, + }; +} + +export { + submitAccountNote, + initAccountNoteModal, + changeAccountNoteComment, + ACCOUNT_NOTE_SUBMIT_REQUEST, + ACCOUNT_NOTE_SUBMIT_SUCCESS, + ACCOUNT_NOTE_SUBMIT_FAIL, + ACCOUNT_NOTE_INIT_MODAL, + ACCOUNT_NOTE_CHANGE_COMMENT, +}; diff --git a/app/soapbox/actions/account_notes.js b/app/soapbox/actions/account_notes.js deleted file mode 100644 index d6aeefc49..000000000 --- a/app/soapbox/actions/account_notes.js +++ /dev/null @@ -1,67 +0,0 @@ -import api from '../api'; - -import { openModal, closeModal } from './modals'; - -export const ACCOUNT_NOTE_SUBMIT_REQUEST = 'ACCOUNT_NOTE_SUBMIT_REQUEST'; -export const ACCOUNT_NOTE_SUBMIT_SUCCESS = 'ACCOUNT_NOTE_SUBMIT_SUCCESS'; -export const ACCOUNT_NOTE_SUBMIT_FAIL = 'ACCOUNT_NOTE_SUBMIT_FAIL'; - -export const ACCOUNT_NOTE_INIT_MODAL = 'ACCOUNT_NOTE_INIT_MODAL'; - -export const ACCOUNT_NOTE_CHANGE_COMMENT = 'ACCOUNT_NOTE_CHANGE_COMMENT'; - -export function submitAccountNote() { - return (dispatch, getState) => { - dispatch(submitAccountNoteRequest()); - - const id = getState().getIn(['account_notes', 'edit', 'account_id']); - - api(getState).post(`/api/v1/accounts/${id}/note`, { - comment: getState().getIn(['account_notes', 'edit', 'comment']), - }).then(response => { - dispatch(closeModal()); - dispatch(submitAccountNoteSuccess(response.data)); - }).catch(error => dispatch(submitAccountNoteFail(error))); - }; -} - -export function submitAccountNoteRequest() { - return { - type: ACCOUNT_NOTE_SUBMIT_REQUEST, - }; -} - -export function submitAccountNoteSuccess(relationship) { - return { - type: ACCOUNT_NOTE_SUBMIT_SUCCESS, - relationship, - }; -} - -export function submitAccountNoteFail(error) { - return { - type: ACCOUNT_NOTE_SUBMIT_FAIL, - error, - }; -} - -export function initAccountNoteModal(account) { - return (dispatch, getState) => { - const comment = getState().getIn(['relationships', account.get('id'), 'note']); - - dispatch({ - type: ACCOUNT_NOTE_INIT_MODAL, - account, - comment, - }); - - dispatch(openModal('ACCOUNT_NOTE')); - }; -} - -export function changeAccountNoteComment(comment) { - return { - type: ACCOUNT_NOTE_CHANGE_COMMENT, - comment, - }; -} \ No newline at end of file diff --git a/app/soapbox/actions/modals.ts b/app/soapbox/actions/modals.ts index 9d6e85139..3e1a106cf 100644 --- a/app/soapbox/actions/modals.ts +++ b/app/soapbox/actions/modals.ts @@ -11,7 +11,7 @@ export function openModal(type: string, props?: any) { } /** Close the modal */ -export function closeModal(type: string) { +export function closeModal(type?: string) { return { type: MODAL_CLOSE, modalType: type, diff --git a/app/soapbox/features/account_timeline/containers/header_container.js b/app/soapbox/features/account_timeline/containers/header_container.js index baf0ccb17..0ffa9b81b 100644 --- a/app/soapbox/features/account_timeline/containers/header_container.js +++ b/app/soapbox/features/account_timeline/containers/header_container.js @@ -2,7 +2,7 @@ import React from 'react'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import { initAccountNoteModal } from 'soapbox/actions/account_notes'; +import { initAccountNoteModal } from 'soapbox/actions/account-notes'; import { followAccount, unfollowAccount, diff --git a/app/soapbox/features/ui/components/account_note_modal.js b/app/soapbox/features/ui/components/account_note_modal.js index 2c7ed11ed..9242b7b8f 100644 --- a/app/soapbox/features/ui/components/account_note_modal.js +++ b/app/soapbox/features/ui/components/account_note_modal.js @@ -3,7 +3,7 @@ import React from 'react'; import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; import { connect } from 'react-redux'; -import { changeAccountNoteComment, submitAccountNote } from 'soapbox/actions/account_notes'; +import { changeAccountNoteComment, submitAccountNote } from 'soapbox/actions/account-notes'; import { closeModal } from 'soapbox/actions/modals'; import { Modal, Text } from 'soapbox/components/ui'; import { makeGetAccount } from 'soapbox/selectors'; diff --git a/app/soapbox/reducers/account_notes.ts b/app/soapbox/reducers/account_notes.ts index 07d5cc89e..446b04ca9 100644 --- a/app/soapbox/reducers/account_notes.ts +++ b/app/soapbox/reducers/account_notes.ts @@ -7,7 +7,7 @@ import { ACCOUNT_NOTE_SUBMIT_REQUEST, ACCOUNT_NOTE_SUBMIT_FAIL, ACCOUNT_NOTE_SUBMIT_SUCCESS, -} from '../actions/account_notes'; +} from '../actions/account-notes'; const EditRecord = ImmutableRecord({ isSubmitting: false, @@ -39,4 +39,4 @@ export default function account_notes(state: State = ReducerRecord(), action: An default: return state; } -} \ No newline at end of file +} diff --git a/app/soapbox/reducers/relationships.js b/app/soapbox/reducers/relationships.js index 80754842c..a846b8199 100644 --- a/app/soapbox/reducers/relationships.js +++ b/app/soapbox/reducers/relationships.js @@ -3,7 +3,7 @@ import { get } from 'lodash'; import { STREAMING_FOLLOW_RELATIONSHIPS_UPDATE } from 'soapbox/actions/streaming'; -import { ACCOUNT_NOTE_SUBMIT_SUCCESS } from '../actions/account_notes'; +import { ACCOUNT_NOTE_SUBMIT_SUCCESS } from '../actions/account-notes'; import { ACCOUNT_FOLLOW_SUCCESS, ACCOUNT_FOLLOW_REQUEST,