Skip to content

Commit 580c88f

Browse files
authored
Merge pull request #442 from Moadong/feature/#441-add-string-to-date-unit-test-FE-123
[feature] stringToDate 유틸리티 함수 단위 테스트 추가
2 parents 367fb3d + 53975a8 commit 580c88f

File tree

7 files changed

+119
-23
lines changed

7 files changed

+119
-23
lines changed

frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import Calendar from '@/pages/AdminPage/tabs/RecruitEditTab/components/Calendar/
55
import Button from '@/components/common/Button/Button';
66
import InputField from '@/components/common/InputField/InputField';
77
import { useUpdateClubDescription } from '@/hooks/queries/club/useUpdateClubDescription';
8-
import { parseRecruitmentPeriod } from '@/utils/stringToDate';
8+
import { parseRecruitmentPeriod } from '@/utils/recruitmentPeriodParser.ts';
99
import { ClubDetail } from '@/types/club';
1010
import { useQueryClient } from '@tanstack/react-query';
1111
import MarkdownEditor from '@/pages/AdminPage/tabs/RecruitEditTab/components/MarkdownEditor/MarkdownEditor';

frontend/src/pages/ClubDetailPage/components/ClubDetailFooter/ClubDetailFooter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as Styled from './ClubDetailFooter.styles';
22
import DeadlineBadge from '@/pages/ClubDetailPage/components/DeadlineBadge/DeadlineBadge';
33
import ClubApplyButton from '@/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton';
4-
import { parseRecruitmentPeriod } from '@/utils/stringToDate';
4+
import { parseRecruitmentPeriod } from '@/utils/recruitmentPeriodParser.ts';
55
import getDeadlineText from '@/utils/getDeadLineText';
66

77
interface ClubDetailFooterProps {

frontend/src/pages/ClubDetailPage/components/ClubDetailHeader/ClubDetailHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as Styled from './ClubDetailHeader.styles';
22
import ClubProfile from '@/pages/ClubDetailPage/components/ClubProfile/ClubProfile';
33
import ClubApplyButton from '@/pages/ClubDetailPage/components/ClubApplyButton/ClubApplyButton';
4-
import { parseRecruitmentPeriod } from '@/utils/stringToDate';
4+
import { parseRecruitmentPeriod } from '@/utils/recruitmentPeriodParser.ts';
55
import getDeadlineText from '@/utils/getDeadLineText';
66
interface ClubDetailHeaderProps {
77
name: string;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { parseRecruitmentPeriod } from './recruitmentPeriodParser.ts';
2+
3+
describe('parseRecruitmentPeriod 함수 테스트', () => {
4+
it('올바른 형식의 날짜를 파싱한다.', () => {
5+
const input = '2024.03.20 14:00 ~ 2024.03.25 18:00';
6+
const result = parseRecruitmentPeriod(input);
7+
8+
expect(result.recruitmentStart).toEqual(new Date('2024-03-20T14:00:00'));
9+
expect(result.recruitmentEnd).toEqual(new Date('2024-03-25T18:00:00'));
10+
});
11+
12+
it('날짜가 기간형식이 아닌 단일 날짜 형식인 경우 null을 반환한다.', () => {
13+
const input = '2024.03.20 14:00';
14+
const result = parseRecruitmentPeriod(input);
15+
16+
expect(result.recruitmentStart).toBeNull();
17+
expect(result.recruitmentEnd).toBeNull();
18+
});
19+
20+
it('빈 문자열이라면 null을 반환한다.', () => {
21+
const input = '';
22+
const result = parseRecruitmentPeriod(input);
23+
24+
expect(result.recruitmentStart).toBeNull();
25+
expect(result.recruitmentEnd).toBeNull();
26+
});
27+
28+
it('날짜 사이 ~가 없다면 null을 반환한다.', () => {
29+
const input = '2024.03.20 14:00 - 2024.03.25 18:00';
30+
const result = parseRecruitmentPeriod(input);
31+
32+
expect(result.recruitmentStart).toBeNull();
33+
expect(result.recruitmentEnd).toBeNull();
34+
});
35+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { parseRecruitmentDateString } from './recruitmentPeriodParser.ts';
2+
3+
describe('parseRecruitmentPeriod 함수 테스트', () => {
4+
it('날짜와 시간이 포함된 문자열을 Date 객체로 정확히 바꾼다', () => {
5+
const input = '2025.05.25 13:45';
6+
const result = new Date('2025-05-25T13:45:00');
7+
expect(parseRecruitmentDateString(input)).toEqual(result);
8+
});
9+
10+
it('자정 시간 "YYYY.MM.DD 00:00" 형식을 올바르게 Date 객체로 변환한다', () => {
11+
const input = '2025.05.25 00:00';
12+
const result = new Date('2025-05-25T00:00:00');
13+
expect(parseRecruitmentDateString(input)).toEqual(result);
14+
});
15+
16+
it('공백이 없는 문자열이라면 예외가 발생한다.', () => {
17+
const input = '2025.05.2513:45';
18+
expect(() => parseRecruitmentDateString(input)).toThrow(
19+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
20+
);
21+
});
22+
23+
it('시간 부분이 누락된 경우 예외가 발생한다', () => {
24+
const input = '2025.05.25 ';
25+
expect(() => parseRecruitmentDateString(input)).toThrow(
26+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
27+
);
28+
});
29+
30+
it('날짜 부분이 누락된 경우 예외가 발생한다', () => {
31+
const input = ' 13:45';
32+
expect(() => parseRecruitmentDateString(input)).toThrow(
33+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
34+
);
35+
});
36+
37+
it('빈 문자열이 주어지면 예외가 발생한다', () => {
38+
const input = '';
39+
expect(() => parseRecruitmentDateString(input)).toThrow(
40+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
41+
);
42+
});
43+
44+
it('YYYY.MM.DD HH:mm 형식이 아닌 입력에 대해 에러를 던진다', () => {
45+
const input = '1.1.1 1:1';
46+
expect(() => parseRecruitmentDateString(input)).toThrow(
47+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
48+
);
49+
});
50+
});
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { parse, isValid } from 'date-fns';
2+
3+
export const parseRecruitmentDateString = (s: string): Date => {
4+
const regex = /^\d{4}\.\d{2}\.\d{2} \d{2}:\d{2}$/;
5+
if (!regex.test(s)) {
6+
throw new Error(
7+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
8+
);
9+
}
10+
const date = parse(s, 'yyyy.MM.dd HH:mm', new Date());
11+
if (!isValid(date)) {
12+
throw new Error(
13+
'유효하지 않은 날짜 형식입니다. 형식은 "YYYY.MM.DD HH:mm" 이어야 합니다.',
14+
);
15+
}
16+
return date;
17+
};
18+
19+
export const parseRecruitmentPeriod = (
20+
periodStr: string,
21+
): { recruitmentStart: Date | null; recruitmentEnd: Date | null } => {
22+
const parts = periodStr.split('~').map((s) => s.trim());
23+
if (parts.length !== 2) {
24+
return { recruitmentStart: null, recruitmentEnd: null };
25+
}
26+
27+
return {
28+
recruitmentStart: parseRecruitmentDateString(parts[0]),
29+
recruitmentEnd: parseRecruitmentDateString(parts[1]),
30+
};
31+
};

frontend/src/utils/stringToDate.ts

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)