Skip to content
Merged
89 changes: 89 additions & 0 deletions .cursor/rules/testing.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## <!-- .cursor/rules/test.playwright.mdc -->

description: "Testing rules (Jest + RTL + Playwright)"
globs: ["**/*.{ts,tsx}"]
alwaysApply: true

---

# Testing Rules

## General

- File naming: `*.test.ts(x)` for unit/component, `*.spec.ts(x)` for integration/E2E.
- Co-locate tests with code when small; otherwise keep under `/tests`.
- Aim for high-value coverage (core logic ~80%+). Skip trivial one-liners.
- Naming: `describe(Component)` + `it('renders …')` with full-sentence style.
- **Comments must be in English** for international collaboration and maintainability.
- **Keep comments minimal and concise** - only add comments when they provide essential context or explain non-obvious behavior.

## Unit/Component (Jest + React Testing Library)

- Test **public behavior** (render, interaction, output). Avoid testing internals.
- Each critical component should include:
- Render snapshot (basic mount),
- Interaction (click, input, keyboard),
- a11y basics (role/label presence, keyboard navigation),
- Store selector correctness (mock store when needed).
- Prefer `screen.getByRole` over `getByTestId` unless no semantic alternative.
- Use `@testing-library/jest-dom` matchers for DOM assertions.

## Store (Zustand slices)

- Test actions:
- Initial state correctness,
- Success/error branches,
- Immutable updates.
- Async actions: mock API calls, assert `isLoading/error/data` transitions.
- Test persistence middleware behavior when applicable.

## E2E (Playwright)

- Cover only critical flows:
- Happy path: load → interact → result,
- Core regressions: auth, filters, CRUD happy path.
- Store screenshots/videos on CI for failed runs.
- Prefer deterministic locators (role, label, data-testid) over CSS selectors.
- Use `page.waitForSelector` for dynamic content loading.

## Package-Specific Rules

### View Package

- Test React components with Jest + RTL
- Test Zustand stores (theme, branch, data, loading, etc.)
- E2E tests for webview interactions
- Mock VSCode API calls appropriately

### Analysis Engine Package

- Test core logic with Jest (Node environment)
- Mock external dependencies (GitHub API, file system)
- Test parsing and analysis algorithms

### VSCode Extension Package

- Test extension commands and utilities
- Mock VSCode extension API
- Test webview communication

## Iterative Test Refinement

- When a test fails, analyze the provided error log to identify the root cause.
- **Priority 1: Locators.** If an element is not found, correct the Playwright locator first. Prefer `getByRole`, `getByText`, `data-testid` in that order.
- **Priority 2: Timing.** If the locator is correct but the element is not ready, add or adjust `page.waitForSelector` or other appropriate `waitFor` functions. Do not use fixed `page.waitForTimeout()`.
- **Priority 3: Assertions.** Ensure the assertion (`expect()`) matches the actual state of the application described in the error log.
- Modify the minimum necessary code to fix the specific error. Do not refactor unrelated code.

## Accessibility

- Include basic accessibility checks (role/label presence, keyboard navigation).
- Ensure focus management in modals/menus is tested.

## Misc

- Keep tests fast/deterministic. Avoid real timeouts/network.
- Use Jest's timer mocking (`jest.useFakeTimers`) if time-dependent.
- Mock D3.js and other heavy dependencies appropriately.
- Use `testPathIgnorePatterns` to exclude build artifacts.
- Ensure focus management in modals/menus is tested.
139 changes: 139 additions & 0 deletions .cursor/templates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Cursor AI 테스트 생성 도구

이 디렉토리는 Cursor AI를 활용하여 **Githru VSCode Extension** 프로젝트의 테스트 코드를 자동 생성하는 도구들을 모아놓은 곳입니다.

## 📁 프로젝트 구조

```
githru-vscode-ext/
├── .cursor/ # Cursor AI 도구들
│ ├── rules/
│ │ └── testing.mdc # 테스트 작성 규칙
│ └── templates/
│ ├── test.playwright.md # E2E 테스트 템플릿
│ └── README.md # 이 파일
├── packages/
│ ├── view/ # React 웹뷰 패키지
│ │ ├── src/
│ │ │ ├── components/ # React 컴포넌트들
│ │ │ ├── store/ # Zustand 상태 관리
│ │ │ └── fake-assets/ # 테스트용 모킹 데이터
│ │ └── tests/ # 실제 테스트 파일들
│ │ ├── pr-commit-detail.e2e.spec.ts
│ │ ├── temporal-filter.e2e.spec.ts
│ │ └── fakeAsset.ts # 테스트 헬퍼 함수들
│ ├── analysis-engine/ # 분석 엔진 패키지
│ └── vscode/ # VSCode 확장 패키지
```

## 🚀 빠른 시작 (Quick Start)

### 1. E2E 테스트 생성 (Playwright)

**템플릿 파일**: `.cursor/templates/test.playwright.md`

1. **템플릿 열기**: `.cursor/templates/test.playwright.md` 파일을 엽니다
2. **시나리오 작성**: 아래 예시를 참고해 테스트 시나리오를 작성합니다
3. **AI 실행**: `⌃+I` (Cursor Agent)를 누르고 템플릿을 붙여넣습니다
4. **파일 생성**: AI가 자동으로 `packages/view/tests/`에 테스트 파일을 생성합니다

## 📝 사용 예시

### E2E 테스트 예시 (TemporalFilter)

```markdown
Context:

- 테스트 대상: TemporalFilter 컴포넌트
- 시나리오:
- [ ] 기간 브러시 필터링이 정상 작동해야 한다
- [ ] 필터링 후 통계가 갱신되어야 한다
- [ ] Reset 버튼으로 필터가 해제되어야 한다

Constraints:

- Zustand state only (no other state libs)
- Mock external dependencies (GitHub API, file system)
- VSCode webview environment
```

**결과**: `packages/view/tests/temporal-filter.e2e.spec.ts` 파일 생성

## 🔧 테스트 룰 및 규칙

### 자동 적용되는 룰

**룰 파일**: `.cursor/rules/testing.mdc`

- Cursor가 자동으로 이 룰을 적용하여 일관된 테스트 코드를 생성합니다
- **Jest + RTL + Playwright** 패턴을 따릅니다
- **VSCode webview 환경**에 최적화되어 있습니다
- **Zustand 상태 관리**와 **외부 의존성 모킹**을 자동으로 처리합니다

### 파일 명명 규칙

- **E2E 테스트**: `{component-name}.e2e.spec.ts`

### 실제 테스트 파일 위치

```
packages/view/tests/
```

## 🎯 테스트 실행 방법

### E2E 테스트 실행

```bash
# packages/view 디렉토리로 이동
cd packages/view

# 모든 E2E 테스트 실행
npm run test:e2e

# 특정 테스트 실행
npm run test:e2e -- tests/pr-commit-detail.e2e.spec.ts
npm run test:e2e -- tests/temporal-filter.e2e.spec.ts

# 특정 브라우저에서 실행
npm run test:e2e -- --project=chromium
npm run test:e2e -- --project=webkit
```

### 테스트 결과 확인

```bash
# 테스트 리포트 확인
npx playwright show-report

# 헤드리스 모드로 실행
npm run test:e2e -- --headed

# 디버그 모드로 실행
npm run test:e2e -- --debug
```

## 🔧 커스터마이징

### 새로운 템플릿 추가

1. `.cursor/templates/` 디렉토리에 새 `.md` 파일 생성
2. 프롬프트 템플릿 작성
3. 이 README에 사용법 추가

**현재 사용 가능한 템플릿**:

- `test.playwright.md`: E2E 테스트 생성용

### 룰 수정

1. `.cursor/rules/testing.mdc` 파일 편집
2. 프로젝트 요구사항에 맞게 가이드라인 조정

## ⚠️ 주의사항

- **생성된 테스트는 반드시 실제 실행해보고 검증하세요**
- **VSCode webview 환경의 제약사항**을 고려하세요
- **Zustand 상태 관리**와 **외부 의존성 모킹**이 자동으로 적용됩니다
- **로딩 상태가 너무 빠를 경우** 스피너 테스트가 스킵될 수 있습니다
- **실제 DOM 구조**에 맞춰 셀렉터가 자동으로 조정됩니다
95 changes: 95 additions & 0 deletions .cursor/templates/test.playwright.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<!-- ai/template/test.playwright.md -->

# ✅ Playwright Test Prompt (Auto-Enhanced)

## 🎯 목적

주요 사용자 시나리오를 **E2E 테스트**로 검증한다.
E2E 테스트 코드를 생성하고 자동으로 실행하여 실패 시 수정까지 한 번에 처리한다.

---

## 📌 사용 방법

1. 테스트 대상 컴포넌트/플로우를 지정한다.
2. 주요 시나리오(AC 기반)를 적는다.
3. Cursor Agent (⌃+I)에 붙여넣는다.
4. **자동으로 테스트 실행 및 결과 분석**
5. **실패 시 자동 수정 제안 및 재실행**

---

## 🚦 가드레일

You are in **AUTO-ENHANCED-TEST-GENERATION** mode.
MUST create runnable Playwright test code (`*.spec.ts`) AND automatically execute it.
Follow project conventions (TypeScript, Playwright setup).
Keep tests fast, deterministic (no arbitrary `timeout`).

**CRITICAL WORKFLOW:**

1. Generate test code based on scenarios
2. Execute test automatically
3. If test fails, analyze error and fix test code
4. Retry up to 3 times with automatic fixes
5. Only modify test code, never modify source code

---

## 입력 템플릿

Context:

- 테스트 대상 (페이지/컴포넌트):
- 시나리오 (AC):
- [ ] 시나리오 1
- [ ] 시나리오 2
- [ ] 시나리오 3

Constraints:

- Zustand state only (no other state libs)
- Mock external dependencies (GitHub API, file system)
- VSCode webview environment

---

## Output contract

- Playwright test code in TypeScript (`*.spec.ts`)
- 테스트는 Happy Path + Critical Regression 최소 커버
- 코드 블록은 반드시 실행 가능해야 함
- Use `page.waitForSelector` for dynamic content
- **반드시 파일 생성**: `packages/view/tests/{component-name}.e2e.spec.ts` 경로에 저장
- **자동 실행**: 생성 후 즉시 `npm run test:e2e` 실행
- **자동 수정**: 실패 시 에러 분석 후 수정된 코드 제안
- **최대 3회 재시도**: 테스트 코드만 수정하여 성공할 때까지 시도
- **소스 코드 수정 금지**: 테스트 코드만 변경 가능

## 🔄 자동 수정 규칙

### 로케이터 오류 수정

- `page.locator()` → `page.waitForSelector()` + `page.locator().first()`
- 더 구체적인 셀렉터 사용
- `data-testid` 우선 사용

### 타이밍 이슈 수정

- `timeout` 값 2배 증가
- `page.waitForLoadState('networkidle')` 추가
- `page.waitForTimeout()` 적절히 사용

### 네트워크 에러 수정

- `page.route()` 사용하여 API 모킹
- `beforeEach`에 네트워크 모킹 추가

### 콘솔 에러 수정

- `page.on('console')` 이벤트 리스너 추가
- 에러 로깅 및 처리

End with:

- CONFIRM: TEST CASES GENERATED AND EXECUTED
Loading
Loading