Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
f0c82ed
과제시작
nemobim Aug 24, 2025
2f00d94
fix: server.js 수정
nemobim Aug 26, 2025
cbca6db
❌ test: 반복 유형 선택 테스트 작성
nemobim Aug 27, 2025
c53b907
✅ test: 반복 유형 선택 기능 구현
nemobim Aug 27, 2025
e034477
❌ test: 반복 유형 선택 일,주,월,년 테스트 작성
nemobim Aug 27, 2025
cd58aa4
✅ test: 반복 유형 선택 일,주,월,년 기능 구현
nemobim Aug 27, 2025
3ef75ff
❌ test: 반복 유형 선택(31일 특정 케이스) 테스트 코드 작성
nemobim Aug 27, 2025
aea65ab
✅ test: 반복 유형 선택(31일 특정 케이스) 기능 구현
nemobim Aug 27, 2025
9530c0e
❌ test: 반복 유형 선택(윤년 29일 특정 케이스 처리) 테스트 코드 작성
nemobim Aug 27, 2025
9242ad5
✅ test: 반복 유형 선택(윤년 29일 특정 케이스 처리) 기능 구현
nemobim Aug 27, 2025
0c8d136
♻️ test: 반복 유형 선택 리팩토링
nemobim Aug 27, 2025
afcd8ac
😧fix: 함수 테스트 tsx > ts로 파일 확장자 수정
nemobim Aug 27, 2025
e21a4c6
❌ test: 반복 일정 표시 테스트 코드 작성
nemobim Aug 27, 2025
04c8917
✅ test: 반복 일정 표시 컴포넌트 구현
nemobim Aug 27, 2025
16215ed
❌ test: 주,월,년에 대한 반복 일정 표시 테스트 코드 추가
nemobim Aug 27, 2025
c3e2513
✅ test: 주,월,년에 대한 반복 일정 아이콘 컴포넌트 구현
nemobim Aug 27, 2025
4028545
♻️ test: 반복 일정 표시 리팩토링
nemobim Aug 27, 2025
7596551
❌ test: 반복 종료 조건( 2025-10-30까지 최대 일자) 테스트 코드 추가
nemobim Aug 27, 2025
3b11723
✅ test: 반복 종료 조건( 2025-10-30까지 최대 일자) 기능 구현
nemobim Aug 27, 2025
204cfd8
❌ test: 반복 일정 단일 수정 테스트 코드 작성
nemobim Aug 27, 2025
5291782
✅ test: 반복 일정 단일 수정 기능 구현
nemobim Aug 27, 2025
390e999
🔦 test: 반복 일정 단일 수정 특정 상황 테스트 코드 추가
nemobim Aug 27, 2025
fc6faf6
❌ test: 반복 일정 단일 삭제 테스트 코드 작성
nemobim Aug 27, 2025
26f5f06
✅ test: 반복 일정 단일 삭제 기능 구현
nemobim Aug 27, 2025
b31e7f7
🔦 test: 반복 일정 단일 삭제 기능 특정 상황 테스트 코드 추가
nemobim Aug 27, 2025
ce7b261
✨ feat: 반복일정 추가 기능 구현
nemobim Aug 27, 2025
6c010f7
✨ feat: 반복 일정 표시 아이콘 추가
nemobim Aug 27, 2025
83dc5f8
🚨 test: 반복일정 통합테스트를 위한 handlers, handelersUtils 추가
nemobim Aug 27, 2025
4f14ca2
😧 fix: 반복일정 api events 에서 events-list로 수정
nemobim Aug 27, 2025
b213e88
🧪 test: 반복 일정 생성관련 통합 테스트 추가
nemobim Aug 28, 2025
e5d8d1b
🧪 test: 반복 통합 테스트에 아이콘이 표시 케이스 추가
nemobim Aug 28, 2025
8b50b34
😧 fix: App, handlers, handlersUtils 원복
nemobim Aug 28, 2025
46c6d1d
😧 fix: useEventOperations 원복
nemobim Aug 28, 2025
8833234
✨ feat: 반복 일정 기능 재구현
nemobim Aug 28, 2025
cf10130
😧 fix: mockJson 원복
nemobim Aug 28, 2025
0cb5ced
🐛 fix: 반복 일정 단일 삭제 안되는 오류 수정
nemobim Aug 28, 2025
344f708
🗑️ remove: 반복일정 삭제 후 CI 통과 확인
nemobim Aug 28, 2025
c80026c
🐛 fix: 반복 일정 단일 삭제 기능 원복
nemobim Aug 28, 2025
475ff13
🐛 fix: 반복 일정 단일 수정 기능 코드 개선
nemobim Aug 28, 2025
08b83fa
🧪 test: 반복 통합테스트와 알림 통합테스트 시나리오 작성
nemobim Aug 28, 2025
b756a60
🧪 test: (심화) 알림 통합 테스트 시나리오 작성 및 테스트 추가
nemobim Aug 28, 2025
0e33a24
😧 test: ci 확인용 테스트
nemobim Aug 28, 2025
12c05be
🧪 test: (심화) form 통합 테스트 시나리오 작성 및 테스트 추가
nemobim Aug 28, 2025
7342769
🧪 test: (심화) 뷰 간 데이터 동기화 시나리오 작성 및 테스트 추가
nemobim Aug 28, 2025
2a760c3
🐛 fix: 타임아웃 10000로 수정
nemobim Aug 28, 2025
2a84675
🧪 test: (심화) 검색어 필터링 e2e 추가
nemobim Aug 28, 2025
7de223c
🐛 fix: CI 오류 테스트
nemobim Aug 28, 2025
b41d8eb
🐛 fix: CI 오류 테스트
nemobim Aug 28, 2025
b6a3708
🐛 fix: CI 오류 테스트
nemobim Aug 28, 2025
e0f0cd0
🐛 fix: CI 오류 테스트
nemobim Aug 28, 2025
d0365ad
🧪 test: (심화) 기본 일정 관리 e2e 추가
nemobim Aug 28, 2025
92c8a07
🧪 test: (심화) 캘린더뷰 e2e 추가
nemobim Aug 28, 2025
79dea7a
🔦 chore: ci에 e2e 실행 명령어 추가
nemobim Aug 28, 2025
23c3832
🔦 chore: ci에 e2e 실행 명령어 추가-1
nemobim Aug 28, 2025
121f431
🔦 chore: ci에 e2e 실행 명령어 추가-2
nemobim Aug 28, 2025
0d62674
🔦 chore: ci에 e2e 실행 명령어 추가-3
nemobim Aug 28, 2025
7c93bc8
🔦 chore: ci에 e2e 실행 명령어 추가-4
nemobim Aug 28, 2025
f0c5f94
🔦 chore: ci에 e2e 실행 명령어 추가-5
nemobim Aug 28, 2025
fd72066
🧪 test: 반복 일정 생성 통합 테스트 작성
nemobim Aug 28, 2025
3253fc7
🧪 test: 반복 일정 종료기간 설정 통합 테스트 작성
nemobim Aug 28, 2025
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
211 changes: 211 additions & 0 deletions .cursor/rules/test-guide.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
---
description: TDD Guidelines for AI Assistants
globs:
alwaysApply: true
---

# TDD Guidelines for AI Assistants

_Based on Kent Beck's philosophy: "Make it work, make it right, make it fast"_

## Core Principles (Immediate Intervention Required if Violated)

1. **Write Tests Before Implementation** – Never write production code without a failing test first.
2. **Minimum Implementation Rule** – Hardcoding is acceptable for the initial pass.
3. **Refactor Only When Green** – Improve structure only after all tests pass.
4. **One at a Time** – One test, one behavior, one failure cause.

---

## TDD Cycle (Red-Green-Refactor)

### Step 1: Write a Failing Test (RED)

```javascript
test('returns success: true when login succeeds', () => {
const result = login('user@test.com', 'password123');
expect(result.success).toBe(true);
});
// Run test → ensure failure first
```

### Step 2: Pass with Minimum Implementation (GREEN)

```javascript
const login = () => {
return { success: true }; // Hardcoding allowed
};
```

### Step 3: Add a New Test to Force Generalization

```javascript
test('returns success: false when login fails', () => {
const result = login('user@test.com', 'wrongpassword');
expect(result.success).toBe(false);
});
```

### Step 4: Implement a Generalized Solution

```javascript
const login = (email, password) => {
return {
success: email === 'user@test.com' && password === 'password123',
};
};
```

---

## Detailed Guidelines

### 1. Readability & Intent-First Design

- Use **descriptive, sentence-style test names**: What / When / How.
- Follow **AAA structure**: Arrange → Act → Assert, or Given → When → Then.
- Minimize control flow logic (if/loop) within tests.
- Each test must clearly communicate **what it verifies**.

```javascript
// ✅ Good Example
test('returns an error message when checking out an empty cart', () => {
const cart = createEmptyCart(); // Arrange
const result = checkout(cart); // Act
expect(result.error).toBe('Your cart is empty'); // Assert
});
```

---

### 2. Allow Meaningful Duplication (DAMP Principle)

- **Allowed duplication**: Enhances clarity and intent within individual tests.
- **Forbidden duplication**: Abstracts away critical context or increases maintenance cost.
- Avoid excessive helpers/fixtures if they obscure the test purpose.
- Always define expected results **explicitly within the test**.

---

### 3. Avoid Implementation-Dependent Tests

- Don’t test private methods, internal states, or call counts.
- Focus on **observable behavior** and **public interfaces**.
- Tests should remain valid even after internal refactoring.

```javascript
// ✅ Behavior-based test
test('applies 20% discount correctly', () => {
expect(calculatePrice(1000, 0.2)).toBe(800);
});

// ❌ Implementation-dependent
test('calls multiply method internally', () => {
/* Do not test internal calls */
});
```

---

### 4. Deterministic & Isolated Tests

- Eliminate flaky tests by controlling:

- **Time** → Use fixed system clocks or fake timers.
- **Randomness** → Provide seeds or fixed values.
- **Network calls** → Use mocks/stubs or MSW (Mock Service Worker).

- Do not share state between tests.
- Each test should run independently in any order.

---

### 5. Single Responsibility Per Test

- One test = one behavior.
- Multiple assertions are okay only if they validate **different aspects of the same behavior**.
- A test should fail for **one clear reason**.

---

### 6. Maintainability & Scalability

- Minimize global fixtures or hidden setup logic.
- Inline duplication where it improves readability.
- Use builders/helpers only when they **reduce noise**, not when they hide intent.
- A failing test should tell you **exactly** what went wrong without reading the implementation.

---

### 7. Balanced Test Strategy

- **Unit tests**: Fast, frequent, cover core logic.
- **Integration/E2E tests**: Fewer but higher confidence.
- Apply the test **pyramid** or **trophy** depending on your team’s domain.

---

### 8. Robust Assertions

- Avoid over-relying on large snapshot tests.
- Prefer explicit assertions on critical properties using `toEqual`, `toBe`, or custom matchers.
- Provide **meaningful failure messages** where possible.

---

### 9. Code Coverage is a Tool, Not the Goal

- Focus on **critical paths, edge cases, and regression scenarios**.
- High coverage naturally emerges from well-scoped, valuable tests.
- Do not write meaningless tests just to boost numbers.

---

## Feature Development Workflow

For any new feature:

1. **Break it down** – “What’s the simplest case?”
2. **RED** – Write a failing test first.
3. **GREEN** – Pass it using minimal implementation.
4. **PRESSURE** – Add tests that force generalization.
5. **REFACTOR** – Improve structure while staying green.
6. **REPEAT** – Iterate for the next scenario.

---

## Common Test Smells (Refactor Immediately)

- Using arbitrary delays or `sleep`.
- Depending on randomness (`Math.random`, UUID without control).
- Overly complex mocks and stubs.
- Large, implicit global fixtures.
- Over-abstracted tests that hide intent.
- Vague or misleading test names.
- Tightly coupled tests that fail when implementation changes.

---

## Code Review Checklist

### TDD Process

- [ ] Were tests written **before** implementation?
- [ ] Does each test verify **only one behavior**?
- [ ] Did implementation start with a **minimum viable solution**?
- [ ] Was refactoring done **only after all tests passed**?

### Test Quality

- [ ] Are test names descriptive and meaningful?
- [ ] Do tests verify **behavior**, not implementation details?
- [ ] Are expected values written explicitly in tests?
- [ ] Are external dependencies (time, network, randomness) properly controlled?

---

**Key Insight**:
TDD is not just a testing methodology — it’s a **design discipline**.
By writing tests first, we guide our design toward better structure and gain confidence in every small step.

---
34 changes: 23 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ on:
- synchronize
- opened
- reopened

workflow_dispatch:

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
Expand All @@ -24,14 +23,16 @@ jobs:
with:
node-version: 20
cache: 'pnpm'
- name: test basic
run: |
pnpm install
pnpm run lint
- name: Install dependencies
run: pnpm install
- name: Run linting
run: pnpm run lint

test:
runs-on: ubuntu-latest
timeout-minutes: 15 # e2e 포함해서 시간 늘림
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
Expand All @@ -42,7 +43,18 @@ jobs:
with:
node-version: 20
cache: 'pnpm'
- name: test basic
run: |
pnpm install
pnpm run test
- name: Install dependencies
run: pnpm install
- name: Run unit tests
run: pnpm run test
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run E2E tests
run: pnpm run test:e2e
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: playwright-report
path: playwright-report/
retention-days: 30
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@
.vscode
node_modules
.coverage

# Playwright
playwright-report/
test-results/
playwright/.cache/
*.trace
*.webm
2 changes: 2 additions & 0 deletions .vitest-preview/index.html

Large diffs are not rendered by default.

12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
"build": "tsc -b && vite build",
"lint:eslint": "eslint . --ext ts,tsx --report-unused-disable-directives",
"lint:tsc": "tsc --pretty",
"lint": "pnpm lint:eslint && pnpm lint:tsc"
"lint": "pnpm lint:eslint && pnpm lint:tsc",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"test:e2e:headed": "playwright test --headed",
"test:e2e:debug": "playwright test --debug",
"test:preview": "vitest-preview"
},
"dependencies": {
"@emotion/react": "^11.11.4",
Expand All @@ -26,13 +31,16 @@
"msw": "^2.10.3",
"notistack": "^3.0.2",
"react": "19.1.0",
"react-dom": "19.1.0"
"react-dom": "19.1.0",
"vitest-preview": "^0.0.1"
},
"devDependencies": {
"@eslint/js": "9.33.0",
"@playwright/test": "^1.55.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^14.5.2",
"@types/node": "^24.3.0",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@typescript-eslint/eslint-plugin": "^8.35.0",
Expand Down
28 changes: 28 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './src/__tests__',
testMatch: '**/*.e2e.ts',
fullyParallel: false, // CI에서는 false로 설정
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: 1, // CI에서는 항상 1로 설정
reporter: 'html',
use: {
baseURL: 'http://localhost:5173',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
webServer: {
command: 'pnpm dev',
url: 'http://localhost:5173',
reuseExistingServer: !process.env.CI,
timeout: 120 * 1000,
},
});
Loading