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
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
### AHHACHUL-Frontend

> **지하철에선? 아하철!**
>
>
> 지하철에서도 즐거우면 안될까요? 🙃🙃

## 👨‍💻 만든 사람들

- 이효범 :octocat: 📚
- 양아름 :octocat: 📚
- 최윤정 :octocat: 📚
- 이희제 :octocat: 📚
3 changes: 1 addition & 2 deletions services/one-app/src/app/(site)/login/callback/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ function LoginCallback() {
}
} catch (error) {
console.error(error);

router.back();
router.replace('/login?error=from_callback');
} finally {
isLoadingRef.current = false;
}
Expand Down
227 changes: 4 additions & 223 deletions services/one-app/src/mocks/handlers.ts
Original file line number Diff line number Diff line change
@@ -1,226 +1,7 @@
import { http, HttpResponse, StrictResponse } from 'msw';
import { faker } from '@faker-js/faker';

function generateDate() {
const lastWeek = new Date(Date.now());
lastWeek.setDate(lastWeek.getDate() - 7);
return faker.date.between({
from: lastWeek,
to: Date.now(),
});
}
const User = [
{ memberId: 'createhb21', nickname: '효범', gender: 'MALE' },
{ memberId: 'areumsheep', nickname: '아름', gender: 'FEMALE' },
{ memberId: 'YoonJeongLulu', nickname: '윤정', gender: 'FEMALE' },
];
const Posts = [];
import { authHandlers, lostFoundHandlers, userHandlers } from './units';

export const handlers = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이렇게 쓰는 패턴은 의도가 뭔가용?

Copy link
Member Author

@createhb21 createhb21 Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://mswjs.io/docs/getting-started#step-2-describe
그냥 msw에서 제시해서 정형화된 패턴 (?)

http.post('/auth/login', async ({ request }) => {
console.log('로그인');
return HttpResponse.json({
memberId: User[0].memberId,
accessToken: faker.string.alphanumeric(20),
accessTokenExpiresIn: faker.number.int({ max: 1000 }),
refreshToken: faker.string.alphanumeric(20),
refreshTokenExpiresIn: faker.number.int({ max: 100000 }),
isNeedAdditionalUserInfo: false,
});
}),
http.post('/auth/logout', () => {
console.log('로그아웃');
return new HttpResponse(null);
}),
http.get('/auth/redirect-url', () => {
console.log('리다이렉트 URL 조회');
return HttpResponse.json({
code: '100',
message: 'SUCCESS',
result: {
redirectUrl: 'redirectUrl',
},
});
}),
http.post('/auth/token/refresh', () => {
console.log('토큰 재발급');
return HttpResponse.json({
accessToken: faker.string.alphanumeric(20),
accessTokenExpiresIn: faker.number.int({ max: 1000 }),
refreshToken: faker.string.alphanumeric(20),
refreshTokenExpiresIn: faker.number.int({ max: 100000 }),
});
}),
http.get('/members/:userId', ({ request, params }): StrictResponse<any> => {
const { userId } = params;
const found = User.find((v) => v.memberId === userId);
if (found) {
return HttpResponse.json(found);
}
return HttpResponse.json(
{ message: 'no_such_user' },
{
status: 404,
},
);
}),
http.get('/members/:userId/posts', ({ request, params }) => {
const { userId } = params;
return HttpResponse.json([
{
id: 1,
writer: User[0].nickname,
content: `${1} ${userId}의 게시글`,
image: { imageId: 1, imageUrl: faker.image.urlLoremFlickr() },
createdAt: generateDate(),
createdBy: User[0].memberId,
},
{
id: 2,
writer: User[0].nickname,
content: `${2} ${userId}의 게시글`,
image: [{ imageId: 1, imageUrl: faker.image.urlLoremFlickr() }],
createdAt: generateDate(),
createdBy: User[0].memberId,
},
{
id: 3,
writer: User[0].nickname,
content: `${3} ${userId}의 게시글`,
image: { imageId: 1, imageUrl: faker.image.urlLoremFlickr() },
createdAt: generateDate(),
createdBy: User[0].memberId,
},
{
id: 4,
writer: User[0].nickname,
content: `${4} ${userId}의 게시글`,
image: { imageId: 1, imageUrl: faker.image.urlLoremFlickr() },
createdAt: generateDate(),
createdBy: User[0].memberId,
},
{
id: 5,
writer: User[0].nickname,
content: `${5} ${userId}의 게시글`,
image: { imageId: 1, imageUrl: faker.image.urlLoremFlickr() },
createdAt: generateDate(),
createdBy: User[0].memberId,
},
]);
}),
http.get(
'/community-posts/:postId',
({ request, params }): StrictResponse<any> => {
console.log('커뮤니티 글 상세 조회');
const { postId } = params;
if (parseInt(postId as string) > 10) {
return HttpResponse.json(
{ message: 'no_such_post' },
{
status: 404,
},
);
}
return HttpResponse.json({
postId,
writer: User[0].nickname,
title: `${1} 게시글 아이디 ${postId}의 제목`,
content: faker.lorem.paragraphs(),
images: [
{ imageId: 1, imageUrl: faker.image.urlLoremFlickr() },
{ imageId: 2, imageUrl: faker.image.urlLoremFlickr() },
{ imageId: 3, imageUrl: faker.image.urlLoremFlickr() },
],
createdAt: generateDate(),
createdBy: User[0].memberId,
});
},
),
http.get('/posts/:postId/comments', ({ request, params }) => {
console.log('커뮤니티 글 댓글 목록 조회');
const { postId } = params;
return HttpResponse.json({
comments: [
{
parentComment: {
id: 1,
upperCommentId: null,
content: faker.lorem.paragraphs(),
status: 'CREATED',
createdAt: generateDate(),
createdBy: User[0].memberId,
writer: User[0].nickname,
},
childComments: [
{
id: 2,
upperCommentId: 1,
content: faker.lorem.paragraphs(),
status: 'CREATED',
createdAt: generateDate(),
createdBy: User[1].memberId,
writer: User[1].nickname,
},
],
},
{
parentComment: {
id: 11,
upperCommentId: null,
content: faker.lorem.paragraphs(),
status: 'DELETED',
createdAt: generateDate(),
createdBy: User[1].memberId,
writer: User[1].nickname,
},
childComments: [
{
id: 22,
upperCommentId: 11,
content: faker.lorem.paragraphs(),
status: 'CREATED',
createdAt: generateDate(),
createdBy: User[1].memberId,
writer: User[1].nickname,
},
],
},
{
parentComment: {
id: 111,
upperCommentId: null,
content: faker.lorem.paragraphs(),
status: 'CREATED',
createdAt: generateDate(),
createdBy: User[2].memberId,
writer: User[2].nickname,
},
childComments: [
{
id: 222,
upperCommentId: 111,
content: faker.lorem.paragraphs(),
status: 'CREATED',
createdAt: generateDate(),
createdBy: User[0].memberId,
writer: User[0].nickname,
},
],
},
{
parentComment: {
id: 1111,
upperCommentId: null,
content: faker.lorem.paragraphs(),
status: 'CREATED',
createdAt: generateDate(),
createdBy: User[2].memberId,
writer: User[2].nickname,
},
childComments: [],
},
],
});
}),
...authHandlers,
...userHandlers,
...lostFoundHandlers,
];
90 changes: 90 additions & 0 deletions services/one-app/src/mocks/mock-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { HttpResponse } from 'msw';
import { faker } from '@faker-js/faker';
import { APIResponseCode, RESPONSE_MESSAGES } from '@/common/constants/api';

export const ERROR_RATE = 0.3;
export const ADDITIONAL_INFO_RATE = 0.3;

export const User = [
{ memberId: '1', nickname: '효범', gender: 'MALE' },
{ memberId: '2', nickname: '윤정', gender: 'FEMALE' },
{ memberId: '3', nickname: '희제', gender: 'MALE' },
];

export const createErrorResponse = () =>
HttpResponse.json(
{
code: APIResponseCode.BAD_REQUEST,
message: RESPONSE_MESSAGES[APIResponseCode.BAD_REQUEST],
result: null,
},
{ status: 400 },
);

export const createSuccessResponse = <TData>(result: TData) =>
HttpResponse.json({
code: APIResponseCode.SUCCESS,
message: RESPONSE_MESSAGES[APIResponseCode.SUCCESS],
result,
});

export const generateDate = () => {
const lastWeek = new Date(Date.now());
lastWeek.setDate(lastWeek.getDate() - 7);
return faker.date.between({
from: lastWeek,
to: Date.now(),
});
};

export const generateImages = (count: number) =>
Array.from({ length: count }, (_, index) => ({
imageId: index + 1,
imageUrl: faker.image.urlLoremFlickr(),
}));

export const generateBasicArticleData = (
postId: string,
user: (typeof User)[0],
imgLength = 3,
) => ({
postId,
writer: user.nickname,
title: `게시글 아이디 ${postId}의 제목`,
content: faker.lorem.paragraphs(),
images: generateImages(imgLength),
createdAt: generateDate(),
createdBy: user.memberId,
});

const generateComment = (
id: number,
upperCommentId: number | null,
user: (typeof User)[0],
) => ({
id,
upperCommentId,
content: faker.lorem.paragraphs(),
status: faker.helpers.arrayElement(['CREATED', 'DELETED']),
createdAt: generateDate(),
createdBy: user.memberId,
writer: user.nickname,
});

export const generateCommentThread = () => {
const parentComment = generateComment(
faker.number.int({ min: 1, max: 1000 }),
null,
faker.helpers.arrayElement(User),
);
const childComments = Array.from(
{ length: faker.number.int({ min: 0, max: 3 }) },
() =>
generateComment(
faker.number.int({ min: 1001, max: 2000 }),
parentComment.id,
faker.helpers.arrayElement(User),
),
);
return { parentComment, childComments };
};
43 changes: 43 additions & 0 deletions services/one-app/src/mocks/units/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { http } from 'msw';
import { faker } from '@faker-js/faker';
import {
User,
ERROR_RATE,
ADDITIONAL_INFO_RATE,
createErrorResponse,
createSuccessResponse,
} from '../mock-utils';

const generateTokenData = () => ({
accessToken: faker.string.alphanumeric(20),
accessTokenExpiresIn: faker.number.int({ max: 100000 }),
refreshToken: faker.string.alphanumeric(20),
refreshTokenExpiresIn: faker.number.int({ max: 1000000 }),
});

const createLoginSuccessResponse = (memberId: string) =>
createSuccessResponse({
memberId,
...generateTokenData(),
isNeedAdditionalUserInfo: Math.random() < ADDITIONAL_INFO_RATE,
});

const mock_로그인 = http.post('/auth/login', async ({ request }) => {
if (Math.random() < ERROR_RATE) {
return createErrorResponse();
}

return createLoginSuccessResponse(User[0].memberId);
});

const mock_리다이렉트_URL_조회 = http.get('/auth/redirect-url', () => {
if (Math.random() < ERROR_RATE) {
return createErrorResponse();
}

return createSuccessResponse({
redirectUrl: 'https://dev.ahhachul.com/redirectUrl',
});
});

export default [mock_로그인, mock_리다이렉트_URL_조회];
3 changes: 3 additions & 0 deletions services/one-app/src/mocks/units/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as authHandlers } from './auth';
export { default as userHandlers } from './user';
export { default as lostFoundHandlers } from './lost-found';
Loading
Loading