create-ai-project 1.11.2 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/.claude/agents/acceptance-test-generator.md +179 -245
  2. package/.claude/agents/code-reviewer.md +3 -9
  3. package/.claude/agents/design-sync.md +221 -0
  4. package/.claude/agents/document-reviewer.md +15 -10
  5. package/.claude/agents/integration-test-reviewer.md +192 -0
  6. package/.claude/agents/prd-creator.md +10 -6
  7. package/.claude/agents/quality-fixer-frontend.md +324 -0
  8. package/.claude/agents/quality-fixer.md +48 -62
  9. package/.claude/agents/requirement-analyzer.md +8 -8
  10. package/.claude/agents/rule-advisor.md +84 -103
  11. package/.claude/agents/task-decomposer.md +21 -27
  12. package/.claude/agents/task-executor-frontend.md +264 -0
  13. package/.claude/agents/task-executor.md +4 -16
  14. package/.claude/agents/technical-designer-frontend.md +444 -0
  15. package/.claude/agents/technical-designer.md +52 -27
  16. package/.claude/agents/work-planner.md +41 -14
  17. package/.claude/agents-en/acceptance-test-generator.md +13 -13
  18. package/.claude/agents-en/code-reviewer.md +8 -10
  19. package/.claude/agents-en/design-sync.md +6 -5
  20. package/.claude/agents-en/document-reviewer.md +8 -7
  21. package/.claude/agents-en/integration-test-reviewer.md +5 -4
  22. package/.claude/agents-en/prd-creator.md +7 -6
  23. package/.claude/agents-en/quality-fixer-frontend.md +3 -14
  24. package/.claude/agents-en/quality-fixer.md +9 -20
  25. package/.claude/agents-en/requirement-analyzer.md +8 -7
  26. package/.claude/agents-en/rule-advisor.md +57 -128
  27. package/.claude/agents-en/task-decomposer.md +4 -10
  28. package/.claude/agents-en/task-executor-frontend.md +4 -16
  29. package/.claude/agents-en/task-executor.md +5 -16
  30. package/.claude/agents-en/technical-designer-frontend.md +17 -15
  31. package/.claude/agents-en/technical-designer.md +13 -15
  32. package/.claude/agents-en/work-planner.md +9 -14
  33. package/.claude/agents-ja/acceptance-test-generator.md +9 -15
  34. package/.claude/agents-ja/code-reviewer.md +3 -11
  35. package/.claude/agents-ja/design-sync.md +2 -6
  36. package/.claude/agents-ja/document-reviewer.md +4 -9
  37. package/.claude/agents-ja/integration-test-reviewer.md +2 -5
  38. package/.claude/agents-ja/prd-creator.md +3 -7
  39. package/.claude/agents-ja/quality-fixer-frontend.md +2 -13
  40. package/.claude/agents-ja/quality-fixer.md +7 -18
  41. package/.claude/agents-ja/requirement-analyzer.md +5 -8
  42. package/.claude/agents-ja/rule-advisor.md +57 -128
  43. package/.claude/agents-ja/task-decomposer.md +4 -10
  44. package/.claude/agents-ja/task-executor-frontend.md +3 -15
  45. package/.claude/agents-ja/task-executor.md +3 -17
  46. package/.claude/agents-ja/technical-designer-frontend.md +17 -15
  47. package/.claude/agents-ja/technical-designer.md +13 -15
  48. package/.claude/agents-ja/work-planner.md +9 -14
  49. package/.claude/commands/build.md +7 -10
  50. package/.claude/commands/design.md +15 -5
  51. package/.claude/commands/front-build.md +103 -0
  52. package/.claude/commands/front-design.md +42 -0
  53. package/.claude/commands/front-plan.md +40 -0
  54. package/.claude/commands/implement.md +23 -29
  55. package/.claude/commands/plan.md +4 -4
  56. package/.claude/commands/project-inject.md +4 -4
  57. package/.claude/{commands-ja/refine-rule.md → commands/refine-skill.md} +25 -25
  58. package/.claude/{commands-ja/sync-rules.md → commands/sync-skills.md} +28 -28
  59. package/.claude/commands/task.md +1 -1
  60. package/.claude/commands-en/build.md +2 -2
  61. package/.claude/commands-en/design.md +1 -1
  62. package/.claude/commands-en/implement.md +8 -8
  63. package/.claude/commands-en/plan.md +3 -3
  64. package/.claude/commands-en/project-inject.md +4 -4
  65. package/.claude/commands-en/{refine-rule.md → refine-skill.md} +47 -48
  66. package/.claude/commands-en/{sync-rules.md → sync-skills.md} +29 -29
  67. package/.claude/commands-ja/build.md +2 -2
  68. package/.claude/commands-ja/design.md +1 -1
  69. package/.claude/commands-ja/implement.md +8 -8
  70. package/.claude/commands-ja/plan.md +3 -3
  71. package/.claude/commands-ja/project-inject.md +4 -4
  72. package/.claude/{commands/refine-rule.md → commands-ja/refine-skill.md} +25 -25
  73. package/.claude/{commands/sync-rules.md → commands-ja/sync-skills.md} +28 -28
  74. package/.claude/settings.local.json +21 -1
  75. package/{docs/rules/ai-development-guide.md → .claude/skills/coding-standards/SKILL.md} +94 -108
  76. package/{docs/rules/documentation-criteria.md → .claude/skills/documentation-criteria/SKILL.md} +19 -6
  77. package/.claude/skills/documentation-criteria/references/adr-template.md +64 -0
  78. package/.claude/skills/documentation-criteria/references/design-template.md +242 -0
  79. package/.claude/skills/documentation-criteria/references/plan-template.md +130 -0
  80. package/.claude/skills/documentation-criteria/references/prd-template.md +109 -0
  81. package/.claude/skills/frontend/technical-spec/SKILL.md +147 -0
  82. package/.claude/skills/frontend/typescript-rules/SKILL.md +315 -0
  83. package/.claude/skills/frontend/typescript-testing/SKILL.md +212 -0
  84. package/{docs/rules-ja/architecture/implementation-approach.md → .claude/skills/implementation-approach/SKILL.md} +10 -5
  85. package/.claude/skills/integration-e2e-testing/SKILL.md +146 -0
  86. package/{docs/rules-ja/project-context.md → .claude/skills/project-context/SKILL.md} +7 -3
  87. package/.claude/skills/subagents-orchestration-guide/SKILL.md +212 -0
  88. package/.claude/skills/task-analyzer/SKILL.md +142 -0
  89. package/.claude/skills/task-analyzer/references/skills-index.yaml +211 -0
  90. package/.claude/skills/technical-spec/SKILL.md +86 -0
  91. package/{docs/rules/typescript.md → .claude/skills/typescript-rules/SKILL.md} +22 -67
  92. package/.claude/skills/typescript-testing/SKILL.md +155 -0
  93. package/{docs/rules-en/coding-standards.md → .claude/skills-en/coding-standards/SKILL.md} +21 -108
  94. package/{docs/rules-en/documentation-criteria.md → .claude/skills-en/documentation-criteria/SKILL.md} +40 -42
  95. package/{docs/adr/template-en.md → .claude/skills-en/documentation-criteria/references/adr-template.md} +1 -1
  96. package/{docs/design/template-en.md → .claude/skills-en/documentation-criteria/references/design-template.md} +11 -31
  97. package/{docs/plans/template-en.md → .claude/skills-en/documentation-criteria/references/plan-template.md} +4 -4
  98. package/{docs/prd/template-en.md → .claude/skills-en/documentation-criteria/references/prd-template.md} +1 -1
  99. package/{docs/rules-en/frontend/technical-spec.md → .claude/skills-en/frontend/technical-spec/SKILL.md} +17 -13
  100. package/{docs/rules-en/frontend/typescript.md → .claude/skills-en/frontend/typescript-rules/SKILL.md} +17 -12
  101. package/{docs/rules-en/frontend/typescript-testing.md → .claude/skills-en/frontend/typescript-testing/SKILL.md} +11 -6
  102. package/{docs/rules-en/architecture/implementation-approach.md → .claude/skills-en/implementation-approach/SKILL.md} +7 -2
  103. package/{docs/rules-en/integration-e2e-testing.md → .claude/skills-en/integration-e2e-testing/SKILL.md} +15 -18
  104. package/{docs/rules-en/project-context.md → .claude/skills-en/project-context/SKILL.md} +7 -3
  105. package/.claude/skills-en/subagents-orchestration-guide/SKILL.md +224 -0
  106. package/.claude/skills-en/task-analyzer/SKILL.md +131 -0
  107. package/{docs/rules-en/rules-index.yaml → .claude/skills-en/task-analyzer/references/skills-index.yaml} +34 -20
  108. package/{docs/rules-en/technical-spec.md → .claude/skills-en/technical-spec/SKILL.md} +6 -6
  109. package/{docs/rules-en/typescript.md → .claude/skills-en/typescript-rules/SKILL.md} +15 -10
  110. package/{docs/rules-en/typescript-testing.md → .claude/skills-en/typescript-testing/SKILL.md} +10 -4
  111. package/{docs/rules-ja/coding-standards.md → .claude/skills-ja/coding-standards/SKILL.md} +12 -99
  112. package/{docs/rules-ja/documentation-criteria.md → .claude/skills-ja/documentation-criteria/SKILL.md} +18 -5
  113. package/.claude/skills-ja/documentation-criteria/references/adr-template.md +64 -0
  114. package/.claude/skills-ja/documentation-criteria/references/design-template.md +261 -0
  115. package/{docs/plans/template-ja.md → .claude/skills-ja/documentation-criteria/references/plan-template.md} +38 -38
  116. package/{docs/prd/template-ja.md → .claude/skills-ja/documentation-criteria/references/prd-template.md} +33 -33
  117. package/{docs/rules-ja/frontend/technical-spec.md → .claude/skills-ja/frontend/technical-spec/SKILL.md} +13 -9
  118. package/.claude/skills-ja/frontend/typescript-rules/SKILL.md +315 -0
  119. package/{docs/rules-ja/frontend/typescript-testing.md → .claude/skills-ja/frontend/typescript-testing/SKILL.md} +93 -5
  120. package/{docs/rules/architecture/implementation-approach.md → .claude/skills-ja/implementation-approach/SKILL.md} +10 -5
  121. package/{docs/rules-ja/integration-e2e-testing.md → .claude/skills-ja/integration-e2e-testing/SKILL.md} +5 -8
  122. package/{docs/rules/project-context.md → .claude/skills-ja/project-context/SKILL.md} +7 -3
  123. package/.claude/skills-ja/subagents-orchestration-guide/SKILL.md +212 -0
  124. package/.claude/skills-ja/task-analyzer/SKILL.md +131 -0
  125. package/{docs/rules-ja/rules-index.yaml → .claude/skills-ja/task-analyzer/references/skills-index.yaml} +34 -19
  126. package/{docs/rules-ja/technical-spec.md → .claude/skills-ja/technical-spec/SKILL.md} +6 -6
  127. package/{docs/rules-ja/typescript.md → .claude/skills-ja/typescript-rules/SKILL.md} +16 -11
  128. package/{docs/rules-ja/typescript-testing.md → .claude/skills-ja/typescript-testing/SKILL.md} +11 -5
  129. package/CLAUDE.en.md +6 -6
  130. package/CLAUDE.ja.md +6 -6
  131. package/CLAUDE.md +19 -28
  132. package/README.ja.md +39 -10
  133. package/README.md +39 -10
  134. package/package.json +1 -1
  135. package/scripts/set-language.js +35 -53
  136. package/scripts/setup-project.js +4 -1
  137. package/docs/adr/template-ja.md +0 -64
  138. package/docs/design/template-ja.md +0 -285
  139. package/docs/guides/en/sub-agents.md +0 -343
  140. package/docs/guides/ja/sub-agents.md +0 -343
  141. package/docs/guides/sub-agents.md +0 -306
  142. package/docs/plans/20250123-integration-test-improvement.md +0 -993
  143. package/docs/rules/rules-index.yaml +0 -137
  144. package/docs/rules/technical-spec.md +0 -47
  145. package/docs/rules/typescript-testing.md +0 -188
  146. package/docs/rules-ja/frontend/typescript.md +0 -131
@@ -0,0 +1,315 @@
1
+ ---
2
+ name: frontend/typescript-rules
3
+ description: 型安全性、コンポーネント設計、状態管理、エラーハンドリングを含むReact/TypeScriptフロントエンド開発ルール。
4
+ ---
5
+
6
+ # TypeScript 開発ルール(フロントエンド)
7
+
8
+ ## 型システム
9
+
10
+ ### 型安全性の原則
11
+ - **strictモード必須**: tsconfig.jsonでstrict: trueを設定
12
+ - **any型使用禁止**: コードベースでany型を使用しない
13
+ - **as使用最小化**: 型キャストはやむを得ない場合のみ(理由をコメント)
14
+ - **unknown優先**: any型が必要な場合はunknown + 型ガード
15
+
16
+ ```typescript
17
+ // 良い: 型ガード付きのunknown
18
+ function processData(data: unknown): User {
19
+ if (!isUser(data)) throw new Error('Invalid user data')
20
+ return data
21
+ }
22
+
23
+ // 悪い: any型の使用
24
+ function processData(data: any): User {
25
+ return data as User
26
+ }
27
+ ```
28
+
29
+ ### 型定義のベストプラクティス
30
+
31
+ #### オブジェクト型
32
+ - **interface優先**: 拡張可能なオブジェクト型にはinterfaceを使用
33
+ - **typeはunion/intersection用**: 複合型やユーティリティ型に使用
34
+ - **readonlyの活用**: 不変なプロパティにはreadonlyを明示
35
+
36
+ ```typescript
37
+ // 良い: 明確な型定義
38
+ interface User {
39
+ readonly id: string
40
+ name: string
41
+ email: string
42
+ }
43
+
44
+ type UserWithRole = User & { role: 'admin' | 'user' }
45
+ ```
46
+
47
+ #### 関数型
48
+ - **戻り値型を明示**: 複雑なロジックを持つ関数
49
+ - **ジェネリクスの活用**: 再利用可能な型安全な関数
50
+
51
+ ```typescript
52
+ // 良い: 戻り値型を明示
53
+ function calculateTotal(items: CartItem[]): number {
54
+ return items.reduce((sum, item) => sum + item.price, 0)
55
+ }
56
+
57
+ // 良い: ジェネリクスの活用
58
+ function pick<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> {
59
+ // implementation
60
+ }
61
+ ```
62
+
63
+ ## Reactコンポーネント設計
64
+
65
+ ### Function Components必須
66
+
67
+ ```typescript
68
+ // 良い: Function Component
69
+ const UserCard: React.FC<UserCardProps> = ({ user, onSelect }) => {
70
+ return (
71
+ <div onClick={() => onSelect(user.id)}>
72
+ {user.name}
73
+ </div>
74
+ )
75
+ }
76
+
77
+ // 悪い: Class Component(非推奨)
78
+ class UserCard extends React.Component<UserCardProps> { }
79
+ ```
80
+
81
+ ### Props型定義
82
+
83
+ ```typescript
84
+ interface ButtonProps {
85
+ label: string
86
+ onClick: () => void
87
+ variant?: 'primary' | 'secondary'
88
+ disabled?: boolean
89
+ }
90
+
91
+ const Button: React.FC<ButtonProps> = ({
92
+ label,
93
+ onClick,
94
+ variant = 'primary',
95
+ disabled = false
96
+ }) => {
97
+ // implementation
98
+ }
99
+ ```
100
+
101
+ ### Children Props
102
+
103
+ ```typescript
104
+ interface LayoutProps {
105
+ children: React.ReactNode
106
+ sidebar?: React.ReactNode
107
+ }
108
+
109
+ const Layout: React.FC<LayoutProps> = ({ children, sidebar }) => (
110
+ <div>
111
+ <main>{children}</main>
112
+ {sidebar && <aside>{sidebar}</aside>}
113
+ </div>
114
+ )
115
+ ```
116
+
117
+ ## 状態管理
118
+
119
+ ### useState型定義
120
+
121
+ ```typescript
122
+ // 良い: 明示的な型
123
+ const [user, setUser] = useState<User | null>(null)
124
+ const [items, setItems] = useState<Item[]>([])
125
+
126
+ // 良い: 初期値から推論可能な場合
127
+ const [count, setCount] = useState(0)
128
+ ```
129
+
130
+ ### useReducerの型安全性
131
+
132
+ ```typescript
133
+ type Action =
134
+ | { type: 'SET_USER'; payload: User }
135
+ | { type: 'CLEAR_USER' }
136
+ | { type: 'SET_ERROR'; payload: string }
137
+
138
+ interface State {
139
+ user: User | null
140
+ error: string | null
141
+ }
142
+
143
+ const reducer = (state: State, action: Action): State => {
144
+ switch (action.type) {
145
+ case 'SET_USER':
146
+ return { ...state, user: action.payload, error: null }
147
+ case 'CLEAR_USER':
148
+ return { ...state, user: null }
149
+ case 'SET_ERROR':
150
+ return { ...state, error: action.payload }
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Custom Hooks
156
+
157
+ ```typescript
158
+ interface UseUserReturn {
159
+ user: User | null
160
+ loading: boolean
161
+ error: Error | null
162
+ refetch: () => Promise<void>
163
+ }
164
+
165
+ function useUser(userId: string): UseUserReturn {
166
+ const [user, setUser] = useState<User | null>(null)
167
+ const [loading, setLoading] = useState(true)
168
+ const [error, setError] = useState<Error | null>(null)
169
+
170
+ const refetch = useCallback(async () => {
171
+ setLoading(true)
172
+ try {
173
+ const data = await fetchUser(userId)
174
+ setUser(data)
175
+ } catch (e) {
176
+ setError(e instanceof Error ? e : new Error('Unknown error'))
177
+ } finally {
178
+ setLoading(false)
179
+ }
180
+ }, [userId])
181
+
182
+ useEffect(() => { refetch() }, [refetch])
183
+
184
+ return { user, loading, error, refetch }
185
+ }
186
+ ```
187
+
188
+ ## エラーハンドリング
189
+
190
+ ### Error Boundary
191
+
192
+ ```typescript
193
+ interface ErrorBoundaryProps {
194
+ children: React.ReactNode
195
+ fallback: React.ReactNode
196
+ }
197
+
198
+ interface ErrorBoundaryState {
199
+ hasError: boolean
200
+ }
201
+
202
+ class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
203
+ state = { hasError: false }
204
+
205
+ static getDerivedStateFromError(): ErrorBoundaryState {
206
+ return { hasError: true }
207
+ }
208
+
209
+ render() {
210
+ if (this.state.hasError) return this.props.fallback
211
+ return this.props.children
212
+ }
213
+ }
214
+ ```
215
+
216
+ ### APIエラーハンドリング
217
+
218
+ ```typescript
219
+ interface ApiError {
220
+ code: string
221
+ message: string
222
+ details?: Record<string, string>
223
+ }
224
+
225
+ function isApiError(error: unknown): error is ApiError {
226
+ return (
227
+ typeof error === 'object' &&
228
+ error !== null &&
229
+ 'code' in error &&
230
+ 'message' in error
231
+ )
232
+ }
233
+
234
+ async function fetchWithErrorHandling<T>(url: string): Promise<T> {
235
+ const response = await fetch(url)
236
+
237
+ if (!response.ok) {
238
+ const error: unknown = await response.json()
239
+ if (isApiError(error)) {
240
+ throw new ApiError(error.code, error.message)
241
+ }
242
+ throw new Error('Unknown API error')
243
+ }
244
+
245
+ return response.json() as Promise<T>
246
+ }
247
+ ```
248
+
249
+ ## イベントハンドリング
250
+
251
+ ### イベント型
252
+
253
+ ```typescript
254
+ const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
255
+ e.preventDefault()
256
+ // handle click
257
+ }
258
+
259
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
260
+ const value = e.target.value
261
+ // handle change
262
+ }
263
+
264
+ const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
265
+ e.preventDefault()
266
+ // handle submit
267
+ }
268
+ ```
269
+
270
+ ## コーディング規約
271
+
272
+ ### 命名規則
273
+ - **コンポーネント**: PascalCase(例: `UserProfile`)
274
+ - **フック**: camelCase + use接頭辞(例: `useUserData`)
275
+ - **型/インターフェース**: PascalCase(例: `UserProps`)
276
+ - **定数**: SCREAMING_SNAKE_CASE(例: `MAX_RETRY_COUNT`)
277
+ - **ファイル名**: コンポーネントはPascalCase、その他はcamelCase
278
+
279
+ ### インポート順序
280
+ 1. React関連
281
+ 2. 外部ライブラリ
282
+ 3. 内部モジュール(絶対パス)
283
+ 4. 内部モジュール(相対パス)
284
+ 5. 型のみのインポート
285
+ 6. スタイル/アセット
286
+
287
+ ```typescript
288
+ import { useState, useEffect } from 'react'
289
+ import { useQuery } from '@tanstack/react-query'
290
+ import { api } from '@/lib/api'
291
+ import { formatDate } from '../utils'
292
+ import type { User } from '@/types'
293
+ import styles from './Component.module.css'
294
+ ```
295
+
296
+ ## アンチパターン
297
+
298
+ ### 避けるべきパターン
299
+
300
+ ```typescript
301
+ // 悪い: Propsのスプレッド展開
302
+ const Button = (props: ButtonProps) => <button {...props} />
303
+
304
+ // 良い: 明示的なPropsの受け渡し
305
+ const Button = ({ label, onClick, disabled }: ButtonProps) => (
306
+ <button onClick={onClick} disabled={disabled}>{label}</button>
307
+ )
308
+
309
+ // 悪い: インラインでの複雑なロジック
310
+ {items.filter(i => i.active).map(i => <Item key={i.id} {...i} />)}
311
+
312
+ // 良い: 事前に変数として抽出
313
+ const activeItems = items.filter(item => item.active)
314
+ {activeItems.map(item => <Item key={item.id} item={item} />)}
315
+ ```
@@ -0,0 +1,212 @@
1
+ ---
2
+ name: frontend/typescript-testing
3
+ description: Vitest、React Testing Library、MSWを使用したフロントエンドテストルール。カバレッジ要件、テスト設計原則、品質基準を含む。
4
+ ---
5
+
6
+ # TypeScript テストルール(フロントエンド)
7
+
8
+ ## テストフレームワーク
9
+ - **Vitest**: このプロジェクトではVitestを使用
10
+ - **React Testing Library**: コンポーネントテスト用
11
+ - **MSW (Mock Service Worker)**: APIモック用
12
+ - テストのインポート: `import { describe, it, expect, beforeEach, vi } from 'vitest'`
13
+ - コンポーネントテストのインポート: `import { render, screen, fireEvent } from '@testing-library/react'`
14
+ - モックの作成: `vi.mock()` を使用
15
+
16
+ ## テストの基本方針
17
+
18
+ ### 品質要件
19
+ - **カバレッジ**: 単体テストのカバレッジは60%以上を必須(フロントエンド標準 2025)
20
+ - **独立性**: 各テストは他のテストに依存せず実行可能
21
+ - **再現性**: テストは環境に依存せず、常に同じ結果を返す
22
+ - **可読性**: テストコードも製品コードと同様の品質を維持
23
+
24
+ ### カバレッジ要件
25
+ **必須**: 単体テストのカバレッジは60%以上
26
+ **コンポーネント別目標**:
27
+ - Atoms(Button、Text等): 70%以上
28
+ - Molecules(FormField等): 65%以上
29
+ - Organisms(Header、Footer等): 60%以上
30
+ - Custom Hooks: 65%以上
31
+ - Utils: 70%以上
32
+
33
+ **指標**: Statements(文)、Branches(分岐)、Functions(関数)、Lines(行)
34
+
35
+ ### テストの種類と範囲
36
+ 1. **単体テスト(React Testing Library)**
37
+ - 個々のコンポーネントや関数の動作を検証
38
+ - 外部依存はすべてモック化
39
+ - 最も数が多く、細かい粒度で実施
40
+ - ユーザーから観測可能な振る舞いに焦点を当てる
41
+
42
+ 2. **統合テスト(React Testing Library + MSW)**
43
+ - 複数のコンポーネントの連携を検証
44
+ - MSW(Mock Service Worker)でAPIをモック
45
+ - 実際のDB接続なし(DBはバックエンドが管理)
46
+ - 主要な機能フローの検証
47
+
48
+ 3. **E2Eテストでの機能横断検証**
49
+ - 新機能追加時、既存機能への影響を必ず検証
50
+ - Design Docの「統合ポイントマップ」で影響度「高」「中」の箇所をカバー
51
+ - 検証パターン: 既存機能動作 → 新機能有効化 → 既存機能の継続性確認
52
+ - 判定基準: 表示内容の変化なし、レンダリング時間5秒以内
53
+ - CI/CDでの自動実行を前提とした設計
54
+
55
+ ## テストの実装規約
56
+
57
+ ### ディレクトリ構造(Co-location原則)
58
+ ```
59
+ src/
60
+ └── components/
61
+ └── Button/
62
+ ├── Button.tsx
63
+ ├── Button.test.tsx # コンポーネントと同じ場所に配置
64
+ └── index.ts
65
+ ```
66
+
67
+ **理由**:
68
+ - React Testing Libraryのベストプラクティス
69
+ - ADR-0002 Co-location原則
70
+ - 実装と一緒にテストを見つけやすく、保守しやすい
71
+
72
+ ### 命名規則
73
+ - テストファイル: `{ComponentName}.test.tsx`
74
+ - 統合テストファイル: `{FeatureName}.integration.test.tsx`
75
+ - テストスイート: 対象のコンポーネントや機能を説明する名前
76
+ - テストケース: ユーザー視点から期待される動作を説明する名前
77
+
78
+ ### テストコードの品質ルール
79
+
80
+ **推奨: すべてのテストを常に有効に保つ**
81
+ - メリット: テストスイートの完全性を保証
82
+ - 実践: 問題があるテストは修正して有効化
83
+
84
+ **避けるべき: test.skip()やコメントアウト**
85
+ - 理由: テストの穴が生まれ、品質チェックが不完全になる
86
+ - 対処: 不要なテストは完全に削除する
87
+
88
+ ## モックの型安全性の徹底
89
+
90
+ ### MSW(Mock Service Worker)セットアップ
91
+ ```typescript
92
+ // 型安全なMSWハンドラー
93
+ import { rest } from 'msw'
94
+
95
+ const handlers = [
96
+ rest.get('/api/users/:id', (req, res, ctx) => {
97
+ return res(ctx.json({ id: '1', name: 'John' } satisfies User))
98
+ })
99
+ ]
100
+ ```
101
+
102
+ ### コンポーネントモックの型安全性
103
+ ```typescript
104
+ // 必要な部分のみ
105
+ type TestProps = Pick<ButtonProps, 'label' | 'onClick'>
106
+ const mockProps: TestProps = { label: 'Click', onClick: vi.fn() }
107
+
108
+ // やむを得ない場合のみ、理由明記
109
+ const mockRouter = {
110
+ push: vi.fn()
111
+ } as unknown as Router // 複雑なRouter型構造のため
112
+ ```
113
+
114
+ ## React Testing Libraryの基本例
115
+
116
+ ```typescript
117
+ import { describe, it, expect, vi } from 'vitest'
118
+ import { render, screen, fireEvent } from '@testing-library/react'
119
+ import { Button } from './Button'
120
+
121
+ describe('Button', () => {
122
+ it('should call onClick when clicked', () => {
123
+ const onClick = vi.fn()
124
+ render(<Button label="Click me" onClick={onClick} />)
125
+ fireEvent.click(screen.getByRole('button', { name: 'Click me' }))
126
+ expect(onClick).toHaveBeenCalledOnce()
127
+ })
128
+ })
129
+ ```
130
+
131
+ ## テスト品質基準
132
+
133
+ ### 境界値・異常系の網羅
134
+ 正常系に加え、境界値と異常系を含める。
135
+ ```typescript
136
+ it('renders empty state for empty array', () => {
137
+ render(<UserList users={[]} />)
138
+ expect(screen.getByText('ユーザーがいません')).toBeInTheDocument()
139
+ })
140
+
141
+ it('displays error message on API failure', async () => {
142
+ server.use(rest.get('/api/users', (req, res, ctx) => res(ctx.status(500))))
143
+ render(<UserList />)
144
+ expect(await screen.findByText('エラーが発生しました')).toBeInTheDocument()
145
+ })
146
+ ```
147
+
148
+ ### ユーザー中心のクエリ
149
+
150
+ ```typescript
151
+ // 良い: アクセシブルなクエリ
152
+ screen.getByRole('button', { name: 'Submit' })
153
+ screen.getByLabelText('Email')
154
+ screen.getByText('Welcome')
155
+
156
+ // 悪い: 実装詳細への依存
157
+ screen.getByTestId('submit-btn')
158
+ container.querySelector('.btn-primary')
159
+ ```
160
+
161
+ ### 非同期処理のテスト
162
+
163
+ ```typescript
164
+ it('loads and displays user data', async () => {
165
+ render(<UserProfile userId="1" />)
166
+
167
+ // ローディング状態を確認
168
+ expect(screen.getByText('Loading...')).toBeInTheDocument()
169
+
170
+ // データ表示を待機
171
+ expect(await screen.findByText('John Doe')).toBeInTheDocument()
172
+
173
+ // ローディングが消えていることを確認
174
+ expect(screen.queryByText('Loading...')).not.toBeInTheDocument()
175
+ })
176
+ ```
177
+
178
+ ### フォームテスト
179
+
180
+ ```typescript
181
+ it('submits form with valid data', async () => {
182
+ const onSubmit = vi.fn()
183
+ render(<LoginForm onSubmit={onSubmit} />)
184
+
185
+ await userEvent.type(screen.getByLabelText('Email'), 'test@example.com')
186
+ await userEvent.type(screen.getByLabelText('Password'), 'password123')
187
+ await userEvent.click(screen.getByRole('button', { name: 'Login' }))
188
+
189
+ expect(onSubmit).toHaveBeenCalledWith({
190
+ email: 'test@example.com',
191
+ password: 'password123'
192
+ })
193
+ })
194
+ ```
195
+
196
+ ## アンチパターン
197
+
198
+ ```typescript
199
+ // 悪い: 実装詳細のテスト
200
+ it('calls setState', () => {
201
+ const setState = vi.spyOn(React, 'useState')
202
+ render(<Counter />)
203
+ // ...
204
+ })
205
+
206
+ // 良い: ユーザーが見る結果をテスト
207
+ it('increments count when clicked', () => {
208
+ render(<Counter />)
209
+ fireEvent.click(screen.getByRole('button', { name: '+' }))
210
+ expect(screen.getByText('Count: 1')).toBeInTheDocument()
211
+ })
212
+ ```
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: implementation-approach
3
+ description: メタ認知的アプローチによる実装戦略選択フレームワーク。確認レベル、統合ポイント定義を含む。
4
+ ---
5
+
1
6
  # 実装戦略選択フレームワーク(メタ認知的アプローチ)
2
7
 
3
8
  ## メタ認知的戦略選択プロセス
@@ -86,7 +91,7 @@
86
91
  **適用条件**: 機能間の依存が少ない、ユーザーが利用可能な形で出力、アーキテクチャ全層への変更が必要
87
92
  **確認方法**: 各機能完成時のエンドユーザー価値提供
88
93
 
89
- #### 水平スライス(基盤駆動)
94
+ #### 水平スライス(基盤駆動)
90
95
  **特徴**: アーキテクチャ層別の段階的構築
91
96
  **適用条件**: 基盤システムの安定性が重要、複数機能が共通基盤に依存、層別の段階的確認が有効
92
97
  **確認方法**: 全基盤層完成時の統合動作確認
@@ -105,7 +110,7 @@
105
110
  各タスクの完了確認における優先順位:
106
111
 
107
112
  - **L1: 機能動作確認** - エンドユーザー機能として動作(例:検索実行可能)
108
- - **L2: テスト動作確認** - 新規テストが追加されパス(例:型定義テスト)
113
+ - **L2: テスト動作確認** - 新規テストが追加されパス(例:型定義テスト)
109
114
  - **L3: ビルド成功確認** - コンパイルエラーなし(例:インターフェース定義)
110
115
 
111
116
  **優先順位**: L1 > L2 > L3 の順で確認可能性を重視
@@ -121,7 +126,7 @@
121
126
  ## アンチパターン
122
127
 
123
128
  - **パターン固執**: リスト内の戦略のみで選択し、独自の組み合わせを検討しない
124
- - **分析不足**: Phase 1の分析フレームワークを飛ばして戦略選択
129
+ - **分析不足**: Phase 1の分析フレームワークを飛ばして戦略選択
125
130
  - **リスク軽視**: Phase 3のリスク分析マトリクスを省略して実装着手
126
131
  - **制約無視**: Phase 4の制約チェックリストを確認せず戦略決定
127
132
  - **根拠省略**: Phase 6の文書化テンプレートを使用せず戦略選択
@@ -129,8 +134,8 @@
129
134
  ## メタ認知的実行のための指針
130
135
 
131
136
  1. **既知パターンの活用**: 出発点として参考し、創造的組み合わせを探索
132
- 2. **WebSearch積極活用**: 同種技術スタックの実装事例を調査
137
+ 2. **WebSearch積極活用**: 同種技術スタックの実装事例を調査
133
138
  3. **5 Whys適用**: 根本理由を追求し本質を把握
134
139
  4. **複数観点評価**: Phase 1-4の各観点から網羅的に評価
135
140
  5. **創造的思考**: 複数戦略の順序適用やプロジェクト固有の制約を活かした設計を検討
136
- 6. **判断根拠明示**: 設計ドキュメントでの戦略選択根拠を明示化
141
+ 6. **判断根拠明示**: 設計ドキュメントでの戦略選択根拠を明示化