Skip to content

Commit

Permalink
docs: レビューテスト用バグ一覧ドキュメントを追加
Browse files Browse the repository at this point in the history
  • Loading branch information
User committed Jan 12, 2026
1 parent aeb1860 commit 88267db
Showing 1 changed file with 259 additions and 0 deletions.
259 changes: 259 additions & 0 deletions BUGS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
# レビューテスト用バグ一覧

このドキュメントには、意図的に仕込まれたバグの詳細が記載されています。採点用の参考資料として使用してください。

## バグ一覧

### 難易度1: UIの状態管理不備

**ファイル**: `components/TodoItem.tsx`
**行番号**: 97-104行目

**バグ内容**:
削除ボタンの`disabled`属性が`isDeleting`のみを考慮しており、`isUpdating`が考慮されていない。

**問題コード**:
```tsx
<button
onClick={handleDelete}
disabled={isDeleting} // isUpdatingが考慮されていない
className="text-red-600 hover:text-red-800 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
title="削除"
>
{isDeleting ? '削除中...' : '🗑️'}
</button>
```

**問題点**:
- TODOの完了状態を更新中(`isUpdating === true`)でも削除ボタンが有効になっている
- 更新処理と削除処理が同時に実行される可能性があり、データの整合性が損なわれる可能性がある
- ユーザー体験が悪化する(更新中に誤って削除してしまう可能性)

**影響範囲**:
- フロントエンドのUI動作
- データ整合性への潜在的な影響

**期待される修正**:
```tsx
disabled={isDeleting || isUpdating}
```

---

### 難易度2: データバリデーション不備

**ファイル**: `app/api/todos/route.ts`
**行番号**: 34-38行目

**バグ内容**:
`description`が空文字列の場合、`null`に変換されずにそのまま空文字列がデータベースに保存される。

**問題コード**:
```typescript
const todo = await prisma.todo.create({
data: {
title: validatedData.title,
description: validatedData.description, // 空文字列がそのまま保存される
},
})
```

**問題点**:
- zodスキーマで`description``optional()`のため、空文字列がバリデーションを通過してしまう
- データベースに空文字列が保存され、`null`と空文字列が混在する可能性がある
- データの一貫性が損なわれる
- フロントエンドで`todo.description && ...`のような条件分岐が正しく動作しない可能性がある

**影響範囲**:
- データベースのデータ整合性
- フロントエンドの表示ロジック

**期待される修正**:
```typescript
description: validatedData.description || null,
```
または
```typescript
description: validatedData.description?.trim() || null,
```

---

### 難易度3: React Hooksの依存配列問題

**ファイル**: `components/TodoList.tsx`
**行番号**: 39-41行目

**バグ内容**:
`useEffect`の依存配列に`fetchTodos`が含まれているが、`fetchTodos`が毎回新しい関数として作成されるため、無限ループが発生する可能性がある。

**問題コード**:
```tsx
const fetchTodos = async () => {
// ...
}

useEffect(() => {
fetchTodos()
}, [fetchTodos]) // fetchTodosが毎回新しい関数として作成される
```

**問題点**:
- `fetchTodos`がコンポーネント内で定義されているため、レンダリングごとに新しい関数インスタンスが作成される
- `useEffect`の依存配列に`fetchTodos`を含めると、毎回依存が変化したと判断され、無限ループが発生する
- 不要なAPIリクエストが大量に発生し、パフォーマンスが低下する
- サーバーに負荷がかかる

**影響範囲**:
- フロントエンドのパフォーマンス
- サーバーへの負荷
- ユーザー体験(画面がフリーズする可能性)

**期待される修正**:
```tsx
useEffect(() => {
fetchTodos()
}, []) // 依存配列を空にする
```
または
```tsx
const fetchTodos = useCallback(async () => {
// ...
}, [])

useEffect(() => {
fetchTodos()
}, [fetchTodos])
```

---

### 難易度4: セキュリティ/データ整合性問題

**ファイル**: `app/api/todos/[id]/route.ts`
**行番号**: 16-20行目(GET, PATCH, DELETEすべて)

**バグ内容**:
IDの形式検証が行われておらず、不正なID形式(SQLインジェクションや不正な文字列)が送られても検証されない。

**問題コード**:
```typescript
try {
const { id } = await params
const todo = await prisma.todo.findUnique({
where: { id }, // IDの形式検証がない
})
// ...
}
```

**問題点**:
- PrismaはSQLインジェクションを防いでいるが、不正なID形式(例: 非常に長い文字列、特殊文字を含む文字列)が送られても検証されない
- 不正なIDでリクエストが送られた場合、適切なエラーメッセージが返されない可能性がある
- データベースへの不要なクエリが発生する可能性がある
- エラーハンドリングが不十分

**影響範囲**:
- セキュリティ(軽微)
- エラーハンドリング
- パフォーマンス(不要なクエリ)

**期待される修正**:
```typescript
// cuid形式の検証を追加
const isValidCuid = (id: string): boolean => {
return /^c[a-z0-9]{24}$/.test(id)
}

try {
const { id } = await params
if (!isValidCuid(id)) {
return NextResponse.json(
{ error: '不正なID形式です' },
{ status: 400 }
)
}
// ...
}
```

---

### 難易度5: 本番環境での接続管理問題

**ファイル**: `lib/prisma.ts`
**行番号**: 7-13行目

**バグ内容**:
本番環境でもPrismaクライアントをグローバルに保存しないため、リクエストごとに新しい`PrismaClient`インスタンスが作成される可能性がある。

**問題コード**:
```typescript
export const prisma = globalForPrisma.prisma ?? new PrismaClient({
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
})

if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma
}
```

**問題点**:
- 本番環境では`globalForPrisma.prisma`が保存されないため、Next.jsのサーバーレス環境ではリクエストごとに新しい`PrismaClient`インスタンスが作成される可能性がある
- 接続プールが適切に管理されず、データベース接続が枯渇する可能性がある
- メモリリークやパフォーマンス低下の原因になる
- 本番環境でのスケーラビリティに影響する

**影響範囲**:
- 本番環境のパフォーマンス
- データベース接続管理
- スケーラビリティ
- メモリ使用量

**期待される修正**:
```typescript
export const prisma = globalForPrisma.prisma ?? new PrismaClient({
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
})

// 本番環境でもグローバルに保存
globalForPrisma.prisma = prisma
```

---

## 採点基準(参考)

### 難易度1(初級)
- コードレビューで簡単に発見できる
- UIの動作を確認すれば発見できる
- 初心者でも発見可能

### 難易度2(初中級)
- データフローの理解が必要
- バリデーションロジックの確認が必要
- 中級者レベル

### 難易度3(中級)
- React Hooksの理解が必要
- 無限ループの原因を理解する必要がある
- 実際に動作を確認しないと発見が難しい場合がある

### 難易度4(上級)
- セキュリティ意識が必要
- エラーハンドリングの観点が必要
- 実装経験が3年以上のエンジニアが発見可能

### 難易度5(最上級)
- 本番環境での動作を理解する必要がある
- Next.jsのサーバーレス環境の理解が必要
- Prismaの接続管理の深い理解が必要
- 実装経験が5年以上のエンジニアが発見可能

---

## 注意事項

- これらのバグは意図的に仕込まれたものです
- 実際のプロダクションコードでは、このようなバグを避けるためにコードレビューやテストを実施してください
- 採点時は、バグの発見数だけでなく、バグの重要度や影響範囲も考慮してください

0 comments on commit 88267db

Please sign in to comment.