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
4 changes: 1 addition & 3 deletions fixtures/study-group.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ const studyGroup = {
title: '스터디를 소개합니다.2',
moderatorId: 'user2',
applyEndDate: '2020-12-23',
participants: [
{ id: 'user2' },
],
participants: [],
personnel: 2,
contents: '우리는 이것저것 합니다.2',
tags: [
Expand Down
92 changes: 92 additions & 0 deletions src/components/introduce/ApplicantViewButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import React, { useState } from 'react';

import { changeDateToTime, isCheckedTimeStatus } from '../../util/utils';

import ApplyStatusButton from './ApplyStatusButton';
import ApplicationFormModal from './modals/ApplicationFormModal';
import AskApplyCancelModal from './modals/AskApplyCancelModal';
import AskLoginModal from './modals/AskLoginModal';

const ApplicantViewButton = ({
group, onApply, user, realTime, onApplyCancel, onChangeApplyFields, applyFields, clearForm,
}) => {
const [loginCheckModal, setLoginCheckModal] = useState(false);
const [applyCancelModal, setApplyCancelModal] = useState(false);
const [modalForm, setModalForm] = useState(false);

const {
moderatorId, participants, applyEndDate,
} = group;

const applyEndTime = changeDateToTime(applyEndDate);

const handleApplyCancelConfirmClick = () => {
setApplyCancelModal(true);
};

const handleLoginCheckCancel = () => {
setLoginCheckModal(false);
};

const handleApplyCancel = () => {
setApplyCancelModal(false);
};

const handleApplyCancelConfirm = () => {
setApplyCancelModal(false);
onApplyCancel();
};

const handleApply = () => {
if (!user) {
setLoginCheckModal(true);
return;
}

setModalForm(true);
};

const handleFormSubmit = () => {
setModalForm(false);
onApply(applyFields);
};

const handleFormCancel = () => {
setModalForm(false);
clearForm();
};

if (moderatorId === user) {
return null;
}

return (
<>
<ApplyStatusButton
user={user}
onApply={handleApply}
onCancel={handleApplyCancelConfirmClick}
applyStatus={participants.some(({ id }) => id === user)}
timeStatus={isCheckedTimeStatus({ ...group, time: realTime, applyEndTime })}
/>
<AskLoginModal
visible={loginCheckModal}
onCancel={handleLoginCheckCancel}
/>
<AskApplyCancelModal
visible={applyCancelModal}
onCancel={handleApplyCancel}
onConfirm={handleApplyCancelConfirm}
/>
<ApplicationFormModal
visible={modalForm}
onCancel={handleFormCancel}
onConfirm={handleFormSubmit}
onChangeApply={onChangeApplyFields}
fields={applyFields}
/>
</>
);
};

export default ApplicantViewButton;
253 changes: 253 additions & 0 deletions src/components/introduce/ApplicantViewButton.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
import React from 'react';

import { fireEvent, render } from '@testing-library/react';

import ApplicantViewButton from './ApplicantViewButton';

import STUDY_GROUP from '../../../fixtures/study-group';

describe('ApplicantViewButton', () => {
const handleApply = jest.fn();
const handleApplyCancel = jest.fn();
const handleClearForm = jest.fn();

beforeEach(() => {
jest.clearAllMocks();
});

const renderApplicantViewButton = ({ group, time, user }) => render((
<ApplicantViewButton
user={user}
group={group}
applyFields={{ reason: 'reason', wantToGet: 'reason' }}
realTime={time}
onApply={handleApply}
onApplyCancel={handleApplyCancel}
clearForm={handleClearForm}
/>
));

context('When the host and logged in user are the same', () => {
const group = {
...STUDY_GROUP,
moderatorId: 'user',
};

it('nothing renders', () => {
const { container } = renderApplicantViewButton({ group, user: 'user' });

expect(container).toBeEmptyDOMElement();
});
});

context('When the organizer and the logged-in user are different', () => {
context(`When the application date is earlier than the
deadline date and the application deadline is not reached`, () => {
const time = Date.now();

const nowDate = new Date();
const tomorrow = nowDate.setDate(nowDate.getDate() + 1);

const group = {
...STUDY_GROUP,
applyEndDate: tomorrow,
participants: [
{ id: 'user2' },
{ id: 'user' },
],
personnel: 3,
};

context('click confirm', () => {
it('Call the cancel application button.', () => {
const { getByText } = renderApplicantViewButton({ group, user: 'user', time });

const button = getByText('신청 취소');

expect(button).not.toBeNull();

fireEvent.click(button);

fireEvent.click(getByText('확인'));

expect(handleApplyCancel).toBeCalled();
});
});

context('click cancel', () => {
it("doesn't call the cancel application button.", () => {
const { getByText } = renderApplicantViewButton({ group, user: 'user', time });

const button = getByText('신청 취소');

expect(button).not.toBeNull();

fireEvent.click(button);

fireEvent.click(getByText('취소'));

expect(handleApplyCancel).not.toBeCalled();
});
});
});

context('When the author and the logged-in user have the same ID', () => {
it("doesn't renders apply button", () => {
const { container } = renderApplicantViewButton({ group: STUDY_GROUP, user: 'user2' });

expect(container).not.toHaveTextContent('신청하기');
});
});

context('When the study recruitment is closed', () => {
const time = Date.now();

describe('current time is after the recruitment deadline', () => {
const nowDate = new Date();
const yesterday = nowDate.setDate(nowDate.getDate() - 1);

const group = {
...STUDY_GROUP,
applyEndDate: yesterday,
participants: [
{ id: 'user2' },
],
personnel: 2,
};

it('renders recruitment closed text', () => {
const { container } = renderApplicantViewButton({ group, time });

expect(container).toHaveTextContent('모집 마감');
});
});

describe('When the number of study group participants equals the maximum number of participants', () => {
const nowDate = new Date();
const tomorrow = nowDate.setDate(nowDate.getDate() + 1);

const group = {
...STUDY_GROUP,
applyEndDate: tomorrow,
participants: [
{ id: 'user2' },
{ id: 'user3' },
],
personnel: 2,
};

it('renders recruitment closed text', () => {
const { container } = renderApplicantViewButton({ group, time });

expect(container).toHaveTextContent('모집 마감');
});
});

describe('When the user clicks the Apply button without logging in', () => {
const nowDate = new Date();
const tomorrow = nowDate.setDate(nowDate.getDate() + 1);

const group = {
...STUDY_GROUP,
applyEndDate: tomorrow,
participants: [
{ id: 'user2' },
],
personnel: 2,
};

it('renders modal window appears and application failure message', () => {
const { container, getByText } = renderApplicantViewButton({ group, time });

const button = getByText('신청하기');

expect(button).not.toBeNull();

fireEvent.click(button);

expect(handleApply).not.toBeCalled();

expect(container).toHaveTextContent('로그인 후 신청 가능합니다.');

fireEvent.click(getByText('확인'));

expect(container).not.toHaveTextContent('로그인 후 신청 가능합니다.');
});
});
});

context('When the study recruitment is opened', () => {
const time = Date.now();

describe(`current time is before the recruitment deadline and
when the number of study group participants is less than the maximum number of participants`, () => {
const nowDate = new Date();
const tomorrow = nowDate.setDate(nowDate.getDate() + 1);

const group = {
...STUDY_GROUP,
applyEndDate: tomorrow,
participants: [
{ id: 'user2' },
],
personnel: 2,
};

it('renders recruitment apply text', () => {
const { container } = renderApplicantViewButton({ group, time });

expect(container).toHaveTextContent('신청하기');
expect(container).not.toHaveTextContent('모집마감');
});
});

describe('When the user clicks the Apply button after logging in', () => {
const nowDate = new Date();
const tomorrow = nowDate.setDate(nowDate.getDate() + 1);

const group = {
...STUDY_GROUP,
applyEndDate: tomorrow,
participants: [
{ id: 'user2' },
],
personnel: 2,
};

context('Click confirm Study participation application', () => {
it('renders modal window appears and application failure message', () => {
const { container, getByText } = renderApplicantViewButton({ group, time, user: 'user' });

const button = getByText('신청하기');

expect(button).not.toBeNull();

fireEvent.click(button);

fireEvent.click(getByText('확인'));

expect(handleApply).toBeCalled();

expect(container).not.toHaveTextContent('로그인 후 신청 가능합니다.');
});
});

context('Click cancel Study participation application', () => {
it('renders modal window appears and application failure message', () => {
const { getByText } = renderApplicantViewButton({ group, time, user: 'user' });

const button = getByText('신청하기');

expect(button).not.toBeNull();

fireEvent.click(button);

fireEvent.click(getByText('취소'));

expect(handleApply).not.toBeCalled();
});
});
});
});
});
});
Loading