Skip to content
Snippets Groups Projects
Commit 490d41b6 authored by tpgus2603's avatar tpgus2603
Browse files

test,refactor 서비스로직 관련 테스트 및 리팩토링

parent fd2daa22
No related branches found
No related tags found
2 merge requests!31Develop,!14[#11] dto설정, 프렌드,서비스로직 테스트 및 로직변경
......@@ -4,7 +4,7 @@ const sequelize = require('../config/sequelize');
const User = require('../models/User');
const Friend = require('../models/Friend');
const Schedule = require('../models/Schedule');
const scheduleService = require('../services/scheduleService'); // scheduleService 임포트
const scheduleService = require('./scheduleService'); // scheduleService 임포트
beforeAll(async () => {
await sequelize.sync({ force: true });
......@@ -62,6 +62,7 @@ describe('Schedule Service', () => {
const schedule = await scheduleService.createSchedule(scheduleData);
expect(schedule).toBeDefined();
expect(schedule.user_id).toBe(2);
expect(schedule.title).toBe('Bob\'s Fixed Schedule');
......@@ -158,7 +159,7 @@ describe('Schedule Service', () => {
test('should delete an existing schedule successfully', async () => {
const result = await scheduleService.deleteSchedule(2, 1);
expect(result).toBe(true);
expect(result).toEqual({ message: 'Schedule successfully deleted' });
// 삭제된 스케줄이 실제로 삭제되었는지 확인
const schedule = await Schedule.findByPk(2);
......@@ -192,23 +193,29 @@ describe('Schedule Service', () => {
await expect(scheduleService.getScheduleById(999, 1)).rejects.toThrow('Schedule not found');
});
});
// test/schedule.test.js
describe('cleanExpiredSchedules', () => {
test('should delete expired flexible schedules', async () => {
// 현재 날짜를 기준으로 만료된 스케줄과 만료되지 않은 스케줄 생성
const now = new Date('2024-05-07T00:00:00Z'); // 테스트를 위한 고정된 현재 날짜
// Jest의 Fake Timers를 사용하여 Date를 고정
jest.useFakeTimers('modern');
jest.setSystemTime(now);
// 만료된 유동 스케줄 생성
await Schedule.create({
id: 3,
user_id: 1,
title: 'Expired Flexible Schedule',
start_time: new Date('2024-04-25T10:00:00Z'),
end_time: new Date('2024-04-25T11:00:00Z'),
is_fixed: false,
expiry_date: new Date('2024-04-30T00:00:00Z'), // 이미 만료됨
expiry_date: new Date('2024-05-06T00:00:00Z'), // 이미 만료됨
});
// 만료되지 않은 유동 스케줄 생성
await Schedule.create({
id: 4,
user_id: 1,
title: 'Valid Flexible Schedule',
start_time: new Date('2024-05-07T10:00:00Z'),
......@@ -221,13 +228,17 @@ describe('Schedule Service', () => {
await scheduleService.cleanExpiredSchedules();
// 만료된 스케줄이 삭제되었는지 확인
const expiredSchedule = await Schedule.findByPk(3);
const expiredSchedule = await Schedule.findOne({ where: { title: 'Expired Flexible Schedule' } });
expect(expiredSchedule).toBeNull();
// 만료되지 않은 스케줄은 남아있는지 확인
const validSchedule = await Schedule.findByPk(4);
const validSchedule = await Schedule.findOne({ where: { title: 'Valid Flexible Schedule' } });
expect(validSchedule).toBeDefined();
expect(validSchedule.title).toBe('Valid Flexible Schedule');
// Jest의 Fake Timers를 복구
jest.useRealTimers();
});
});
});
......@@ -5,7 +5,6 @@ const Schedule = require('../models/Schedule');
const ScheduleResponseDTO = require('../dtos/ScheduleResponseDTO');
class scheduleService {
/**
* 트랜잭션 래퍼 함수
*/
......@@ -31,9 +30,9 @@ class scheduleService {
{ is_fixed: true },
{
is_fixed: false,
expiry_date: { [Op.gt]: new Date() }
}
]
expiry_date: { [Op.gt]: new Date() },
},
],
};
if (id) {
......@@ -45,10 +44,11 @@ class scheduleService {
/**
* 스케줄 유효성 검사
* 이미 컨트롤러에서 검증했으므로, 추가 검증 필요 시 수행
*/
validateScheduleTime(start_time, end_time) {
if (new Date(start_time) >= new Date(end_time)) {
throw new Error('Start time must be before end time');
throw new Error("Start time must be before end time");
}
}
......@@ -57,12 +57,20 @@ class scheduleService {
*/
getNextMonday(startTime) {
const date = new Date(startTime);
const day = date.getDay();
const daysUntilNextMonday = (7 - day + 1) % 7;
const nextMonday = new Date(date);
nextMonday.setDate(date.getDate() + daysUntilNextMonday);
nextMonday.setHours(0, 0, 0, 0); // 자정으로 설정
const day = date.getUTCDay(); // 0=Sunday, 1=Monday, ..., 6=Saturday
const daysUntilNextMonday = (8 - day) % 7 || 7; // Ensure next Monday
const nextMonday = new Date(
Date.UTC(
date.getUTCFullYear(),
date.getUTCMonth(),
date.getUTCDate() + daysUntilNextMonday,
0,
0,
0,
0 // Set to midnight UTC
)
);
return nextMonday;
}
......@@ -73,9 +81,14 @@ class scheduleService {
async createSchedule({ userId, title, start_time, end_time, is_fixed }) {
const schedule = await this.withTransaction(async (transaction) => {
this.validateScheduleTime(start_time, end_time);
const overlap = await this.checkScheduleOverlap(userId, start_time, end_time);
const overlap = await this.checkScheduleOverlap(
userId,
start_time,
end_time
);
if (overlap) {
throw new Error('Schedule overlaps with existing schedule');
throw new Error("Schedule overlaps with existing schedule");
}
const scheduleData = {
......@@ -84,7 +97,7 @@ class scheduleService {
start_time,
end_time,
is_fixed,
expiry_date: is_fixed ? null : this.getNextMonday(start_time)
expiry_date: is_fixed ? null : this.getNextMonday(start_time),
};
return Schedule.create(scheduleData, { transaction });
......@@ -100,30 +113,35 @@ class scheduleService {
const updatedSchedule = await this.withTransaction(async (transaction) => {
const schedule = await Schedule.findOne({
where: { id, user_id: userId },
transaction
transaction,
});
if (!schedule) {
throw new Error('Schedule not found');
throw new Error("Schedule not found");
}
// 이미 컨트롤러에서 검증했으므로, 추가 검증이 필요하다면 수행
if (updateData.start_time && updateData.end_time) {
this.validateScheduleTime(updateData.start_time, updateData.end_time);
}
const overlap = await this.checkScheduleOverlap(
userId,
updateData.start_time,
updateData.end_time,
updateData.start_time || schedule.start_time,
updateData.end_time || schedule.end_time,
id
);
if (overlap) {
throw new Error('Schedule overlaps with existing schedule');
throw new Error("Schedule overlaps with existing schedule");
}
const is_fixed = schedule.is_fixed;
const updatedDataWithExpiry = {
...updateData,
expiry_date: is_fixed ? null : this.getNextMonday(updateData.start_time),
updatedAt: new Date()
expiry_date: is_fixed
? null
: this.getNextMonday(updateData.start_time || schedule.start_time),
updatedAt: new Date(),
};
delete updatedDataWithExpiry.is_fixed;
......@@ -140,15 +158,15 @@ class scheduleService {
return this.withTransaction(async (transaction) => {
const result = await Schedule.destroy({
where: { id, user_id: userId },
transaction
transaction,
});
if (!result) {
throw new Error('Schedule not found');
throw new Error("Schedule not found");
}
// 삭제 성공 메시지 반환
return { message: 'Schedule successfully deleted' };
return { message: "Schedule successfully deleted" };
});
}
......@@ -159,9 +177,11 @@ class scheduleService {
try {
const schedules = await Schedule.findAll({
where: this.getScheduleWhereClause(userId),
order: [['start_time', 'ASC']]
order: [["start_time", "ASC"]],
});
const schedulesDTO = schedules.map(schedule => new ScheduleResponseDTO(schedule));
const schedulesDTO = schedules.map(
(schedule) => new ScheduleResponseDTO(schedule)
);
return schedulesDTO;
} catch (error) {
throw new Error(`Failed to fetch schedules: ${error.message}`);
......@@ -174,11 +194,11 @@ class scheduleService {
async getScheduleById(id, userId) {
try {
const schedule = await Schedule.findOne({
where: this.getScheduleWhereClause(userId, id)
where: this.getScheduleWhereClause(userId, id),
});
if (!schedule) {
throw new Error('Schedule not found');
throw new Error("Schedule not found");
}
return new ScheduleResponseDTO(schedule);
......@@ -195,8 +215,8 @@ class scheduleService {
await Schedule.destroy({
where: {
is_fixed: false,
expiry_date: { [Op.lte]: new Date() }
}
expiry_date: { [Op.lte]: new Date() },
},
});
} catch (error) {
throw new Error(`Failed to clean expired schedules: ${error.message}`);
......@@ -214,16 +234,16 @@ class scheduleService {
{
[Op.and]: [
{ start_time: { [Op.lte]: start_time } },
{ end_time: { [Op.gte]: start_time } }
]
{ end_time: { [Op.gte]: start_time } },
],
},
{
[Op.and]: [
{ start_time: { [Op.gte]: start_time } },
{ start_time: { [Op.lte]: end_time } }
]
}
]
{ start_time: { [Op.lte]: end_time } },
],
},
],
};
if (excludeId) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment