Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions src/components/main/StudyGroups.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react';

import { Link } from 'react-router-dom';

import styled from '@emotion/styled';

import palette from '../../styles/palette';

import StudyGroup from './StudyGroup';

const StudyGroupsWrapper = styled.div`
Expand All @@ -11,16 +15,44 @@ const StudyGroupsWrapper = styled.div`
align-content: space-between;
`;

const StudyGroups = ({ groups, realTime }) => (
<StudyGroupsWrapper>
{groups.map((group) => (
<StudyGroup
key={group.id}
group={group}
realTime={realTime}
/>
))}
</StudyGroupsWrapper>
const TitleHeader = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
// TODO: Link 공통 style component 만들기
a {
margin-right: 4rem;
padding: .6rem .9rem .6rem .9rem;
border: 1px solid ${palette.gray[7]};
background: white;
color: ${palette.gray[7]};
font-weight: bold;
border-radius: .7rem;
:hover {
color: white;
background: ${palette.gray[7]};
}
}
`;

const StudyGroups = ({ groups, realTime, user }) => (
<>
<TitleHeader>
<h2>지금 바로 시작하세요!</h2>
{user && (
<Link to="/write">스터디 개설하기</Link>
)}
</TitleHeader>
<StudyGroupsWrapper>
{groups.map((group) => (
<StudyGroup
key={group.id}
group={group}
realTime={realTime}
/>
))}
</StudyGroupsWrapper>
</>
);

export default StudyGroups;
2 changes: 2 additions & 0 deletions src/containers/groups/StudyGroupsContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const StudyGroupsContainer = () => {
const dispatch = useDispatch();

const groups = useSelector(get('groups'));
const user = useSelector(get('user'));

useInterval(() => {
setRealTime(Date.now());
Expand All @@ -37,6 +38,7 @@ const StudyGroupsContainer = () => {

return (
<StudyGroups
user={user}
groups={groups}
realTime={realTime}
/>
Expand Down
11 changes: 10 additions & 1 deletion src/containers/write/WriteButtonsContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ import WriteButtons from '../../components/write/WriteButtons';

const isCheckApplyEndDate = (applyDate) => Date.now() - applyDate >= 0;

const { NO_INPUT, NO_TAG, FAST_APPLY_DEADLINE } = ERROR_MESSAGE;
const {
NO_INPUT, NO_TAG, FAST_APPLY_DEADLINE, NO_LOGGED_IN,
} = ERROR_MESSAGE;

const WriteButtonsContainer = () => {
const [error, setError] = useState(null);
Expand All @@ -21,6 +23,7 @@ const WriteButtonsContainer = () => {

const writeField = useSelector(get('writeField'));
const groupId = useSelector(get('groupId'));
const user = useSelector(get('user'));

const {
title, applyEndDate, personnel, tags,
Expand All @@ -29,6 +32,12 @@ const WriteButtonsContainer = () => {
const applyEndTime = new Date(applyEndDate).getTime();

const onSubmit = () => {
// TODO: 모달창으로 처리 후 redirection 시키기?
if (!user) {
setError(NO_LOGGED_IN);
return;
}

if (isCheckValidate([title, applyEndDate, personnel])) {
setError(NO_INPUT);
return;
Expand Down
179 changes: 105 additions & 74 deletions src/containers/write/WriteButtonsContainer.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ describe('WriteButtonsContainer', () => {
useSelector.mockImplementation((state) => state({
writeField: given.writeField,
groupId: given.groupId,
user: given.user,
}));
});

Expand Down Expand Up @@ -62,101 +63,131 @@ describe('WriteButtonsContainer', () => {
});

describe('when click submit button', () => {
context('without input value null, so validation check success', () => {
given('writeField', () => (WRITE_FORM));
context('with user', () => {
given('user', () => ('user'));

context('with group', () => {
given('groupId', () => ('1'));
context('without input value null, so validation check success', () => {
given('writeField', () => (WRITE_FORM));

it('dispatch action writeStudyGroup event', () => {
const { getByText } = renderWriteButtonsContainer();
context('with group', () => {
given('groupId', () => ('1'));

fireEvent.click(getByText('등록하기'));
it('dispatch action writeStudyGroup event', () => {
const { getByText } = renderWriteButtonsContainer();

expect(dispatch).toBeCalledTimes(1);
fireEvent.click(getByText('등록하기'));

expect(mockPush).toBeCalledWith('/introduce/1');
expect(dispatch).toBeCalledTimes(1);

expect(mockPush).toBeCalledWith('/introduce/1');
});
});
});

context('without group', () => {
given('groupId', () => (null));
context('without group', () => {
given('groupId', () => (null));

it('dispatch action submit event', () => {
const { getByText } = renderWriteButtonsContainer();
it('dispatch action submit event', () => {
const { getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));
fireEvent.click(getByText('등록하기'));

expect(mockPush).not.toBeCalled();
expect(mockPush).not.toBeCalled();
});
});
});
});
context('with input value null, so validation check failure', () => {
describe('When the title and applyEndDate, personnel are blank', () => {
given('writeField', () => ({
title: '',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: '',
participants: [],
personnel: '',
tags: [
'JavaScript',
'Algorithm',
],
}));

it('renders error message "There are some items that have not been entered."', () => {
const { container, getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));

expect(container).toHaveTextContent('입력이 안된 사항이 있습니다.');

context('with input value null, so validation check failure', () => {
describe('When the title and applyEndDate, personnel are blank', () => {
given('writeField', () => ({
title: '',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: '',
participants: [],
personnel: '',
tags: [
'JavaScript',
'Algorithm',
],
}));

it('renders error message "There are some items that have not been entered."', () => {
const { container, getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));

expect(container).toHaveTextContent('입력이 안된 사항이 있습니다.');
});
});
});

describe('When the length of tags is 0', () => {
given('writeField', () => ({
title: '123',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: new Date().toString(),
participants: [],
personnel: '1',
tags: [],
}));
describe('When the length of tags is 0', () => {
given('writeField', () => ({
title: '123',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: new Date().toString(),
participants: [],
personnel: '1',
tags: [],
}));

it('renders error message "Please enter a tag."', () => {
const { container, getByText } = renderWriteButtonsContainer();
it('renders error message "Please enter a tag."', () => {
const { container, getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));
fireEvent.click(getByText('등록하기'));

expect(container).toHaveTextContent('태그를 입력하세요.');
expect(container).toHaveTextContent('태그를 입력하세요.');
});
});
});

describe('When the application deadline is earlier than the current time', () => {
given('writeField', () => ({
title: '123',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: '2020-10-01',
participants: [],
personnel: '1',
tags: [
'javascript',
'react',
],
}));

it('renders error message "The application deadline is earlier than the current time."', () => {
const { container, getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));

expect(container).toHaveTextContent('접수 마감날짜가 현재 시간보다 빠릅니다.');
describe('When the application deadline is earlier than the current time', () => {
given('writeField', () => ({
title: '123',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: '2020-10-01',
participants: [],
personnel: '1',
tags: [
'javascript',
'react',
],
}));

it('renders error message "The application deadline is earlier than the current time."', () => {
const { container, getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));

expect(container).toHaveTextContent('접수 마감날짜가 현재 시간보다 빠릅니다.');
});
});
});
});

context('without user', () => {
given('user', () => (null));

given('writeField', () => ({
title: '123',
contents: '우리는 이것저것 합니다.1',
moderatorId: 'user1',
applyEndDate: '2020-10-01',
participants: [],
personnel: '1',
tags: [
'javascript',
'react',
],
}));

it('renders error message "Please use after logging in"', () => {
const { container, getByText } = renderWriteButtonsContainer();

fireEvent.click(getByText('등록하기'));

expect(container).toHaveTextContent('로그인 후 이용하세요.');
});
});
});
});
38 changes: 3 additions & 35 deletions src/pages/MainPage.jsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,13 @@
import React from 'react';

import { Link } from 'react-router-dom';

import styled from '@emotion/styled';

import StudyGroupsContainer from '../containers/groups/StudyGroupsContainer';
import Responsive from '../styles/Responsive';
import palette from '../styles/palette';

const MainPageWrapper = styled(Responsive)`

`;

const TitleHeader = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
// TODO: Link 공통 style component 만들기
a {
margin-right: 4rem;
padding: .6rem .9rem .6rem .9rem;
border: 1px solid ${palette.gray[7]};
background: white;
color: ${palette.gray[7]};
font-weight: bold;
border-radius: .7rem;
:hover {
color: white;
background: ${palette.gray[7]};
}
}
`;
import StudyGroupsContainer from '../containers/groups/StudyGroupsContainer';

const MainPage = () => (
<MainPageWrapper>
<TitleHeader>
<h2>지금 바로 시작하세요!</h2>
<Link to="/write">스터디 개설하기</Link>
</TitleHeader>
<Responsive>
<StudyGroupsContainer />
</MainPageWrapper>
</Responsive>
);

export default MainPage;
Loading