Feat: msw 핸들러 추가

This commit is contained in:
정현조 2024-09-25 15:24:39 +09:00
parent 0de67e7f94
commit 4e844dd367
11 changed files with 1131 additions and 328 deletions

View File

@ -0,0 +1,19 @@
import { http, HttpResponse } from 'msw';
import { RefreshTokenResponse, MemberResponse } from '@/types';
export const authHandlers = [
http.post('/api/auth/reissue', () => {
const response: RefreshTokenResponse = { accessToken: 'newAccessToken' };
return HttpResponse.json(response);
}),
http.get('/api/auth/profile', () => {
const response: MemberResponse = {
id: 1,
nickname: 'javajoha',
profileImage: 'profile.jpg',
email: 'j9@naver.com',
};
return HttpResponse.json(response);
}),
];

View File

@ -0,0 +1,77 @@
import { http, HttpResponse } from 'msw';
import { LabelCategoryRequest, LabelCategoryResponse } from '@/types';
export const categoryHandlers = [
// 레이블 카테고리 리스트 조회 핸들러
http.get('/api/projects/:projectId/categories', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const categories: LabelCategoryResponse[] = [
{ id: 1, name: 'Category 1' },
{ id: 2, name: 'Category 2' },
];
return HttpResponse.json(categories);
}),
// 레이블 카테고리 추가 핸들러
http.post('/api/projects/:projectId/categories', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const categoryData = (await request.json()) as LabelCategoryRequest;
console.log(categoryData);
const newCategory: LabelCategoryResponse = {
id: Math.floor(Math.random() * 1000), // 임의로 ID 생성
name: `New Category for project ${projectId}`,
};
return HttpResponse.json(newCategory);
}),
// 레이블 카테고리 단일 조회 핸들러
http.get('/api/projects/:projectId/categories/:categoryId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const categoryId = Array.isArray(params.categoryId)
? parseInt(params.categoryId[0], 10)
: parseInt(params.categoryId as string, 10);
console.log(projectId);
const category: LabelCategoryResponse = {
id: categoryId,
name: `Category ${categoryId}`,
};
return HttpResponse.json(category);
}),
// 레이블 카테고리 삭제 핸들러
http.delete('/api/projects/:projectId/categories/:categoryId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const categoryId = Array.isArray(params.categoryId)
? parseInt(params.categoryId[0], 10)
: parseInt(params.categoryId as string, 10);
return HttpResponse.json({ message: `Category ${categoryId} deleted from project ${projectId}` });
}),
// 레이블 카테고리 존재 여부 조회 핸들러
http.get('/api/projects/:projectId/categories/exist', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const categoryName = Array.isArray(params.categoryName) ? params.categoryName[0] : params.categoryName;
const exists = categoryName === 'Category 1'; // 임의로 'Category 1'만 존재하는 것으로 설정
return HttpResponse.json(exists);
}),
];

View File

@ -0,0 +1,115 @@
import { http, HttpResponse } from 'msw';
import { FolderResponse, FolderRequest } from '@/types';
export const folderHandlers = [
// 특정 폴더 조회 핸들러
http.get('/api/projects/:projectId/folders/:folderId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10); // string으로 캐스팅
const folderId = Array.isArray(params.folderId)
? parseInt(params.folderId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const folderResponse: FolderResponse = {
id: folderId,
title: `Folder ${folderId}`,
images: [
{
id: 1,
imageTitle: 'image1.jpg',
imagePath: 'https://example.com/image1.jpg',
dataPath: 'https://example.com/data1.json',
status: 'PENDING',
},
],
children: [
{
id: 1,
title: 'Subfolder 1',
},
],
};
return HttpResponse.json(folderResponse);
}),
// 폴더 생성 핸들러
http.post('/api/projects/:projectId/folders', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10); // string으로 캐스팅
const folderData = (await request.json()) as FolderRequest;
const createdFolder: FolderResponse = {
id: Math.floor(Math.random() * 1000), // 임의로 폴더 ID 생성
title: folderData.title,
images: [],
children: [],
};
console.log(projectId);
return HttpResponse.json(createdFolder);
}),
// 폴더 수정 핸들러
http.put('/api/projects/:projectId/folders/:folderId', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10); // string으로 캐스팅
const folderId = Array.isArray(params.folderId)
? parseInt(params.folderId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const folderData = (await request.json()) as FolderRequest;
const updatedFolder: FolderResponse = {
id: folderId,
title: folderData.title,
images: [],
children: [],
};
return HttpResponse.json(updatedFolder);
}),
// 폴더 삭제 핸들러
http.delete('/api/projects/:projectId/folders/:folderId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10); // string으로 캐스팅
const folderId = Array.isArray(params.folderId)
? parseInt(params.folderId[0], 10)
: parseInt(params.projectId as string, 10);
return HttpResponse.json({ message: `Folder ${folderId} deleted from project ${projectId}` });
}),
// 폴더 리뷰 목록 조회 핸들러
http.get('/api/projects/:projectId/folders/:folderId/review', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const folderId = Array.isArray(params.folderId)
? parseInt(params.folderId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId, folderId);
const reviews = [
{
reviewId: 1,
title: 'First Review',
content: 'Review for the first folder',
status: 'APPROVED',
},
{
reviewId: 2,
title: 'Second Review',
content: 'Review for the second folder',
status: 'REQUESTED',
},
];
return HttpResponse.json(reviews);
}),
];

View File

@ -1,331 +1,24 @@
import { http, HttpResponse } from 'msw';
import {
ProjectResponse,
FolderResponse,
ImageResponse,
WorkspaceResponse,
MemberResponse,
RefreshTokenResponse,
AutoLabelingResponse,
ErrorResponse,
} from '@/types';
import { authHandlers } from './authHandlers';
import { labelHandlers } from './labelHandlers';
import { reviewHandlers } from './reviewHandlers';
import { categoryHandlers } from './categoryHandlers';
import { memberHandlers } from './memberHandlers';
import { workspaceHandlers } from './workspaceHandlers';
import { folderHandlers } from './folderHandler';
import { modelHandlers } from './modelHandlers';
import { imageHandlers } from './imageHandlers';
import { projectHandlers } from './projectHandlers';
// 모든 핸들러를 배열로 통합
export const handlers = [
// Auth Handlers
http.post('/api/auth/reissue', () => {
// 토큰 재발급 핸들러
const response: RefreshTokenResponse = {
accessToken: 'newAccessToken',
};
return HttpResponse.json(response);
}),
http.get('/api/auth/profile', () => {
// 사용자 프로필 핸들러
const response: MemberResponse = {
id: 1,
nickname: 'javajoha',
profileImage: 'profile.jpg',
email: 'j9@naver.com',
};
return HttpResponse.json(response);
}),
// Workspace Handlers
http.get('/api/workspaces/:workspaceId', ({ params }) => {
// 워크스페이스 조회 핸들러
const { workspaceId } = params;
const response: WorkspaceResponse = {
id: parseInt(workspaceId as string, 10),
memberId: 'abc1324',
title: 'workspace1',
content: '갤럭시 s24 불량 검증',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
};
return HttpResponse.json(response);
}),
http.put('/api/workspaces/:workspaceId', ({ params }) => {
// 워크스페이스 수정 핸들러
const { workspaceId } = params;
const response: WorkspaceResponse = {
id: parseInt(workspaceId as string, 10),
memberId: 'abc1324',
title: 'Updated Workspace Title',
content: 'Updated Workspace Content',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T06:00:00.668Z',
};
return HttpResponse.json(response);
}),
http.delete('/api/workspaces/:workspaceId', ({ params }) => {
const { workspaceId } = params;
console.log(workspaceId);
return HttpResponse.json({});
}),
http.get('/api/workspaces', () => {
// 워크스페이스 목록 조회 핸들러
const response: WorkspaceResponse[] = [
{
id: 1,
memberId: 'abc1324',
title: 'Workspace 1',
content: 'Content 1',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
},
];
return HttpResponse.json(response);
}),
// Project Handlers
http.get('/api/workspaces/:workspaceId/projects', ({ request, params }) => {
const workspaceId = parseInt(params.workspaceId as string, 10);
const url = new URL(request.url);
const lastProjectId = parseInt(url.searchParams.get('lastProjectId') || '0', 10);
const limit = parseInt(url.searchParams.get('limit') || '10', 10);
const projects: ProjectResponse[] = Array.from({ length: limit }, (_, index) => ({
id: lastProjectId + index + 1,
title: `프로젝트 ${lastProjectId + index + 1}`,
workspaceId,
projectType: ['classification', 'detection', 'segmentation'][index % 3] as
| 'classification'
| 'detection'
| 'segmentation',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
thumbnail: `thumbnail_${lastProjectId + index + 1}.jpg`,
}));
// 응답 생성
const response: ProjectResponse[] = projects;
return HttpResponse.json(response);
}),
http.get('/api/projects/:projectId', ({ params }) => {
// 프로젝트 조회 핸들러
const { projectId } = params;
const response: ProjectResponse = {
id: parseInt(projectId as string, 10),
title: 'Project Title',
workspaceId: 1,
projectType: 'classification',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
};
return HttpResponse.json(response);
}),
http.post('/api/workspaces/:workspaceId/projects', () => {
// 프로젝트 생성 핸들러
const response: ProjectResponse = {
id: 3,
title: 'New Project',
workspaceId: 1,
projectType: 'detection',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
};
return HttpResponse.json(response);
}),
http.put('/api/projects/:projectId', ({ params }) => {
// 프로젝트 수정 핸들러
const { projectId } = params;
const response: ProjectResponse = {
id: parseInt(projectId as string, 10),
title: 'Updated Project Title',
workspaceId: 1,
projectType: 'segmentation',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T06:00:00.668Z',
};
return HttpResponse.json(response);
}),
http.delete('/api/projects/:projectId', ({ params }) => {
const { projectId } = params;
console.log(projectId);
return HttpResponse.json({});
}),
http.post('/api/projects/:projectId/label/auto', () => {
const response: AutoLabelingResponse = {
imageId: 1,
imageUrl: 'image-url.jpg',
data: `{
"version": "0.1.0",
"task_type": "cls",
"shapes": [
{
"label": "NG",
"color": "#FF0000",
"points": [[0, 0]],
"group_id": null,
"shape_type": "point",
"flags": {}
}
],
"split": "none",
"imageHeight": 2000,
"imageWidth": 4000,
"imageDepth": 4
}`,
};
return HttpResponse.json(response);
}),
// DELETE: 프로젝트 멤버 제거 핸들러
http.delete('/api/projects/:projectId/members', ({ params }) => {
const { projectId } = params;
return HttpResponse.json({ message: `프로젝트 ${projectId}에서 멤버 제거 성공` });
}),
// PUT: 프로젝트 멤버 권한 수정 핸들러
http.put('/api/projects/:projectId/members', () => {
return HttpResponse.json({});
}),
// POST: 워크스페이스 멤버 추가 핸들러
http.post('/api/workspaces/:workspaceId/members/:memberId', ({ params }) => {
const { workspaceId, memberId } = params;
if (!workspaceId || !memberId) {
const errorResponse: ErrorResponse = {
status: 400,
code: 1002,
message: '잘못된 요청입니다. 요청을 확인해주세요.',
isSuccess: false,
};
return HttpResponse.json(errorResponse, { status: 400 });
}
// 성공 응답
const response: WorkspaceResponse = {
id: parseInt(workspaceId as string, 10),
memberId: 'abc1324',
title: 'Workspace 1',
content: 'Workspace for testing',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
return HttpResponse.json(response, { status: 200 });
}),
// GET: 프로젝트 멤버 리스트 조회 핸들러 (가상)
// 실제 구현 시 API 경로와 메서드를 확인 후 업데이트 필요
http.get('/api/projects/:projectId/members', () => {
const members: MemberResponse[] = [
{ id: 1, nickname: 'admin', profileImage: 'admin.jpg', email: 'j9@naver.com' },
{ id: 2, nickname: 'editor', profileImage: 'editor.jpg', email: 'j9@naver.com' },
{ id: 3, nickname: 'viewer', profileImage: 'viewer.jpg', email: 'j9@naver.com' },
];
return HttpResponse.json(members);
}),
// GET: 워크스페이스 멤버 리스트 조회 핸들러 (가상)
// 실제 구현 시 API 경로와 메서드를 확인 후 업데이트 필요
http.get('/api/workspaces/:workspaceId/members', () => {
const members: MemberResponse[] = [
{ id: 1, nickname: 'admin', profileImage: 'admin.jpg', email: 'j9@naver.com' },
{ id: 2, nickname: 'editor', profileImage: 'editor.jpg', email: 'j9@naver.com' },
{ id: 3, nickname: 'viewer', profileImage: 'viewer.jpg', email: 'j9@naver.com' },
];
return HttpResponse.json(members);
}),
// Folder and Image Handlers
http.get('/api/projects/:projectId/folders/:folderId', ({ params }) => {
const { folderId } = params;
const response: FolderResponse = {
id: parseInt(folderId as string, 10),
title: 'My Folder',
images: [
{
id: 1,
imageTitle: 'image.jpg',
imagePath: 'https://example.com/image.jpg',
dataPath: 'https://example.com/image.json',
status: 'PENDING',
},
{
id: 2,
imageTitle: 'another_image.jpg',
imagePath: 'https://example.com/another_image.jpg',
dataPath: 'https://example.com/another_image.json',
status: 'IN_PROGRESS',
},
],
children: [
{
id: 1,
title: 'Car',
},
{
id: 2,
title: 'Bike',
},
],
};
return HttpResponse.json(response);
}),
http.get('/api/projects/:projectId/folders/:folderId/images/:imageId', ({ params }) => {
// 이미지 조회 핸들러
const { imageId } = params;
const response: ImageResponse = {
id: parseInt(imageId as string, 10),
imageTitle: 'Image Title',
imagePath: 'image-url.jpg',
dataPath: 'data-url.json',
status: 'PENDING',
};
return HttpResponse.json(response);
}),
// Auto Labeling Handler
http.post('/api/projects/:projectId/label/auto', () => {
const response: AutoLabelingResponse = {
imageId: 1,
imageUrl: 'image-url.jpg',
data: `{
"version": "0.1.0",
"task_type": "cls",
"shapes": [
{
"label": "NG",
"color": "#FF0000",
"points": [[0, 0]],
"group_id": null,
"shape_type": "point",
"flags": {}
}
],
"split": "none",
"imageHeight": 2000,
"imageWidth": 4000,
"imageDepth": 4
}`,
};
return HttpResponse.json(response);
}),
// Error Handler Example
http.get('/api/error', () => {
const errorResponse: ErrorResponse = {
status: 400,
code: 1003,
message: '필수 요청 파라미터가 입력되지 않았습니다.',
isSuccess: false,
};
return HttpResponse.json(errorResponse);
}),
...authHandlers,
...labelHandlers,
...reviewHandlers,
...categoryHandlers,
...memberHandlers,
...workspaceHandlers,
...folderHandlers,
...modelHandlers,
...imageHandlers,
...projectHandlers,
];

View File

@ -0,0 +1,122 @@
import { http, HttpResponse } from 'msw';
import { ImageMoveRequest, ImageStatusChangeRequest } from '@/types';
export const imageHandlers = [
// 이미지 조회 핸들러
http.get('/api/images/:imageId', ({ params }) => {
const imageId = Array.isArray(params.imageId)
? parseInt(params.imageId[0], 10)
: parseInt(params.imageId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
const imageResponse = {
id: imageId,
title: `Image ${imageId}`,
url: `https://example.com/images/${imageId}`,
memberId,
};
return HttpResponse.json(imageResponse);
}),
// 이미지 이동 핸들러
http.put('/api/images/:imageId', async ({ params, request }) => {
const imageId = Array.isArray(params.imageId)
? parseInt(params.imageId[0], 10)
: parseInt(params.imageId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
const moveRequest = (await request.json()) as ImageMoveRequest;
return HttpResponse.json({
message: `Image ${imageId} moved to folder ${moveRequest.moveFolderId} by member ${memberId}`,
});
}),
// 이미지 삭제 핸들러
http.delete('/api/images/:imageId', ({ params }) => {
const imageId = Array.isArray(params.imageId)
? parseInt(params.imageId[0], 10)
: parseInt(params.imageId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
return HttpResponse.json({ message: `Image ${imageId} deleted by member ${memberId}` });
}),
// 이미지 상태 변경 핸들러
http.put('/api/images/:imageId/status', async ({ params, request }) => {
const imageId = Array.isArray(params.imageId)
? parseInt(params.imageId[0], 10)
: parseInt(params.imageId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
const statusChangeRequest = (await request.json()) as ImageStatusChangeRequest;
return HttpResponse.json({
message: `Image ${imageId} status changed to ${statusChangeRequest.labelStatus} by member ${memberId}`,
});
}),
// 이미지 파일 업로드 핸들러
http.post('/api/projects/:projectId/folders/:folderId/images/file', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const folderId = Array.isArray(params.folderId)
? parseInt(params.folderId[0], 10)
: parseInt(params.folderId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
const formData = await request.formData();
const files = formData.getAll('imageList') as File[];
return HttpResponse.json({
message: `Uploaded ${files.length} images to folder ${folderId} in project ${projectId} by member ${memberId}`,
});
}),
// 이미지 폴더 업로드 핸들러
http.post('/api/projects/:projectId/folders/:folderId/images/file', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
const formData = await request.formData();
const files = formData.getAll('imageList') as File[];
return HttpResponse.json({
message: `Uploaded ${files.length} images to folder 0 in project ${projectId} by member ${memberId}`,
});
}),
// 이미지 ZIP 파일 업로드 핸들러
http.post('/api/projects/:projectId/folders/:folderId/images/zip', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
const formData = await request.formData();
const file = formData.get('folderZip') as File;
return HttpResponse.json({
message: `Uploaded zip file "${file.name}" to project ${projectId} by member ${memberId}`,
});
}),
];

View File

@ -0,0 +1,36 @@
import { http, HttpResponse } from 'msw';
export const labelHandlers = [
// 이미지 레이블 저장 핸들러
http.post('/api/projects/:projectId/images/:imageId/label', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const imageId = Array.isArray(params.imageId)
? parseInt(params.imageId[0], 10)
: parseInt(params.imageId as string, 10);
const labelData = (await request.json()) as { data: string };
return HttpResponse.json({
message: `Label saved for image ${imageId} in project ${projectId}`,
labelData: labelData.data,
});
}),
// 자동 레이블링 실행 핸들러
http.post('/api/projects/:projectId/label/auto', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const memberId = Array.isArray(params.memberId)
? parseInt(params.memberId[0], 10)
: parseInt(params.memberId as string, 10);
// 여기에서는 예를 들어 자동 레이블링 작업이 성공적으로 완료된 상황을 가정합니다.
return HttpResponse.json({
message: `Auto-labeling started for project ${projectId} by member ${memberId}`,
status: 'IN_PROGRESS',
});
}),
];

View File

@ -0,0 +1,18 @@
import { http, HttpResponse } from 'msw';
import { MemberResponse } from '@/types';
export const memberHandlers = [
http.get('/api/members', ({ params }) => {
const keyword = Array.isArray(params.keyword) ? params.keyword[0] : params.keyword;
const members: MemberResponse[] = [
{ id: 1, nickname: 'john_doe', profileImage: 'john.jpg', email: 'john@example.com' },
{ id: 2, nickname: 'jane_doe', profileImage: 'jane.jpg', email: 'jane@example.com' },
{ id: 3, nickname: 'sam_smith', profileImage: 'sam.jpg', email: 'sam@example.com' },
];
const filteredMembers = members.filter((member) => member.email.includes(keyword || ''));
return HttpResponse.json(filteredMembers);
}),
];

View File

@ -0,0 +1,201 @@
import { http, HttpResponse } from 'msw';
import {
ModelRequest,
ModelResponse,
ProjectModelsResponse,
ModelCategoryResponse,
ModelTrainRequest,
ResultResponse,
ReportResponse,
} from '@/types';
export const modelHandlers = [
// 모델 이름 업데이트 핸들러
http.put('/api/projects/:projectId/models/:modelId', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const modelId = Array.isArray(params.modelId)
? parseInt(params.modelId[0], 10)
: parseInt(params.modelId as string, 10);
console.log(projectId);
const modelData = (await request.json()) as ModelRequest;
const updatedModel: ModelResponse = {
id: modelId,
name: modelData.name,
};
return HttpResponse.json(updatedModel);
}),
// 모델 학습 핸들러
http.post('/api/projects/:projectId/train', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const trainData = (await request.json()) as ModelTrainRequest;
return HttpResponse.json({
message: `Model training started for project ${projectId}`,
trainData,
});
}),
// 프로젝트의 모델 리스트 조회 핸들러
http.get('/api/projects/:projectId/models', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const models: ProjectModelsResponse = [
{ id: 1, name: 'Model 1' },
{ id: 2, name: 'Model 2' },
];
return HttpResponse.json(models);
}),
// 모델 추가 핸들러
http.post('/api/projects/:projectId/models', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const modelData = (await request.json()) as ModelRequest;
console.log(projectId);
const newModel: ModelResponse = {
id: Math.floor(Math.random() * 1000), // 임의로 ID 생성
name: modelData.name,
};
return HttpResponse.json(newModel);
}),
// 모델 카테고리 조회 핸들러
http.get('/api/models/:modelId/categories', ({ params }) => {
const modelId = Array.isArray(params.modelId)
? parseInt(params.modelId[0], 10)
: parseInt(params.modelId as string, 10);
console.log(modelId);
const categories: ModelCategoryResponse[] = [
{ id: 1, name: 'Category 1' },
{ id: 2, name: 'Category 2' },
];
return HttpResponse.json(categories);
}),
// 모델 결과 조회 핸들러
http.get('/api/results/model/:modelId', ({ params }) => {
const modelId = Array.isArray(params.modelId)
? parseInt(params.modelId[0], 10)
: parseInt(params.modelId as string, 10);
console.log(modelId);
const results: ResultResponse[] = [
{
id: 1,
precision: 0.85,
recall: 0.8,
fitness: 0.9,
ratio: 0.75,
epochs: 50,
batch: 32,
lr0: 0.001,
lrf: 0.0001,
optimizer: 'ADAM',
map50: 0.92,
map5095: 0.88,
},
{
id: 2,
precision: 0.87,
recall: 0.82,
fitness: 0.91,
ratio: 0.77,
epochs: 40,
batch: 16,
lr0: 0.001,
lrf: 0.00005,
optimizer: 'SGD',
map50: 0.93,
map5095: 0.89,
},
];
return HttpResponse.json(results);
}),
// 모델 보고서 조회 핸들러
http.get('/api/projects/:projectId/reports/model/:modelId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const modelId = Array.isArray(params.modelId)
? parseInt(params.modelId[0], 10)
: parseInt(params.modelId as string, 10);
console.log(projectId);
const reports: ReportResponse[] = [
{
modelId: modelId,
totalEpochs: 5,
epoch: 1,
boxLoss: 0.05,
clsLoss: 0.04,
dflLoss: 0.03,
fitness: 0.88,
epochTime: 110,
leftSecond: 1000,
},
{
modelId: modelId,
totalEpochs: 5,
epoch: 2,
boxLoss: 0.04,
clsLoss: 0.035,
dflLoss: 0.025,
fitness: 0.89,
epochTime: 115,
leftSecond: 900,
},
{
modelId: modelId,
totalEpochs: 5,
epoch: 3,
boxLoss: 0.03,
clsLoss: 0.03,
dflLoss: 0.02,
fitness: 0.9,
epochTime: 120,
leftSecond: 800,
},
{
modelId: modelId,
totalEpochs: 5,
epoch: 4,
boxLoss: 0.025,
clsLoss: 0.028,
dflLoss: 0.018,
fitness: 0.91,
epochTime: 125,
leftSecond: 700,
},
{
modelId: modelId,
totalEpochs: 5,
epoch: 5,
boxLoss: 0.02,
clsLoss: 0.025,
dflLoss: 0.015,
fitness: 0.92,
epochTime: 130,
leftSecond: 600,
},
];
return HttpResponse.json(reports);
}),
];

View File

@ -0,0 +1,205 @@
import { http, HttpResponse } from 'msw';
import { ProjectMemberResponse, ProjectResponse } from '@/types';
export const projectHandlers = [
// 프로젝트 목록 조회 핸들러
http.get('/api/workspaces/:workspaceId/projects', ({ params, request }) => {
const workspaceId = Array.isArray(params.workspaceId)
? parseInt((params.workspaceId as string[])[0], 10)
: parseInt(params.workspaceId as string, 10);
const url = new URL(request.url);
const lastProjectId = parseInt(url.searchParams.get('lastProjectId') || '0', 10);
const limit = parseInt(url.searchParams.get('limit') || '10', 10);
const projects: ProjectResponse[] = Array.from({ length: limit }, (_, index) => ({
id: lastProjectId + index + 1,
title: `프로젝트 ${lastProjectId + index + 1}`,
workspaceId,
projectType: ['classification', 'detection', 'segmentation'][index % 3] as
| 'classification'
| 'detection'
| 'segmentation',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
thumbnail: `thumbnail_${lastProjectId + index + 1}.jpg`,
}));
return HttpResponse.json(projects);
}),
// 특정 프로젝트 조회 핸들러
http.get('/api/projects/:projectId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
const response: ProjectResponse = {
id: projectId,
title: 'Project Title',
workspaceId: 1,
projectType: 'classification',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
};
return HttpResponse.json(response);
}),
// 프로젝트 생성 핸들러
http.post('/api/workspaces/:workspaceId/projects', async ({ params, request }) => {
const workspaceId = Array.isArray(params.workspaceId)
? parseInt((params.workspaceId as string[])[0], 10)
: parseInt(params.workspaceId as string, 10);
// body의 타입을 명시적으로 정의
const body = (await request.json()) as {
title: string;
projectType: 'classification' | 'detection' | 'segmentation';
};
const { title, projectType } = body;
const newProject: ProjectResponse = {
id: Math.floor(Math.random() * 1000),
title,
workspaceId,
projectType,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
return HttpResponse.json(newProject);
}),
// 프로젝트 수정 핸들러
http.put('/api/projects/:projectId', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
// body의 타입을 명시적으로 정의
const body = (await request.json()) as {
title: string;
projectType: 'classification' | 'detection' | 'segmentation';
};
const { title, projectType } = body;
const updatedProject: ProjectResponse = {
id: projectId,
title,
workspaceId: 1,
projectType,
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: new Date().toISOString(),
};
return HttpResponse.json(updatedProject);
}),
// 프로젝트 삭제 핸들러
http.delete('/api/projects/:projectId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
console.log(`Deleted project ${projectId}`);
return HttpResponse.json({ message: `Project ${projectId} deleted successfully` });
}),
// 프로젝트 멤버 조회 핸들러
http.get('/api/projects/:projectId/members', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const members: ProjectMemberResponse[] = [
{
memberId: 1,
nickname: 'adminUser',
profileImage: 'admin.jpg',
privilegeType: 'ADMIN',
},
{
memberId: 2,
nickname: 'managerUser',
profileImage: 'manager.jpg',
privilegeType: 'MANAGER',
},
{
memberId: 3,
nickname: 'editorUser',
profileImage: 'editor.jpg',
privilegeType: 'EDITOR',
},
{
memberId: 4,
nickname: 'viewerUser',
profileImage: 'viewer.jpg',
privilegeType: 'VIEWER',
},
];
return HttpResponse.json(members);
}),
// 프로젝트 멤버 추가 핸들러
http.post('/api/projects/:projectId/members', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const newMember = (await request.json()) as {
nickname: string;
profileImage: string;
privilegeType: 'ADMIN' | 'MANAGER' | 'EDITOR' | 'VIEWER';
};
const addedMember: ProjectMemberResponse = {
memberId: Math.floor(Math.random() * 1000), // 임의의 ID 생성
nickname: newMember.nickname,
profileImage: newMember.profileImage,
privilegeType: newMember.privilegeType,
};
return HttpResponse.json(addedMember);
}),
// 프로젝트 멤버 권한 수정 핸들러
http.put('/api/projects/:projectId/members', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const privilegeData = (await request.json()) as {
memberId: number;
privilegeType: 'ADMIN' | 'MANAGER' | 'EDITOR' | 'VIEWER';
};
const updatedMember: ProjectMemberResponse = {
memberId: privilegeData.memberId,
nickname: 'Updated User',
profileImage: 'updated.jpg',
privilegeType: privilegeData.privilegeType,
};
return HttpResponse.json(updatedMember);
}),
// 프로젝트 멤버 삭제 핸들러
http.delete('/api/projects/:projectId/members', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
const { targetMemberId } = (await request.json()) as { targetMemberId: number };
return HttpResponse.json({ message: `Member ${targetMemberId} removed from project ${projectId}` });
}),
// 프로젝트 삭제 핸들러
http.delete('/api/projects/:projectId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt((params.projectId as string[])[0], 10)
: parseInt(params.projectId as string, 10);
console.log(`Deleted project ${projectId}`);
return HttpResponse.json({ message: `Project ${projectId} deleted successfully` });
}),
];

View File

@ -0,0 +1,151 @@
import { http, HttpResponse } from 'msw';
import { ReviewDetailResponse, ReviewRequest, ReviewResponse, ReviewStatusRequest } from '@/types';
export const reviewHandlers = [
// 리뷰 단건 조회 핸들러
http.get('/api/projects/:projectId/reviews/:reviewId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const reviewId = Array.isArray(params.reviewId)
? parseInt(params.reviewId[0], 10)
: parseInt(params.reviewId as string, 10);
console.log(projectId);
const reviewDetail: ReviewDetailResponse = {
reviewId: reviewId,
title: 'Sample Review Title',
content: 'This is a detailed review content.',
reviewStatus: 'REQUESTED',
images: [
{
id: 1,
imageTitle: 'Image 1',
status: 'PENDING',
imagePath: 'https://example.com/image1.jpg',
dataPath: 'https://example.com/data1.json',
},
],
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
author: { id: 1, nickname: 'Author', profileImage: '', email: 'author@example.com' },
reviewer: { id: 2, nickname: 'Reviewer', profileImage: '', email: 'reviewer@example.com' },
};
return HttpResponse.json(reviewDetail);
}),
// 리뷰 생성 핸들러
http.post('/api/projects/:projectId/reviews', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const reviewData = (await request.json()) as ReviewRequest;
const newReview: ReviewResponse = {
projectId,
reviewId: Math.floor(Math.random() * 1000), // 임의로 생성된 ID
title: reviewData.title,
content: reviewData.content,
status: 'REQUESTED',
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
author: { id: 1, nickname: 'Author', profileImage: '', email: 'author@example.com' },
};
return HttpResponse.json(newReview);
}),
// 리뷰 수정 핸들러
http.put('/api/projects/:projectId/reviews/:reviewId', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const reviewId = Array.isArray(params.reviewId)
? parseInt(params.reviewId[0], 10)
: parseInt(params.reviewId as string, 10);
console.log(projectId);
const reviewData = (await request.json()) as ReviewRequest;
const updatedReview: ReviewResponse = {
projectId,
reviewId,
title: reviewData.title,
content: reviewData.content,
status: 'REQUESTED',
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
author: { id: 1, nickname: 'Author', profileImage: '', email: 'author@example.com' },
};
return HttpResponse.json(updatedReview);
}),
// 리뷰 삭제 핸들러
http.delete('/api/projects/:projectId/reviews/:reviewId', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const reviewId = Array.isArray(params.reviewId)
? parseInt(params.reviewId[0], 10)
: parseInt(params.reviewId as string, 10);
return HttpResponse.json({ message: `Review ${reviewId} from project ${projectId} deleted successfully.` });
}),
// 리뷰 상태 변경 핸들러
http.put('/api/projects/:projectId/reviews/:reviewId/status', async ({ params, request }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
const reviewId = Array.isArray(params.reviewId)
? parseInt(params.reviewId[0], 10)
: parseInt(params.reviewId as string, 10);
console.log(projectId);
const statusRequest = (await request.json()) as ReviewStatusRequest;
const updatedReview: ReviewResponse = {
projectId,
reviewId,
title: `Updated Review ${reviewId}`,
content: 'Updated content',
status: statusRequest.reviewStatus,
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
author: { id: 1, nickname: 'Author', profileImage: '', email: 'author@example.com' },
};
return HttpResponse.json(updatedReview);
}),
http.get('/api/projects/:projectId/reviews', ({ params }) => {
const projectId = Array.isArray(params.projectId)
? parseInt(params.projectId[0], 10)
: parseInt(params.projectId as string, 10);
console.log(projectId);
const reviewStatus = Array.isArray(params.reviewStatus) ? params.reviewStatus[0] : params.reviewStatus;
const lastReviewId = Array.isArray(params.lastReviewId) ? params.lastReviewId[0] : params.lastReviewId;
const limitPage = Array.isArray(params.limitPage)
? parseInt(params.limitPage[0], 10)
: parseInt(params.limitPage as string, 10) || 10;
const reviews: ReviewResponse[] = Array.from({ length: limitPage }, (_, index) => ({
projectId,
reviewId: lastReviewId ? parseInt(lastReviewId, 10) + index : index + 1,
title: `Review ${index + 1}`,
content: `Review content ${index + 1}`,
status: (reviewStatus || 'REQUESTED') as 'REQUESTED' | 'APPROVED' | 'REJECTED',
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
author: { id: 1, nickname: 'Author', profileImage: '', email: 'author@example.com' },
}));
return HttpResponse.json(reviews);
}),
];

View File

@ -0,0 +1,166 @@
import { http, HttpResponse } from 'msw';
import { WorkspaceResponse, WorkspaceListResponse, ReviewResponse, WorkspaceMemberResponse } from '@/types';
export const workspaceHandlers = [
// 워크스페이스 조회 핸들러
http.get('/api/workspaces/:workspaceId', ({ params }) => {
const { workspaceId } = params;
const response: WorkspaceResponse = {
id: parseInt(workspaceId as string, 10),
memberId: 'abc1324',
title: 'workspace1',
content: '갤럭시 s24 불량 검증',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
};
return HttpResponse.json(response);
}),
// 워크스페이스 수정 핸들러
http.put('/api/workspaces/:workspaceId', ({ params }) => {
const { workspaceId } = params;
const response: WorkspaceResponse = {
id: parseInt(workspaceId as string, 10),
memberId: 'abc1324',
title: 'Updated Workspace Title',
content: 'Updated Workspace Content',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T06:00:00.668Z',
};
return HttpResponse.json(response);
}),
// 워크스페이스 삭제 핸들러
http.delete('/api/workspaces/:workspaceId', ({ params }) => {
const { workspaceId } = params;
console.log(`Workspace ${workspaceId} deleted`);
return HttpResponse.json({});
}),
http.get('/api/workspaces', () => {
console.log('워크스페이스 목록 전체 조회');
const workspaces: WorkspaceListResponse = {
workspaceResponses: [
{
id: 1,
memberId: 'abc1324',
title: 'Workspace 1',
content: 'Content 1',
createdAt: '2024-09-18T05:04:44.668Z',
updatedAt: '2024-09-18T05:04:44.668Z',
},
{
id: 2,
memberId: 'xyz5678',
title: 'Workspace 2',
content: 'Content 2',
createdAt: '2024-09-19T05:04:44.668Z',
updatedAt: '2024-09-19T05:04:44.668Z',
},
],
};
return HttpResponse.json(workspaces);
}),
// 워크스페이스 멤버 추가 핸들러
http.post('/api/workspaces/:workspaceId/members/:newMemberId', async ({ params }) => {
const workspaceId = Array.isArray(params.workspaceId)
? parseInt((params.workspaceId as string[])[0], 10)
: parseInt(params.workspaceId as string, 10);
const newMemberId = Array.isArray(params.newMemberId)
? parseInt((params.newMemberId as string[])[0], 10)
: parseInt(params.newMemberId as string, 10);
console.log(workspaceId);
const addedMember: WorkspaceMemberResponse = {
id: newMemberId,
nickname: `Member${newMemberId}`,
profileImage: `profile${newMemberId}.jpg`,
};
return HttpResponse.json(addedMember);
}),
// 워크스페이스 멤버 삭제 핸들러
http.delete('/api/workspaces/:workspaceId/members/:targetMemberId', ({ params }) => {
const workspaceId = Array.isArray(params.workspaceId)
? parseInt((params.workspaceId as string[])[0], 10)
: parseInt(params.workspaceId as string, 10);
const targetMemberId = Array.isArray(params.targetMemberId)
? parseInt((params.targetMemberId as string[])[0], 10)
: parseInt(params.targetMemberId as string, 10);
return HttpResponse.json({ message: `Member ${targetMemberId} removed from workspace ${workspaceId}` });
}),
// 워크스페이스 멤버 조회 핸들러
http.get('/api/workspaces/:workspaceId/members', ({ params }) => {
const workspaceId = Array.isArray(params.workspaceId)
? parseInt((params.workspaceId as string[])[0], 10)
: parseInt(params.workspaceId as string, 10);
console.log(workspaceId);
const members: WorkspaceMemberResponse[] = [
{
id: 1,
nickname: 'adminUser',
profileImage: 'admin.jpg',
},
{
id: 2,
nickname: 'managerUser',
profileImage: 'manager.jpg',
},
{
id: 3,
nickname: 'editorUser',
profileImage: 'editor.jpg',
},
];
return HttpResponse.json(members);
}),
// 워크스페이스 리뷰 조회 핸들러
http.get('/api/workspaces/:workspaceId/reviews', ({ params }) => {
const workspaceId = Array.isArray(params.workspaceId)
? parseInt((params.workspaceId as string[])[0], 10)
: parseInt(params.workspaceId as string, 10);
console.log(workspaceId);
const reviews: ReviewResponse[] = [
{
reviewId: 1,
projectId: 1,
title: 'First Review',
content: 'This is a review content.',
status: 'APPROVED',
author: {
id: 1,
nickname: 'Reviewer1',
profileImage: 'reviewer1.jpg',
email: 'reviewer1@example.com',
},
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
},
{
reviewId: 2,
projectId: 2,
title: 'Second Review',
content: 'This is another review content.',
status: 'REQUESTED',
author: {
id: 2,
nickname: 'Reviewer2',
profileImage: 'reviewer2.jpg',
email: 'reviewer2@example.com',
},
createAt: new Date().toISOString(),
updateAt: new Date().toISOString(),
},
];
return HttpResponse.json(reviews);
}),
];