-
Notifications
You must be signed in to change notification settings - Fork 1
[25.07.13 / TASK-213] Feature - 프론트엔드 테스팅 리팩토링 및 고도화 #46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
""" Walkthrough이 변경 사항은 Cypress 기반의 E2E 테스트 환경을 새롭게 도입하고, 주요 페이지(메인, 로그인, 리더보드)에 대한 테스트를 추가합니다. 또한, 빈 데이터 상태를 명확하게 처리하기 위해 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Cypress
participant App(Next.js)
participant Mock API
User->>Cypress: 테스트 실행 (예: 로그인 테스트)
Cypress->>App(Next.js): 페이지 방문 및 쿠키 설정
App(Next.js)->>Mock API: API 요청 (예: /api/login)
Mock API-->>App(Next.js): 목 데이터 응답
App(Next.js)-->>Cypress: 렌더링 결과 반환
Cypress->>User: 테스트 결과 검증
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
💤 Files with no reviewable changes (1)
🚧 Files skipped from review as they are similar to previous changes (1)
🧰 Additional context used🧠 Learnings (2)📓 Common learnings
jest.config.ts (1)
🔇 Additional comments (1)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (6)
src/utils/datetime.util.ts (1)
58-61
: 중복된Math.floor
호출을 제거하여 코드를 간소화하세요.현재 구현에서
Math.floor(Math.floor(time) / 60)
와Math.floor(time) % 60
에서Math.floor
가 중복 호출되고 있습니다. 입력값을 한 번만 floor 처리하여 재사용하는 것이 더 효율적입니다.다음과 같이 개선할 수 있습니다:
export const formatTimeToMMSS = (time: number) => { - const minute = Math.floor(Math.floor(time) / 60) + const flooredTime = Math.floor(time); + const minute = Math.floor(flooredTime / 60) .toString() .padStart(2, '0'); - const second = (Math.floor(time) % 60).toString().padStart(2, '0'); + const second = (flooredTime % 60).toString().padStart(2, '0'); return `${minute}분 ${second}초`; };src/shared/EmptyState.tsx (2)
1-5
: 인터페이스를 export하여 재사용성을 높이세요.
EmptyStateProps
인터페이스가 다른 컴포넌트에서 타입 안전성을 위해 사용될 수 있도록 export하는 것을 고려해보세요.-interface EmptyStateProps { +export interface EmptyStateProps { title: string; description?: string; icon?: React.ReactNode; }
9-16
: 접근성을 위한 ARIA 속성 추가를 고려하세요.현재 구현은 시각적으로 잘 작동하지만, 스크린 리더 사용자를 위한 접근성을 개선할 수 있습니다.
- <div className="flex flex-col items-center justify-center w-full h-full min-h-[300px] gap-4 text-center p-8"> + <div className="flex flex-col items-center justify-center w-full h-full min-h-[300px] gap-4 text-center p-8" role="status" aria-live="polite"> {icon && <div className="text-TEXT-ALT text-6xl opacity-50">{icon}</div>} <div className="flex flex-col gap-2"> - <h3 className="text-TEXT-MAIN text-TITLE-4 font-medium">{title}</h3> + <h3 className="text-TEXT-MAIN text-TITLE-4 font-medium" id="empty-state-title">{title}</h3> - {description && <p className="text-TEXT-ALT text-SUBTITLE-4 max-w-md">{description}</p>} + {description && <p className="text-TEXT-ALT text-SUBTITLE-4 max-w-md" aria-describedby="empty-state-title">{description}</p>} </div> </div>cypress/support/commands.ts (1)
10-14
: 인증 쿠키 설정 명령어가 잘 구현되었습니다.mock 토큰을 사용하여 테스트용 인증 쿠키를 설정하는 로직이 적절합니다. 다만
cy.wait(100)
부분에 대한 주석이 있으면 더 좋겠습니다.다음과 같이 주석을 추가하면 더 명확할 것 같습니다:
cy.setCookie('access_token', MOCK_ACCESS_TOKEN, DEFAULT_OPTION); cy.setCookie('refresh_token', MOCK_REFRESH_TOKEN, DEFAULT_OPTION); + // 쿠키 설정 완료를 위한 짧은 대기 cy.wait(100);
cypress/support/mock.ts (2)
71-72
: 주석 내용이 실제 데이터와 불일치
// 게시물 목록 응답 데이터
주석이 이미 14 라인에서 사용되었고, 71 라인 이후에는 그래프 데이터(postsGraphData
)가 선언됩니다. 주석을 맞게 수정해 두면 가독성이 향상됩니다.
238-249
: 매직 스트링 대신 리터럴 유니온 타입 활용 제안
getTotalStatsMessage
의type
매개변수는'view' | 'like' | 'post'
로 한정되는 것이 명확합니다. 리터럴 유니온 타입을 사용하면 오타를 컴파일 단계에서 잡을 수 있습니다.-export const getTotalStatsMessage = (type: string) => { +export const getTotalStatsMessage = (type: 'view' | 'like' | 'post') => {
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (28)
cypress.config.ts
(1 hunks)cypress/e2e/leaderboards.cy.ts
(1 hunks)cypress/e2e/login.cy.ts
(1 hunks)cypress/e2e/main.cy.ts
(1 hunks)cypress/support/base.ts
(1 hunks)cypress/support/commands.ts
(1 hunks)cypress/support/e2e.ts
(1 hunks)cypress/support/index.ts
(1 hunks)cypress/support/mock.ts
(1 hunks)package.json
(3 hunks)readme.md
(2 hunks)setupTests.ts
(0 hunks)src/__mock__/handlers.ts
(0 hunks)src/__mock__/responses.ts
(0 hunks)src/__mock__/server.ts
(0 hunks)src/__test__/instance.test.tsx
(0 hunks)src/__test__/login.test.tsx
(0 hunks)src/__test__/main.test.tsx
(0 hunks)src/app/(auth-required)/leaderboards/Content.tsx
(4 hunks)src/app/(auth-required)/main/Content.tsx
(4 hunks)src/app/components/Header/index.tsx
(1 hunks)src/constants/env.constant.ts
(1 hunks)src/shared/EmptyState.tsx
(1 hunks)src/shared/index.ts
(1 hunks)src/utils/__tests__/datetime.util.test.ts
(1 hunks)src/utils/__tests__/number.util.test.ts
(1 hunks)src/utils/datetime.util.ts
(1 hunks)src/utils/number.util.ts
(1 hunks)
💤 Files with no reviewable changes (7)
- setupTests.ts
- src/test/instance.test.tsx
- src/mock/server.ts
- src/mock/handlers.ts
- src/test/login.test.tsx
- src/mock/responses.ts
- src/test/main.test.tsx
🧰 Additional context used
🧠 Learnings (14)
📓 Common learnings
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-1
Timestamp: 2024-11-28T06:56:55.698Z
Learning: `src/app/main/Content.tsx`에 있는 `Content` 컴포넌트는 React와 TypeScript로 작성되었으며, `feature/dashboard` 브랜치에서 구현될 예정입니다. 현재 브랜치에 추가된 경우는 실수로 인한 것이므로, 향후 리뷰에서는 이 점을 고려하겠습니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-2
Timestamp: 2024-11-28T07:36:05.773Z
Learning: `src/app/main/page.tsx` 파일에서, 사용되지 않는 페이지로 남는 문제를 방지하기 위해 `Content` 컴포넌트를 아직 구현되지 않았더라도 import하는 것이 허용됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#35
File: src/app/(auth-required)/leaderboards/Content.tsx:84-85
Timestamp: 2025-05-15T10:47:24.746Z
Learning: 리더보드 페이지의 dateRange 드롭다운 defaultValue 동기화 문제는 별도의 브랜치(refactor/essential-components)에서 해결될 예정.
src/shared/index.ts (1)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-2
Timestamp: 2024-11-28T07:36:05.773Z
Learning: `src/app/main/page.tsx` 파일에서, 사용되지 않는 페이지로 남는 문제를 방지하기 위해 `Content` 컴포넌트를 아직 구현되지 않았더라도 import하는 것이 허용됩니다.
package.json (2)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: tsconfig.json:24-30
Timestamp: 2024-11-29T13:49:06.007Z
Learning: `eslint.config.mjs` 파일에서 발생하는 오류를 방지하기 위해 `tsconfig.json`의 `include` 배열에 `eslint.config.mjs`를 포함해야 합니다.
Learnt from: HA0N1
PR: Check-Data-Out/velog-dashboard-v2-fe#1
File: eslint.config.mjs:12-28
Timestamp: 2024-11-23T17:56:55.608Z
Learning: '@typescript-eslint/no-unused-vars' 규칙은 'tseslint.configs.recommended'에 포함되어 있으므로 추가로 설정할 필요가 없습니다.
readme.md (1)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
src/app/components/Header/index.tsx (2)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/utils/QueryProvider.tsx:6-6
Timestamp: 2024-11-28T07:39:01.023Z
Learning: `src/utils/QueryProvider.tsx` 파일에서는 프로젝트의 설계상 전역적인 `QueryClient` 인스턴스를 사용합니다.
Learnt from: Nuung
PR: Check-Data-Out/velog-dashboard-v2-fe#23
File: src/components/auth-required/notice/index.tsx:18-27
Timestamp: 2025-03-11T12:38:34.012Z
Learning: React 컴포넌트에서 API 응답 데이터를 처리할 때는 데이터가 없거나 배열이 비어있는 경우(전체 기능 비활성화, DB 마이그레이션, DBMS 연결 문제 등)에 대비한 방어적 코딩이 필요하다. 특히 `data?.posts[0]`과 같이 배열의 요소에 접근하기 전에 `if (!data?.posts || data.posts.length === 0) return;`와 같은 가드 클로즈를 사용하여 런타임 오류를 방지해야 한다.
src/app/(auth-required)/leaderboards/Content.tsx (6)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-1
Timestamp: 2024-11-28T06:56:55.698Z
Learning: `src/app/main/Content.tsx`에 있는 `Content` 컴포넌트는 React와 TypeScript로 작성되었으며, `feature/dashboard` 브랜치에서 구현될 예정입니다. 현재 브랜치에 추가된 경우는 실수로 인한 것이므로, 향후 리뷰에서는 이 점을 고려하겠습니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-2
Timestamp: 2024-11-28T07:36:05.773Z
Learning: `src/app/main/page.tsx` 파일에서, 사용되지 않는 페이지로 남는 문제를 방지하기 위해 `Content` 컴포넌트를 아직 구현되지 않았더라도 import하는 것이 허용됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#35
File: src/app/(auth-required)/leaderboards/Content.tsx:84-85
Timestamp: 2025-05-15T10:47:24.746Z
Learning: 리더보드 페이지의 dateRange 드롭다운 defaultValue 동기화 문제는 별도의 브랜치(refactor/essential-components)에서 해결될 예정.
Learnt from: Nuung
PR: Check-Data-Out/velog-dashboard-v2-fe#23
File: src/components/auth-required/notice/index.tsx:18-27
Timestamp: 2025-03-11T12:38:34.012Z
Learning: React 컴포넌트에서 API 응답 데이터를 처리할 때는 데이터가 없거나 배열이 비어있는 경우(전체 기능 비활성화, DB 마이그레이션, DBMS 연결 문제 등)에 대비한 방어적 코딩이 필요하다. 특히 `data?.posts[0]`과 같이 배열의 요소에 접근하기 전에 `if (!data?.posts || data.posts.length === 0) return;`와 같은 가드 클로즈를 사용하여 런타임 오류를 방지해야 한다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/Content.tsx:0-0
Timestamp: 2024-11-28T07:23:17.460Z
Learning: `src/app/(login)/Content.tsx`의 `instance` 함수는 기본적으로 headers를 제공하므로, 별도의 headers 설정이 필요하지 않습니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/utils/QueryProvider.tsx:6-6
Timestamp: 2024-11-28T07:39:01.023Z
Learning: `src/utils/QueryProvider.tsx` 파일에서는 프로젝트의 설계상 전역적인 `QueryClient` 인스턴스를 사용합니다.
src/app/(auth-required)/main/Content.tsx (4)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-2
Timestamp: 2024-11-28T07:36:05.773Z
Learning: `src/app/main/page.tsx` 파일에서, 사용되지 않는 페이지로 남는 문제를 방지하기 위해 `Content` 컴포넌트를 아직 구현되지 않았더라도 import하는 것이 허용됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-1
Timestamp: 2024-11-28T06:56:55.698Z
Learning: `src/app/main/Content.tsx`에 있는 `Content` 컴포넌트는 React와 TypeScript로 작성되었으며, `feature/dashboard` 브랜치에서 구현될 예정입니다. 현재 브랜치에 추가된 경우는 실수로 인한 것이므로, 향후 리뷰에서는 이 점을 고려하겠습니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/Content.tsx:49-60
Timestamp: 2024-11-28T07:35:06.631Z
Learning: In the login page (`src/app/(login)/Content.tsx`), error messages are not displayed separately due to the current implementation.
Learnt from: Nuung
PR: Check-Data-Out/velog-dashboard-v2-fe#23
File: src/components/auth-required/notice/index.tsx:18-27
Timestamp: 2025-03-11T12:38:34.012Z
Learning: React 컴포넌트에서 API 응답 데이터를 처리할 때는 데이터가 없거나 배열이 비어있는 경우(전체 기능 비활성화, DB 마이그레이션, DBMS 연결 문제 등)에 대비한 방어적 코딩이 필요하다. 특히 `data?.posts[0]`과 같이 배열의 요소에 접근하기 전에 `if (!data?.posts || data.posts.length === 0) return;`와 같은 가드 클로즈를 사용하여 런타임 오류를 방지해야 한다.
cypress/e2e/leaderboards.cy.ts (1)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
cypress/e2e/login.cy.ts (4)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/Content.tsx:49-60
Timestamp: 2024-11-28T07:35:06.631Z
Learning: In the login page (`src/app/(login)/Content.tsx`), error messages are not displayed separately due to the current implementation.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-2
Timestamp: 2024-11-28T07:36:05.773Z
Learning: `src/app/main/page.tsx` 파일에서, 사용되지 않는 페이지로 남는 문제를 방지하기 위해 `Content` 컴포넌트를 아직 구현되지 않았더라도 import하는 것이 허용됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/Content.tsx:0-0
Timestamp: 2024-11-28T07:23:17.460Z
Learning: `src/app/(login)/Content.tsx`의 `instance` 함수는 기본적으로 headers를 제공하므로, 별도의 headers 설정이 필요하지 않습니다.
cypress/e2e/main.cy.ts (4)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-1
Timestamp: 2024-11-28T06:56:55.698Z
Learning: `src/app/main/Content.tsx`에 있는 `Content` 컴포넌트는 React와 TypeScript로 작성되었으며, `feature/dashboard` 브랜치에서 구현될 예정입니다. 현재 브랜치에 추가된 경우는 실수로 인한 것이므로, 향후 리뷰에서는 이 점을 고려하겠습니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/main/page.tsx:1-2
Timestamp: 2024-11-28T07:36:05.773Z
Learning: `src/app/main/page.tsx` 파일에서, 사용되지 않는 페이지로 남는 문제를 방지하기 위해 `Content` 컴포넌트를 아직 구현되지 않았더라도 import하는 것이 허용됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
Learnt from: Nuung
PR: Check-Data-Out/velog-dashboard-v2-fe#23
File: src/components/auth-required/notice/index.tsx:18-27
Timestamp: 2025-03-11T12:38:34.012Z
Learning: React 컴포넌트에서 API 응답 데이터를 처리할 때는 데이터가 없거나 배열이 비어있는 경우(전체 기능 비활성화, DB 마이그레이션, DBMS 연결 문제 등)에 대비한 방어적 코딩이 필요하다. 특히 `data?.posts[0]`과 같이 배열의 요소에 접근하기 전에 `if (!data?.posts || data.posts.length === 0) return;`와 같은 가드 클로즈를 사용하여 런타임 오류를 방지해야 한다.
cypress/support/commands.ts (1)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
cypress/support/base.ts (2)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/api/index.ts:9-18
Timestamp: 2024-11-28T07:55:51.854Z
Learning: `src/api/index.ts` 파일의 `response` 인터셉터에서 에러 처리는 fetch 반환 객체의 구조가 항상 일정하고, 서버에서 커스텀 오류 메시지를 전송하기 때문에 현재 구현된 방식 그대로 유지한다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#3
File: src/api/index.ts:23-37
Timestamp: 2024-12-08T13:32:30.200Z
Learning: In `src/api/index.ts`, the `instance` 함수에서 JSON 파싱이 자동으로 처리됩니다.
cypress/support/e2e.ts (3)
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#3
File: src/api/index.ts:23-37
Timestamp: 2024-12-08T13:32:30.200Z
Learning: In `src/api/index.ts`, the `instance` 함수에서 JSON 파싱이 자동으로 처리됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/Content.tsx:0-0
Timestamp: 2024-11-28T07:23:17.460Z
Learning: `src/app/(login)/Content.tsx`의 `instance` 함수는 기본적으로 headers를 제공하므로, 별도의 headers 설정이 필요하지 않습니다.
cypress/support/mock.ts (4)
Learnt from: Nuung
PR: Check-Data-Out/velog-dashboard-v2-fe#23
File: src/components/auth-required/notice/index.tsx:18-27
Timestamp: 2025-03-11T12:38:34.012Z
Learning: React 컴포넌트에서 API 응답 데이터를 처리할 때는 데이터가 없거나 배열이 비어있는 경우(전체 기능 비활성화, DB 마이그레이션, DBMS 연결 문제 등)에 대비한 방어적 코딩이 필요하다. 특히 `data?.posts[0]`과 같이 배열의 요소에 접근하기 전에 `if (!data?.posts || data.posts.length === 0) return;`와 같은 가드 클로즈를 사용하여 런타임 오류를 방지해야 한다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/api/index.ts:9-18
Timestamp: 2024-11-28T07:55:51.854Z
Learning: `src/api/index.ts` 파일의 `response` 인터셉터에서 에러 처리는 fetch 반환 객체의 구조가 항상 일정하고, 서버에서 커스텀 오류 메시지를 전송하기 때문에 현재 구현된 방식 그대로 유지한다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#3
File: src/api/index.ts:23-37
Timestamp: 2024-12-08T13:32:30.200Z
Learning: In `src/api/index.ts`, the `instance` 함수에서 JSON 파싱이 자동으로 처리됩니다.
Learnt from: six-standard
PR: Check-Data-Out/velog-dashboard-v2-fe#2
File: src/app/(login)/page.tsx:0-0
Timestamp: 2024-11-28T07:21:09.457Z
Learning: velog-dashboard-v2-fe 프로젝트의 로그인 페이지(`src/app/(login)/page.tsx`)에서 서버는 쿠키를 직접 가져가는 방식으로 동작하므로, API 응답 성공 전에 쿠키를 설정해야 합니다.
🧬 Code Graph Analysis (6)
src/utils/__tests__/number.util.test.ts (1)
src/utils/number.util.ts (1)
parseNumber
(8-13)
cypress/e2e/leaderboards.cy.ts (1)
cypress/support/base.ts (1)
BaseSuccess
(1-9)
cypress/e2e/main.cy.ts (1)
cypress/support/base.ts (1)
BaseSuccess
(1-9)
cypress/support/commands.ts (1)
cypress/support/mock.ts (2)
MOCK_ACCESS_TOKEN
(3-3)MOCK_REFRESH_TOKEN
(4-4)
src/utils/__tests__/datetime.util.test.ts (1)
src/utils/datetime.util.ts (3)
convertDateToKST
(24-48)KSTDateFormat
(6-15)formatTimeToMMSS
(57-64)
cypress/support/e2e.ts (2)
cypress/support/base.ts (2)
BaseError
(11-22)BaseSuccess
(1-9)cypress/support/mock.ts (9)
userResponseData
(7-12)postsFirstData
(15-41)postsSecondData
(43-69)postsStatsResponseData
(85-94)userLeaderboardResponseData
(129-165)postLeaderboardResponseData
(168-204)totalStatsResponseData
(207-215)notificationsResponseData
(218-235)postsGraphData
(72-82)
🔇 Additional comments (31)
src/utils/__tests__/datetime.util.test.ts (1)
1-91
: 테스트 커버리지가 우수합니다!datetime 유틸리티 함수들에 대한 포괄적이고 체계적인 테스트 케이스들이 잘 작성되어 있습니다. 특히 경계값, 소수점 처리, 잘못된 입력에 대한 테스트가 포함되어 있어 함수의 안정성을 보장합니다.
src/shared/index.ts (1)
8-8
: LGTM! EmptyState export 추가가 적절합니다.새로운 EmptyState 컴포넌트를 shared 모듈을 통해 접근할 수 있도록 하는 적절한 변경사항입니다.
cypress/support/index.ts (1)
1-4
: LGTM! Cypress 지원 유틸리티 통합이 잘 구성되었습니다.Cypress 테스트에 필요한 지원 모듈들을 단일 진입점으로 통합하는 적절한 구조입니다. 이는 테스트 파일에서 필요한 유틸리티와 목(mock)에 쉽게 접근할 수 있게 해줍니다.
src/constants/env.constant.ts (1)
13-14
: Cypress 테스트 환경 지원을 위한 적절한 변경사항입니다.환경변수 검증 로직에
!process.env.CYPRESS
조건을 추가하여 Cypress E2E 테스트 환경에서 환경변수 누락으로 인한 오류를 방지하는 것은 매우 적절한 접근입니다. 이는 PR의 전체적인 테스팅 전략 변경과 일치합니다.package.json (2)
15-21
: 스크립트 구조 개선과 Cypress 도입이 잘 반영되었습니다.스크립트명을
jest:test
,eslint:lint
,prettier:format
으로 변경하여 목적을 명확히 하고, Cypress 관련 스크립트를 추가한 것은 매우 적절합니다. 특히cypress:open
(프리뷰 포함)과cypress:test
(헤드리스 모드) 구분이 개발 편의성을 높입니다.
48-67
: Cypress 의존성 추가가 적절합니다.
cypress
와@cypress/webpack-preprocessor
추가로 E2E 테스팅 환경이 완성되었습니다. MSW에서 Cypress로의 전환 전략이 package.json에 잘 반영되어 있습니다.src/utils/number.util.ts (1)
8-13
: 방어적 프로그래밍으로 함수 안전성이 크게 향상되었습니다.
undefined
,Infinity
,NaN
처리를 추가하고Math.floor
를 사용하여 정수 부분만 포맷팅하는 것은 매우 적절한 리팩토링입니다. 특히 API 응답 데이터가 예상과 다를 수 있는 상황에서 일관된'0'
반환으로 UI 안정성을 보장합니다.src/app/components/Header/index.tsx (1)
55-58
: 테스트 환경 호환성과 캐시 전략이 잘 개선되었습니다.
staleTime
5분 설정과retry: 1
옵션 추가로 성능을 최적화하고, enabled 조건을 제거하여 Cypress 테스트 환경에서의 호환성을 높인 것은 매우 적절한 변경사항입니다. 주석으로 변경 의도가 명확히 표현되어 있어 좋습니다.readme.md (2)
30-31
: 스크립트명 변경이 문서에 정확히 반영되었습니다.
eslint:lint
와prettier:format
으로 명령어가 더 명확해져서 개발자들이 각 도구의 목적을 쉽게 이해할 수 있습니다. package.json의 변경사항과 완벽히 일치합니다.
35-37
: 테스팅 명령어 구분이 매우 명확해졌습니다.단위 테스트(
jest:test
)와 E2E 테스트(cypress:open
,cypress:test
)를 명확히 구분하고, Cypress 테스트에서 프리뷰 유무를 구분한 것이 사용자 편의성을 크게 높입니다. 새로운 테스팅 전략이 문서에 잘 반영되어 있습니다.src/utils/__tests__/number.util.test.ts (1)
1-52
: 포괄적이고 잘 작성된 단위 테스트입니다.
parseNumber
함수의 모든 주요 동작을 체계적으로 테스트하고 있습니다:
- 천 단위 콤마 포맷팅 (정수, 음수)
- 특수값 처리 (undefined, NaN, Infinity)
- 소수점 처리 (정수 부분만 반환)
- 경계값 테스트 (999, 1000 등)
테스트 케이스들이 함수의 실제 구현체와 정확히 일치하며, 한국어로 작성된 설명도 명확합니다.
src/app/(auth-required)/main/Content.tsx (4)
10-10
: EmptyState 컴포넌트 import가 적절합니다.새로 도입된 공용 컴포넌트를 올바르게 import하고 있습니다.
24-28
: useInfiniteQuery에서 isLoading 상태 추출이 적절합니다.빈 데이터 상태 처리를 위해 필요한 로딩 상태를 올바르게 추출하고 있습니다.
57-58
: 빈 데이터 상태 로직이 올바르게 구현되었습니다.로딩 중이 아니고 게시물이 없는 경우를 정확히 감지하는 로직입니다. 이전 학습내용과 일치하는 방어적 코딩 패턴을 따르고 있습니다.
101-111
: EmptyState 컴포넌트 사용이 적절합니다.빈 데이터 상태에 대한 사용자 친화적인 메시지와 아이콘을 제공하여 UX를 개선했습니다. 조건부 렌더링 로직도 명확합니다.
cypress/support/commands.ts (3)
3-8
: 쿠키 보안 옵션이 적절하게 설정되었습니다.
httpOnly
,secure
,sameSite: 'strict'
등 보안을 고려한 쿠키 설정 옵션들이 올바르게 적용되어 있습니다.
16-19
: 쿠키 정리 명령어가 적절합니다.인증 관련 쿠키들을 깔끔하게 정리하는 명령어입니다.
21-24
: 페이지 로드 대기 로직이 적절합니다.body 요소의 가시성과 document 속성 존재를 확인하여 페이지 로드 완료를 안정적으로 감지하고 있습니다.
src/app/(auth-required)/leaderboards/Content.tsx (6)
23-34
: 기본값 처리가 적절하게 개선되었습니다.기본 파라미터를 명시적으로 정의하고 사용자 입력과 병합하는 방식이 일관성 있고 명확합니다. 이는 이전 리뷰에서 언급된 defaultValue 동기화 문제를 부분적으로 개선합니다.
36-39
: 쿼리에서 isLoading 상태 추출이 적절합니다.빈 데이터 상태 처리를 위해 필요한 로딩 상태를 올바르게 추출하고 있으며, finalParams를 일관되게 사용하고 있습니다.
41-51
: 데이터 변환 로직에서 finalParams 사용이 일관됩니다.memoized 데이터 변환에서도 finalParams를 일관되게 사용하여 파라미터 관리가 통일되었습니다.
58-59
: 빈 데이터 상태 로직이 올바르게 구현되었습니다.로딩 중이 아니고 데이터가 없는 경우를 정확히 감지하는 로직입니다.
91-91
: defaultValue에서 finalParams 사용이 적절합니다.일관된 파라미터 사용으로 UI 동기화를 개선했습니다.
105-115
: EmptyState 컴포넌트 사용이 적절합니다.현재 필터 조건에 맞는 동적 메시지를 제공하여 사용자가 빈 데이터 상태를 이해하기 쉽게 했습니다. 조건부 렌더링 로직도 명확합니다.
cypress.config.ts (1)
3-27
: Cypress E2E 테스트 설정이 적절합니다.다음 설정들이 잘 구성되어 있습니다:
- 기본 URL과 파일 패턴 설정
- 적절한 뷰포트 크기 (1920x1080)
- 합리적인 타임아웃 설정 (10초)
- 테스트용 환경 변수 정의
- 비디오 녹화 비활성화로 성능 최적화
setupNodeEvents
함수가 현재는 비어있지만, 필요에 따라 나중에 구현할 수 있는 구조로 되어있어 적절합니다.cypress/e2e/login.cy.ts (1)
1-52
: 우수한 로그인 페이지 E2E 테스트 구현입니다.포괄적인 테스트 시나리오와 견고한 셀렉터 전략이 인상적입니다:
- 다중 대체 옵션을 가진 유연한 셀렉터 사용 (예:
input[name*="accessToken"], input[name*="access"], input[placeholder*="Access"]
)- 성공/실패 시나리오 모두 커버
- 샘플 로그인 기능까지 포함한 완전한 테스트 커버리지
테스트가 UI 변경에 대해 내성을 가지면서도 기능을 정확히 검증합니다.
cypress/e2e/main.cy.ts (1)
1-72
: 메인 페이지 E2E 테스트가 매우 잘 구현되었습니다.특히 다음 부분들이 우수합니다:
setAuthCookies()
를 통한 적절한 인증 설정- 대시보드 통계와 게시물 목록의 구체적 데이터 검증
- 빈 데이터 상태에 대한 포괄적 테스트 (라인 57-71)
빈 데이터 상태 테스트에서
cy.intercept
를 사용하여 API 응답을 모킹하고EmptyState
컴포넌트의 렌더링을 검증하는 접근법이 특히 인상적입니다.cypress/e2e/leaderboards.cy.ts (1)
1-84
: 리더보드 페이지 E2E 테스트가 매우 포괄적으로 구현되었습니다.다음 사항들이 특히 우수합니다:
- 4개의 필터 드롭다운에 대한 체계적인 테스트 (라인 34-45)
- 사용자/게시물 리더보드 모드 간 전환 테스트
- 빈 데이터 상태에 대한 이중 검증 (사용자 및 게시물 리더보드 모두)
필터 기능 테스트에서 각 select 요소를
eq()
인덱스로 정확히 타겟팅하는 방식과, 빈 상태 테스트에서 두 개의 별도 API 인터셉트를 사용하는 접근법이 매우 체계적입니다.cypress/support/base.ts (1)
1-22
: API 응답 모킹을 위한 우수한 유틸리티 함수 설계입니다.다음과 같은 장점들이 있습니다:
BaseSuccess
의 제네릭 타입 사용으로 타입 안전성 확보- 일관된 응답 구조 (
statusCode
,body
내success
,message
,data
,error
)- 한국어 기본 메시지로 프로젝트 언어 정책에 부합
- 유연한 에러 상태 코드 지원
이 함수들이 전체 Cypress 테스트 환경에서 일관된 API 모킹을 제공하는 기반이 됩니다.
cypress/support/e2e.ts (2)
15-85
: 포괄적인 Cypress E2E 설정이 매우 잘 구현되었습니다.특히 다음 부분들이 우수합니다:
- 조건부 로그인 검증 로직 (라인 16-23): 유효하지 않은 토큰에 대한 적절한 에러 응답
- 커서 기반 페이지네이션 처리 (라인 37-44): URL 파라미터 기반 동적 응답
- 모든 주요 API 엔드포인트에 대한 완전한 인터셉트 커버리지
API 모킹 전략이 실제 백엔드 동작을 잘 시뮬레이션하며, 테스트의 안정성과 예측 가능성을 보장합니다.
87-101
: TypeScript 인터페이스 선언이 적절합니다.커스텀 Cypress 명령어들에 대한 타입 선언이 정확하고, 주석으로 각 함수의 목적을 명확히 설명했습니다. ESLint 규칙 비활성화도 필요한 범위로 제한되어 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드 잘 봤습니다! 코멘트 확인 한 번 부탁드려요!
정말 고생 많으셨습니다!! 👍 🔥
좋았던 점
- 유틸에 검증이 강화된 부분도 좋고, 관련 테스트 작성해주신 부분도 너무 좋았습니다!
- 데이터 없는 경우에 대해 추가된 컴포넌트도 좋았습니다.
- cypress라는 툴을 처음 봤는데 좋은 것 같아요! E2E 테스팅 깔끔하게 잘 될 것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
코드 잘 봤습니다. 고생하셨습니다!
회의 때 cypress라는 툴을 처음 접했는데 오,, 신기하네요👍
이번 PR에서 e2e 테스트 동작 과정을 조금 더 이해하게 된 것 같습니다!
좋았던 점
- 게시물이 없는 경우, 리더보드 데이터가 없는 경우에 대한 처리가 추가된 점이 좋은 것 같습니다!
- 중복되는 로직을 util로 분리하신 점이 좋았습니다.
궁금한 점
- 추가로 충돌이 발생한 부분은 어떤 이유 때문일까요?? 궁금해서 여쭤봅니다!!
cy.get('button[type="submit"], button:contains("로그인")').first().click(); | ||
|
||
cy.url().should('eq', Cypress.config().baseUrl + '/'); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
빈 값으로 입력되었을 경우에 대한 유효성 검사는 없어도 괜찮을까요??!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 맞습니다!
애초에 빈 값일 경우에는 버튼 활성화가 되지 않아서 큰 문제가 없을 것 같아요~
return Math.floor(item) | ||
.toString() | ||
.replace(/\B(?=(\d{3})+(?!\d))/g, ','); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
반복되는 로직 util로 분리하신 점 좋은 것 같아요👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋았던 점
- 케이스가 꽤나 빼곡하게, 핵심 feature 위주로 E2E 잘 작성해주셔서 너무 좋았습니다!
- 고생많으셨어요!, 다른 분들이 세심하게 리뷰잉 해주셔서 저는 조그마한 코멘트만 남겨봅니다!
아쉬운 점
- BaseError 를 실제로 test 하는 경우가 많이 없어서요! 지금 사실 가장 필요한 부분이 api timeout 에러시 그냥 next error page 가 나오는 경우거든요.
- E2E 특성상 known error 위주로 다루듯, 저희도 known error case 가 있으면 더 좋을 것 같아요.
known error case
중 대표적인게 00 시 넘어서 아직 신규 데이터 수집이 안되었을때 음수로 나온다던가 등?
* @param {number} [item] - 변환할 정수 | ||
* @returns {string} | ||
*/ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그냥 이전부터 궁금했는데, jsdocs 에 공백을 두는 이유가 있어요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그냥 개인적인 습관인 것 같습니다
붙이는것보다 띄우는 게 가독성 면에서 더 좋다고 생각하고 있습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html
공식 ts 에서 jsdocs 에 대한 내용
https://jsdoc.app/
공식 jsdocs 도 모두 붙이는데, 이 참에 기준님 습관을 바꿔보는 것은 어떨까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(node, react jsdocs 도 깃헙 레포 보시면, 모두 붙여 쓰는 것을 볼 수 있습니다!)
src/utils/datetime.util.ts
Outdated
|
||
export const formatTimeToMMSS = (time: number) => { | ||
const minute = Math.floor(time / 60) | ||
const minute = Math.floor(Math.floor(time) / 60) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 정도면 기준님 커서 압수해야하는거 아님ㅋㅋㅋㅋㅋㅋ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오.. 저 부분은 좀 예상을 못 했네요;;
이전에 한 번 전체 Accept할 때 슬쩍 끼워뒀나 봅니다..
env: { | ||
NEXT_PUBLIC_BASE_URL: 'http://localhost:3000', | ||
NEXT_PUBLIC_CHANNELTALK_PLUGIN_KEY: 'test_key', | ||
NEXT_PUBLIC_GA_ID: '', | ||
NEXT_PUBLIC_SENTRY_AUTH_TOKEN: 'test_sentry_token', | ||
NEXT_PUBLIC_SENTRY_DSN: 'test_sentry_dsn', | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이제 환경 변수 추가 또는 변경될 때 마다 해당 값도 바뀌어야 겠네요..?!
다른 방법은 없을까..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분은 지금 당장 대책이 안 떠오르기는 하네요..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
남겨주신 코멘트 확인 했습니다! 고생 많으셨습니다~~~!! 👍 🚀
🔥 변경 사항
단순 Jest + React-Testing-Library로 구현되어 있던 테스트 환경을 정리하였습니다!
페이지 컴포넌트는 Cypress 기반 E2E 테스트, 이외 유틸리티 함수 관련 테스트는 Jest 기반 단위 테스트로 변경하였습니다.
또한, MSW 등 현재 테스트 환경에 맞지 않는 도구들을 제거하고, README 파일을 정리하였습니다.
🏷 관련 이슈
📸 스크린샷 (UI 변경 시 필수)
📌 체크리스트
Summary by CodeRabbit
새로운 기능
버그 수정
문서화
테스트/빌드 환경
리팩터