diff --git a/src/App.test.jsx b/src/App.test.jsx
index dcc42d6..dcf46a6 100644
--- a/src/App.test.jsx
+++ b/src/App.test.jsx
@@ -23,7 +23,7 @@ describe('App', () => {
useSelector.mockImplementation((selector) => selector({
groups: STUDY_GROUPS,
- group: STUDY_GROUP,
+ group: given.group,
writeField: {
tags: [],
},
@@ -37,6 +37,7 @@ describe('App', () => {
));
context('with path /', () => {
+ given('group', () => (null));
it('renders the study list page', () => {
const { container } = renderApp({ path: '/' });
@@ -45,6 +46,7 @@ describe('App', () => {
});
context('with path /introduce', () => {
+ given('group', () => (STUDY_GROUP));
it('renders the study introduce page', () => {
const { container } = renderApp({ path: '/introduce/1' });
@@ -53,6 +55,7 @@ describe('App', () => {
});
context('with path /write', () => {
+ given('group', () => (null));
it('renders the study write page', () => {
const { container } = renderApp({ path: '/write' });
diff --git a/src/components/write/WriteButtons.jsx b/src/components/write/WriteButtons.jsx
new file mode 100644
index 0000000..7a23c0b
--- /dev/null
+++ b/src/components/write/WriteButtons.jsx
@@ -0,0 +1,19 @@
+import React from 'react';
+
+import styled from '@emotion/styled';
+
+const WriteButtonsWrapper = styled.div``;
+
+const WriteButtons = ({ onSubmit }) => (
+
+
+
+
+);
+
+export default WriteButtons;
diff --git a/src/components/write/WriteButtons.test.jsx b/src/components/write/WriteButtons.test.jsx
new file mode 100644
index 0000000..5c6ac7e
--- /dev/null
+++ b/src/components/write/WriteButtons.test.jsx
@@ -0,0 +1,18 @@
+import React from 'react';
+
+import { render } from '@testing-library/react';
+
+import WriteButtons from './WriteButtons';
+
+describe('WriteButtons', () => {
+ const renderWriteButtons = () => render((
+
+ ));
+
+ it('render Write buttons', () => {
+ const { container } = renderWriteButtons();
+
+ expect(container).toHaveTextContent('등록하기');
+ expect(container).toHaveTextContent('취소');
+ });
+});
diff --git a/src/containers/write/WriteButtonsContainer.jsx b/src/containers/write/WriteButtonsContainer.jsx
new file mode 100644
index 0000000..a0f1caa
--- /dev/null
+++ b/src/containers/write/WriteButtonsContainer.jsx
@@ -0,0 +1,39 @@
+import React, { useEffect, useCallback } from 'react';
+
+import { useDispatch, useSelector } from 'react-redux';
+
+import { useHistory } from 'react-router-dom';
+
+import { get } from '../../util/utils';
+import { writeStudyGroup } from '../../reducers/slice';
+
+import WriteButtons from '../../components/write/WriteButtons';
+
+const WriteButtonsContainer = () => {
+ const history = useHistory();
+ const dispatch = useDispatch();
+
+ const writeField = useSelector(get('writeField'));
+ const group = useSelector(get('group'));
+
+ const onSubmit = useCallback(() => {
+ // TODO: write form validate 체크 하기
+ dispatch(writeStudyGroup());
+ }, [dispatch]);
+
+ useEffect(() => {
+ if (group) {
+ const { id } = group;
+ history.push(`/introduce/${id}`);
+ }
+ }, [history, group]);
+
+ return (
+
+ );
+};
+
+export default WriteButtonsContainer;
diff --git a/src/containers/write/WriteButtonsContainer.test.jsx b/src/containers/write/WriteButtonsContainer.test.jsx
new file mode 100644
index 0000000..0fe07ad
--- /dev/null
+++ b/src/containers/write/WriteButtonsContainer.test.jsx
@@ -0,0 +1,75 @@
+import React from 'react';
+
+import { useDispatch, useSelector } from 'react-redux';
+import { MemoryRouter } from 'react-router-dom';
+
+import { render, fireEvent } from '@testing-library/react';
+
+import WriteButtonsContainer from './WriteButtonsContainer';
+
+import WRITE_FORM from '../../../fixtures/write-form';
+import STUDY_GROUP from '../../../fixtures/study-group';
+
+const mockPush = jest.fn();
+
+jest.mock('react-router-dom', () => ({
+ ...jest.requireActual('react-router-dom'),
+ useHistory() {
+ return { push: mockPush };
+ },
+}));
+
+describe('WriteButtonsContainer', () => {
+ const dispatch = jest.fn();
+
+ beforeEach(() => {
+ dispatch.mockClear();
+ mockPush.mockClear();
+
+ useDispatch.mockImplementation(() => dispatch);
+
+ useSelector.mockImplementation((state) => state({
+ writeField: WRITE_FORM,
+ group: given.group,
+ }));
+ });
+
+ const renderWriteButtonsContainer = () => render((
+
+
+
+ ));
+
+ it('render Write buttons', () => {
+ const { container } = renderWriteButtonsContainer();
+
+ expect(container).toHaveTextContent('등록하기');
+ expect(container).toHaveTextContent('취소');
+ });
+
+ describe('when click submit button', () => {
+ context('with group', () => {
+ given('group', () => (STUDY_GROUP));
+ it('dispatch action submit event', () => {
+ const { getByText } = renderWriteButtonsContainer();
+
+ fireEvent.click(getByText('등록하기'));
+
+ expect(dispatch).toBeCalledTimes(1);
+
+ expect(mockPush).toBeCalledWith('/introduce/1');
+ });
+ });
+
+ context('without group', () => {
+ given('group', () => (null));
+ it('dispatch action submit event', () => {
+ const { getByText } = renderWriteButtonsContainer();
+
+ fireEvent.click(getByText('등록하기'));
+
+ expect(mockPush).not.toBeCalled();
+ });
+ });
+ });
+});
diff --git a/src/pages/WritePage.jsx b/src/pages/WritePage.jsx
index 12f971c..0038974 100644
--- a/src/pages/WritePage.jsx
+++ b/src/pages/WritePage.jsx
@@ -1,6 +1,7 @@
import React from 'react';
import TagFormContainer from '../containers/write/TagsFormContainer';
+import WriteButtonsContainer from '../containers/write/WriteButtonsContainer';
import WriteFormContainer from '../containers/write/WriteFormContainer';
import Responsive from '../styles/Responsive';
@@ -10,9 +11,7 @@ const IntroducePage = () => (
스터디 그룹 개설하기
-
-
-
+
);
export default IntroducePage;
diff --git a/src/pages/WritePage.test.jsx b/src/pages/WritePage.test.jsx
index f410059..524f772 100644
--- a/src/pages/WritePage.test.jsx
+++ b/src/pages/WritePage.test.jsx
@@ -33,11 +33,10 @@ describe('WritePage', () => {
});
it('renders write form tag', () => {
- const { getByPlaceholderText, getByText } = renderWritePage();
+ const { getByPlaceholderText } = renderWritePage();
expect(getByPlaceholderText('제목을 입력하세요')).not.toBeNull();
expect(getByPlaceholderText('내용')).not.toBeNull();
- expect(getByText('저장')).not.toBeNull();
});
it('renders tag form text', () => {
@@ -46,5 +45,12 @@ describe('WritePage', () => {
expect(getByPlaceholderText('태그를 입력하세요')).not.toBeNull();
expect(container).toHaveTextContent('태그');
});
+
+ it('renders buttons', () => {
+ const { getByText } = renderWritePage();
+
+ expect(getByText('등록하기')).not.toBeNull();
+ expect(getByText('취소')).not.toBeNull();
+ });
});
});
diff --git a/src/reducers/slice.js b/src/reducers/slice.js
index bc0a4e8..d712d39 100644
--- a/src/reducers/slice.js
+++ b/src/reducers/slice.js
@@ -3,6 +3,7 @@ import { createSlice } from '@reduxjs/toolkit';
import {
getStudyGroup,
getStudyGroups,
+ postStudyGroup,
} from '../services/api';
const writeInitialState = {
@@ -52,6 +53,14 @@ const { actions, reducer } = createSlice({
},
};
},
+ clearWriteFields(state) {
+ return {
+ ...state,
+ writeField: {
+ ...writeInitialState,
+ },
+ };
+ },
},
});
@@ -59,6 +68,7 @@ export const {
setStudyGroups,
setStudyGroup,
changeWriteField,
+ clearWriteFields,
} = actions;
export const loadStudyGroups = (tag) => async (dispatch) => {
@@ -75,4 +85,14 @@ export const loadStudyGroup = (id) => async (dispatch) => {
dispatch(setStudyGroup(group));
};
+export const writeStudyGroup = () => async (dispatch, getState) => {
+ const { writeField } = getState();
+
+ // NOTE: 현재 로그인 기능이 없는 관계로 임의로 작성자(moderatorId)를 넣어줌
+ const group = await postStudyGroup({ ...writeField, moderatorId: 'user1' });
+
+ dispatch(setStudyGroup(group));
+ dispatch(clearWriteFields());
+};
+
export default reducer;
diff --git a/src/reducers/slice.test.js b/src/reducers/slice.test.js
index b98380d..4b416d1 100644
--- a/src/reducers/slice.test.js
+++ b/src/reducers/slice.test.js
@@ -9,10 +9,13 @@ import reducer, {
setStudyGroup,
loadStudyGroup,
changeWriteField,
+ writeStudyGroup,
+ clearWriteFields,
} from './slice';
import STUDY_GROUPS from '../../fixtures/study-groups';
import STUDY_GROUP from '../../fixtures/study-group';
+import WRITE_FORM from '../../fixtures/write-form';
const middlewares = [thunk];
const mockStore = configureStore(middlewares);
@@ -108,6 +111,24 @@ describe('reducer', () => {
expect(state.writeField.tags).toEqual(['JavaScript', 'React']);
});
});
+
+ describe('clearWriteFields', () => {
+ const initialState = {
+ writeField: {
+ title: '타이틀',
+ contents: '내용',
+ },
+ };
+
+ it('clears fields of write', () => {
+ const state = reducer(initialState, clearWriteFields());
+
+ const { writeField: { title, contents } } = state;
+
+ expect(title).toBe('');
+ expect(contents).toBe('');
+ });
+ });
});
describe('async actions', () => {
@@ -141,7 +162,24 @@ describe('async actions', () => {
const actions = store.getActions();
expect(actions[0]).toEqual(setStudyGroup(null));
- expect(actions[1]).toEqual(setStudyGroup([]));
+ expect(actions[1]).toEqual(setStudyGroup(undefined));
+ });
+ });
+
+ describe('writeStudyGroup', () => {
+ beforeEach(() => {
+ store = mockStore({
+ writeField: WRITE_FORM,
+ });
+ });
+
+ it('dispatches clearWriteFields', async () => {
+ await store.dispatch(writeStudyGroup());
+
+ const actions = store.getActions();
+
+ expect(actions[0]).toEqual(setStudyGroup(undefined));
+ expect(actions[1]).toEqual(clearWriteFields(undefined));
});
});
});
diff --git a/src/services/__mocks__/api.js b/src/services/__mocks__/api.js
index bcf0b9b..55c13c7 100644
--- a/src/services/__mocks__/api.js
+++ b/src/services/__mocks__/api.js
@@ -1,3 +1,5 @@
export const getStudyGroups = async () => [];
-export const getStudyGroup = async () => [];
+export const getStudyGroup = async () => {};
+
+export const postStudyGroup = async () => {};
diff --git a/src/services/api.js b/src/services/api.js
index be36463..2fb9f44 100644
--- a/src/services/api.js
+++ b/src/services/api.js
@@ -9,3 +9,8 @@ export const getStudyGroup = async (id) => {
const response = await axios.get(`http://localhost:3000/groups/${id}`);
return response.data;
};
+
+export const postStudyGroup = async (post) => {
+ const response = await axios.post('http://localhost:3000/groups/', post);
+ return response.data;
+};
diff --git a/src/services/api.test.js b/src/services/api.test.js
index c2f5fc6..baae116 100644
--- a/src/services/api.test.js
+++ b/src/services/api.test.js
@@ -3,6 +3,7 @@ import axios from 'axios';
import {
getStudyGroup,
getStudyGroups,
+ postStudyGroup,
} from './api';
import STUDY_GROUPS from '../../fixtures/study-groups';
@@ -39,4 +40,19 @@ describe('api', () => {
);
});
});
+
+ describe('postStudyGroup', () => {
+ beforeEach(() => {
+ axios.post.mockResolvedValue({ data: STUDY_GROUP });
+ });
+
+ it('returns study group post', async () => {
+ await expect(postStudyGroup(STUDY_GROUP)).resolves.toEqual(STUDY_GROUP);
+
+ expect(axios.post).toHaveBeenCalledWith(
+ 'http://localhost:3000/groups/',
+ STUDY_GROUP,
+ );
+ });
+ });
});