@hd-agent-kit/cli 1.0.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.
@@ -0,0 +1,319 @@
1
+ # /security-scan — Güvenlik Tarama Skill'i
2
+
3
+ > **Tetikleyici:** `/security-scan`
4
+ > **Amaç:** Dependency audit, XSS/CSRF risk tespiti, env variable kontrolü ve güvenlik best practice'lerine uyum raporu oluşturmak.
5
+ > **Çıktı:** Kategorize edilmiş güvenlik raporu + düzeltme önerileri
6
+
7
+ ---
8
+
9
+ ## Temel İlkeler
10
+
11
+ - **Defense in depth.** Tek bir güvenlik katmanına güvenme; çok katmanlı savunma kur.
12
+ - **Principle of least privilege.** Her modül/kullanıcı sadece gereken minimum yetkiye sahip olsun.
13
+ - **Fail secure.** Hata durumunda güvenli tarafa düş (erişimi kapat, default deny).
14
+ - **Input'a asla güvenme.** Tüm kullanıcı girdilerini her zaman doğrula ve sanitize et.
15
+
16
+ ---
17
+
18
+ ## Kullanım Formatları
19
+
20
+ ```
21
+ /security-scan ← Tüm proje taraması
22
+ /security-scan src/services/auth.ts ← Belirli dosya taraması
23
+ /security-scan dependencies ← Sadece dependency audit
24
+ /security-scan env ← Sadece env variable kontrolü
25
+ /security-scan auth ← Auth katmanı güvenlik kontrolü
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Tarama Kategorileri
31
+
32
+ ### Kategori 1: Dependency Güvenliği
33
+
34
+ ```
35
+ 📦 Dependency Audit:
36
+
37
+ 1. Bilinen Güvenlik Açıkları:
38
+ ├── npm audit / pnpm audit sonucu:
39
+ │ ├── Critical: [N adet]
40
+ │ ├── High: [N adet]
41
+ │ ├── Moderate: [N adet]
42
+ │ └── Low: [N adet]
43
+ ├── Etkilenen paketler:
44
+ │ ├── [paket@versiyon] → [CVE-XXXX-XXXX] — [açıklama] — Fix: [güncel versiyon]
45
+ │ └── ...
46
+ └── Transitive dependency riskleri: [dolaylı bağımlılıklardaki açıklar]
47
+
48
+ 2. Eski/Bakımsız Dependency'ler:
49
+ ├── Son güncellemesi 1+ yıl: [liste]
50
+ ├── Deprecated paketler: [liste]
51
+ ├── Bilinen alternatifler: [mevcut → önerilen]
52
+ └── Önemsiz/gereksiz dependency'ler: [kaldırılabilecekler]
53
+
54
+ 3. License Kontrolü:
55
+ ├── Ticari kullanımda sorunlu lisanslar: [GPL, AGPL vs.]
56
+ ├── Lisans uyumsuzlukları: [var/yok]
57
+ └── Lisansı belirsiz paketler: [liste]
58
+
59
+ 4. Supply Chain Riskleri:
60
+ ├── Lockfile güncel mi? (package-lock.json / pnpm-lock.yaml)
61
+ ├── Exact versioning kullanılıyor mu?
62
+ ├── .npmrc güvenlik ayarları: [var/yok]
63
+ └── Typosquatting riski: [benzer isimli paketler]
64
+ ```
65
+
66
+ ### Kategori 2: XSS (Cross-Site Scripting) Taraması
67
+
68
+ ```
69
+ 🛡️ XSS Risk Analizi:
70
+
71
+ 1. dangerouslySetInnerHTML Kullanımı:
72
+ ├── Kullanım yerleri: [dosya:satır listesi]
73
+ ├── Sanitization: [DOMPurify kullanılıyor mu?]
74
+ ├── Kaynak güvenli mi: [kullanıcı girdisi mi, statik veri mi?]
75
+ └── Risk seviyesi: [Kritik/Yüksek/Orta/Düşük]
76
+
77
+ 2. URL İşleme:
78
+ ├── href'e kullanıcı girdisi aktarılıyor mu?
79
+ ├── javascript: protocol kontrolü: [var/yok]
80
+ ├── URL sanitization: [var/yok]
81
+ └── window.location manipülasyonu: [var/yok]
82
+
83
+ 3. DOM Manipülasyonu:
84
+ ├── innerHTML kullanımı: [var/yok]
85
+ ├── document.write kullanımı: [var/yok]
86
+ ├── eval() kullanımı: [var/yok]
87
+ ├── new Function() kullanımı: [var/yok]
88
+ └── template literal'da HTML: [var/yok]
89
+
90
+ 4. Üçüncü Parti Script'ler:
91
+ ├── Harici script tag'ları: [liste]
92
+ ├── SRI (Subresource Integrity): [var/yok]
93
+ ├── Sandbox attribute: [iframe'lerde var/yok]
94
+ └── Postmessage origin kontrolü: [var/yok]
95
+ ```
96
+
97
+ ### Kategori 3: CSRF & İstek Güvenliği
98
+
99
+ ```
100
+ 🔐 CSRF & Request Security:
101
+
102
+ 1. CSRF Koruması:
103
+ ├── CSRF token implementasyonu: [var/yok]
104
+ ├── SameSite cookie attribute: [var/yok, değeri]
105
+ ├── Custom header kontrolü: [var/yok]
106
+ └── State-changing GET request'ler: [var/yok — olmamalı]
107
+
108
+ 2. CORS Yapılandırması:
109
+ ├── Access-Control-Allow-Origin: [değer]
110
+ ├── Wildcard (*) kullanımı: [var/yok — riskli]
111
+ ├── Credentials ile CORS: [var/yok]
112
+ ├── Allowed methods: [liste]
113
+ └── Exposed headers: [liste]
114
+
115
+ 3. HTTP Güvenlik Header'ları:
116
+ ├── Content-Security-Policy: [var/yok, değer]
117
+ ├── X-Content-Type-Options: nosniff [var/yok]
118
+ ├── X-Frame-Options: [var/yok, değer]
119
+ ├── Strict-Transport-Security: [var/yok]
120
+ ├── Referrer-Policy: [var/yok, değer]
121
+ ├── Permissions-Policy: [var/yok]
122
+ └── X-XSS-Protection: [var/yok — modern tarayıcılarda gereksiz]
123
+ ```
124
+
125
+ ### Kategori 4: Authentication & Authorization
126
+
127
+ ```
128
+ 🔑 Auth Güvenliği:
129
+
130
+ 1. Token Yönetimi:
131
+ ├── Token storage: [localStorage / sessionStorage / httpOnly cookie]
132
+ ├── Token tipi: [JWT / opaque / session ID]
133
+ ├── Token expiry: [var/yok, süre]
134
+ ├── Refresh token mekanizması: [var/yok]
135
+ ├── Token rotation: [var/yok]
136
+ └── Logout'ta token invalidation: [var/yok]
137
+
138
+ 2. Oturum Güvenliği:
139
+ ├── Session fixation koruması: [var/yok]
140
+ ├── Concurrent session kontrolü: [var/yok]
141
+ ├── Idle timeout: [var/yok, süre]
142
+ ├── Absolute timeout: [var/yok, süre]
143
+ └── Secure/HttpOnly/SameSite cookie flags: [var/yok]
144
+
145
+ 3. Yetkilendirme:
146
+ ├── Route-level auth check: [var/yok]
147
+ ├── API-level auth check: [var/yok]
148
+ ├── Role-based access control: [var/yok]
149
+ ├── Client-side route guard: [var/yok]
150
+ ├── Server-side middleware: [var/yok]
151
+ └── Privilege escalation riski: [var/yok]
152
+
153
+ 4. Şifre/Credential Güvenliği:
154
+ ├── Şifre karmaşıklık kuralları: [var/yok]
155
+ ├── Rate limiting (brute force): [var/yok]
156
+ ├── Account lockout: [var/yok]
157
+ ├── Password hash algoritması: [bcrypt/argon2/scrypt]
158
+ └── 2FA desteği: [var/yok]
159
+ ```
160
+
161
+ ### Kategori 5: Environment & Secret Yönetimi
162
+
163
+ ```
164
+ 🔒 Environment & Secrets:
165
+
166
+ 1. Env Variable Güvenliği:
167
+ ├── Client-side'da erişilebilen secret'lar: [RISK — liste]
168
+ ├── .env dosyası gitignore'da mı?: [Evet/Hayır]
169
+ ├── .env.example mevcut mu?: [Evet/Hayır]
170
+ ├── Hardcoded secret/API key: [var/yok — dosya:satır]
171
+ └── Secret'lar sadece server-side'da mı?: [Evet/Hayır]
172
+
173
+ 2. Git Geçmişi:
174
+ ├── Geçmişte commit'lenmiş secret: [tespit edilebiliyorsa]
175
+ ├── .gitignore kapsamı yeterli mi?: [Evet/Hayır]
176
+ └── Git hook'lar (secret scanning): [var/yok]
177
+
178
+ 3. Üçüncü Parti Servis Key'leri:
179
+ ├── API key'ler rotation'a uygun mu?: [Evet/Hayır]
180
+ ├── Minimum yetki prensibi: [Evet/Hayır]
181
+ ├── Key scope/restriction: [var/yok]
182
+ └── Ayrı dev/prod key'ler: [Evet/Hayır]
183
+ ```
184
+
185
+ ### Kategori 6: Input Validation & Data Sanitization
186
+
187
+ ```
188
+ 🧹 Input Validation:
189
+
190
+ 1. Form Validation:
191
+ ├── Client-side validation: [var/yok, kütüphane]
192
+ ├── Server-side validation: [var/yok, kütüphane]
193
+ ├── Validation schema paylaşımı (client-server): [var/yok]
194
+ └── Zod/Yup/Valibot kullanımı: [var/yok]
195
+
196
+ 2. SQL/NoSQL Injection:
197
+ ├── Parameterized query kullanımı: [var/yok]
198
+ ├── ORM kullanımı: [var/yok — Prisma/Drizzle vs.]
199
+ ├── Raw query'ler: [var/yok — dosya:satır]
200
+ └── User input'un query'de doğrudan kullanımı: [var/yok]
201
+
202
+ 3. File Upload:
203
+ ├── File type validation: [var/yok]
204
+ ├── File size limiti: [var/yok, değer]
205
+ ├── File name sanitization: [var/yok]
206
+ ├── Magic number validation: [var/yok]
207
+ └── Upload dizini web root dışında mı?: [Evet/Hayır]
208
+
209
+ 4. API Input:
210
+ ├── Request body validation: [var/yok]
211
+ ├── Query parameter validation: [var/yok]
212
+ ├── Path parameter validation: [var/yok]
213
+ ├── Content-Type kontrolü: [var/yok]
214
+ └── Rate limiting: [var/yok]
215
+ ```
216
+
217
+ ### Kategori 7: Frontend-Specific Güvenlik
218
+
219
+ ```
220
+ 🖥️ Frontend Güvenlik:
221
+
222
+ 1. Dış Linkler:
223
+ ├── rel="noopener noreferrer" kullanımı: [var/yok]
224
+ ├── Target="_blank" güvenliği: [var/yok]
225
+ └── Outbound link kontrolü: [var/yok]
226
+
227
+ 2. Sensitive Data Handling:
228
+ ├── Console.log'da sensitive veri: [var/yok]
229
+ ├── localStorage'da sensitive veri: [var/yok]
230
+ ├── URL'de sensitive veri (query param): [var/yok]
231
+ ├── Error mesajlarında sensitive veri leak: [var/yok]
232
+ └── Source map production'da kapalı mı?: [Evet/Hayır]
233
+
234
+ 3. Content Injection:
235
+ ├── User-generated content sanitization: [var/yok]
236
+ ├── Markdown rendering güvenliği: [var/yok]
237
+ ├── Rich text editor güvenliği: [var/yok]
238
+ └── SVG upload XSS riski: [var/yok]
239
+ ```
240
+
241
+ ---
242
+
243
+ ## Puanlama Sistemi
244
+
245
+ ```
246
+ 🔒 Güvenlik Raporu:
247
+
248
+ ┌──────────────────────────┬───────┬──────────┐
249
+ │ Kategori │ Puan │ Seviye │
250
+ ├──────────────────────────┼───────┼──────────┤
251
+ │ Dependency Güvenliği │ XX/100│ 🟢/🟡/🔴│
252
+ │ XSS Koruması │ XX/100│ 🟢/🟡/🔴│
253
+ │ CSRF & Request Security │ XX/100│ 🟢/🟡/🔴│
254
+ │ Auth & Authorization │ XX/100│ 🟢/🟡/🔴│
255
+ │ Environment & Secrets │ XX/100│ 🟢/🟡/🔴│
256
+ │ Input Validation │ XX/100│ 🟢/🟡/🔴│
257
+ │ Frontend Security │ XX/100│ 🟢/🟡/🔴│
258
+ ├──────────────────────────┼───────┼──────────┤
259
+ │ GENEL │ XX/100│ 🟢/🟡/🔴│
260
+ └──────────────────────────┴───────┴──────────┘
261
+
262
+ 🟢 90-100: Güvenli
263
+ 🟡 60-89: İyileştirme gerekli
264
+ 🔴 0-59: Kritik — acil müdahale
265
+ ```
266
+
267
+ ---
268
+
269
+ ## Düzeltme Önerileri
270
+
271
+ ```
272
+ 🎯 Düzeltme Planı (Öncelik Sırasına Göre):
273
+
274
+ 🔴 Kritik (Hemen Düzelt):
275
+ 1. [Sorun] → [Çözüm] — [Etkilenen dosya]
276
+ 2. [Sorun] → [Çözüm]
277
+
278
+ 🟡 Yüksek (Bu Sprint İçinde):
279
+ 3. [Sorun] → [Çözüm]
280
+ 4. [Sorun] → [Çözüm]
281
+
282
+ 🟢 Orta (Plana Al):
283
+ 5. [Sorun] → [Çözüm]
284
+ 6. [Sorun] → [Çözüm]
285
+
286
+ ℹ️ Bilgi (Best Practice Önerisi):
287
+ 7. [Öneri]
288
+ 8. [Öneri]
289
+ ```
290
+
291
+ ---
292
+
293
+ ## OWASP Top 10 Kontrol Listesi
294
+
295
+ Her taramada OWASP Top 10'u (2021) referans al:
296
+
297
+ | # | Risk | Kontrol | Durum |
298
+ |---|------|---------|-------|
299
+ | A01 | Broken Access Control | Yetkilendirme kontrolleri | ✅/❌ |
300
+ | A02 | Cryptographic Failures | Şifreleme/hashing uygulamaları | ✅/❌ |
301
+ | A03 | Injection | SQL/NoSQL/OS/LDAP injection koruması | ✅/❌ |
302
+ | A04 | Insecure Design | Güvenli tasarım pattern'ları | ✅/❌ |
303
+ | A05 | Security Misconfiguration | Header'lar, CORS, default ayarlar | ✅/❌ |
304
+ | A06 | Vulnerable Components | Dependency güvenliği | ✅/❌ |
305
+ | A07 | Auth Failures | Kimlik doğrulama zafiyetleri | ✅/❌ |
306
+ | A08 | Data Integrity Failures | Veri bütünlüğü kontrolleri | ✅/❌ |
307
+ | A09 | Logging Failures | Güvenlik log'lama | ✅/❌ |
308
+ | A10 | SSRF | Server-Side Request Forgery koruması | ✅/❌ |
309
+
310
+ ---
311
+
312
+ ## Çıktı Formatı
313
+
314
+ 1. **Genel skor** — Hızlı bakış güvenlik puanlama tablosu
315
+ 2. **Kritik bulgular** — Acil düzeltme gerektiren sorunlar (varsa ilk başta vurgula)
316
+ 3. **Kategori detayları** — Her kategori için kontrol listesi sonuçları
317
+ 4. **OWASP Top 10 uyum** — Hangi riskler karşılanmış, hangisi eksik
318
+ 5. **Düzeltme planı** — Öncelik sırasına göre aksiyon listesi
319
+ 6. **Otomatik düzeltilebilecekler** — Hemen uygulanabilecek fix'ler (kullanıcı onayı ile)
@@ -0,0 +1,389 @@
1
+ # /write-tests — Test Yazma Skill'i
2
+
3
+ > **Tetikleyici:** `/write-tests [dosya/modül]`
4
+ > **Amaç:** Belirtilen component, hook veya utility için kapsamlı test dosyası üretmek.
5
+ > **Çıktı:** Proje convention'ına uygun test dosyası
6
+
7
+ ---
8
+
9
+ ## Temel İlkeler
10
+
11
+ - **Kullanıcı davranışını test et, implementation detail'leri değil.** Testing Library felsefesi.
12
+ - **Her test bağımsız (isolated) olmalı.** Testler arası paylaşılan state olmamalı.
13
+ - **Mock'ları minimum tut.** Gerçek modülleri mümkün olduğunca kullan.
14
+ - **Test piramidini uygula.** Çok unit test, az integration test, minimal E2E test.
15
+ - **Mevcut test convention'ına uy.** Proje kurallarındaki test yapısını takip et.
16
+
17
+ ---
18
+
19
+ ## Kullanım Formatları
20
+
21
+ ```
22
+ /write-tests src/components/Button.tsx
23
+ /write-tests src/hooks/useAuth.ts
24
+ /write-tests src/utils/formatDate.ts
25
+ /write-tests src/services/userService.ts
26
+ /write-tests src/features/auth/ ← Tüm klasör için test planı
27
+ /write-tests UserProfile ← Modül adı ile (AI dosyayı bulur)
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Uygulama Adımları
33
+
34
+ ### Adım 1: Hedef Analizi
35
+
36
+ Hedef dosyayı oku ve şunları tespit et:
37
+
38
+ ```
39
+ 📋 Test Hedefi Analizi:
40
+ ├── Hedef dosya: [dosya yolu]
41
+ ├── Dosya tipi: [component / hook / util / service / page]
42
+ ├── Export'lar: [fonksiyon/component listesi]
43
+ ├── Bağımlılıklar: [import edilen modüller]
44
+ ├── Props/Parametreler: [tip bilgileri]
45
+ ├── Side effect'ler: [API çağrısı, localStorage, timer vs.]
46
+ ├── Mevcut test: [var/yok, dosya yolu]
47
+ └── Test runner: [Vitest / Jest / projeden tespit et]
48
+ ```
49
+
50
+ ### Adım 2: Proje Test Convention Tespiti
51
+
52
+ Projede mevcut testleri inceleyerek convention belirle:
53
+
54
+ ```
55
+ 🔍 Test Convention:
56
+ ├── Test runner: [Vitest / Jest]
57
+ ├── Test dosya konumu: [yanında / __tests__/ klasöründe]
58
+ ├── Dosya adlandırma: [*.test.ts / *.spec.ts / *.test.tsx]
59
+ ├── Import stili: [import { render } from '@testing-library/react']
60
+ ├── Describe/it yapısı: [nested describe / flat it]
61
+ ├── Mock yaklaşımı: [vi.mock / jest.mock / MSW]
62
+ ├── Setup dosyası: [setupTests.ts / vitest.setup.ts]
63
+ ├── Custom render/wrapper: [var/yok — theme provider, router wrapper vs.]
64
+ └── Assertion stili: [expect().toBe / expect().toEqual / custom matchers]
65
+ ```
66
+
67
+ ### Adım 3: Test Senaryoları Planlama
68
+
69
+ Her dosya tipi için farklı senaryo stratejisi:
70
+
71
+ #### Component Test Senaryoları
72
+ ```
73
+ 📝 Test Planı — [ComponentName]:
74
+
75
+ 1. Rendering Testleri:
76
+ □ Default props ile doğru render edilme
77
+ □ Tüm prop varyasyonları (her prop kombinasyonu)
78
+ □ Conditional rendering (if/ternary ile gösterilen/gizlenen bölümler)
79
+ □ Children prop ile render
80
+ □ Empty/null state render
81
+
82
+ 2. Kullanıcı Etkileşimi:
83
+ □ Click olayları (button, link, toggle)
84
+ □ Form input'ları (type, clear, submit)
85
+ □ Keyboard navigasyonu (Tab, Enter, Escape)
86
+ □ Hover/focus state'leri (tooltip, dropdown)
87
+
88
+ 3. State Değişiklikleri:
89
+ □ Initial state doğruluğu
90
+ □ State geçişleri (loading → success, loading → error)
91
+ □ Controlled vs uncontrolled davranış
92
+
93
+ 4. API/Async Operasyonlar:
94
+ □ Loading state gösterimi
95
+ □ Success state ve veri gösterimi
96
+ □ Error state ve hata mesajı
97
+ □ Retry mekanizması (varsa)
98
+
99
+ 5. Edge Case'ler:
100
+ □ Boş veri / undefined prop
101
+ □ Çok uzun metin / overflow
102
+ □ Hızlı ardışık tıklama (debounce/throttle)
103
+ □ Unmount sırasında cleanup
104
+
105
+ 6. Erişilebilirlik:
106
+ □ ARIA attribute'ları doğru mu?
107
+ □ Semantik HTML kullanılmış mı?
108
+ □ Keyboard ile erişilebilir mi?
109
+ □ Screen reader uyumlu mu?
110
+ ```
111
+
112
+ #### Hook Test Senaryoları
113
+ ```
114
+ 📝 Test Planı — [useHookName]:
115
+
116
+ 1. Initial State:
117
+ □ Default değerler doğru mu?
118
+ □ Parametrelerle başlatma
119
+
120
+ 2. State Güncellemeleri:
121
+ □ Her action/setter doğru çalışıyor mu?
122
+ □ State geçişleri beklenen sırada mı?
123
+ □ Birden fazla güncelleme batch ediliyor mu?
124
+
125
+ 3. Side Effect'ler:
126
+ □ useEffect doğru zamanda çalışıyor mu?
127
+ □ Cleanup fonksiyonu çağrılıyor mu?
128
+ □ Dependency değişikliğinde yeniden çalışıyor mu?
129
+
130
+ 4. API Entegrasyonu (varsa):
131
+ □ Fetch başarılı senaryo
132
+ □ Fetch hata senaryosu
133
+ □ Loading/stale/error state geçişleri
134
+ □ Cache invalidation (TanStack Query vs.)
135
+
136
+ 5. Edge Case'ler:
137
+ □ Rapid state güncellemeleri
138
+ □ Unmount sırasında async işlem
139
+ □ Invalid parametre geçilmesi
140
+ ```
141
+
142
+ #### Utility/Service Test Senaryoları
143
+ ```
144
+ 📝 Test Planı — [functionName]:
145
+
146
+ 1. Happy Path:
147
+ □ Normal input → beklenen output
148
+ □ Farklı geçerli input varyasyonları
149
+
150
+ 2. Edge Case'ler:
151
+ □ Boş input (null, undefined, empty string, empty array)
152
+ □ Sınır değerler (0, -1, MAX_SAFE_INTEGER)
153
+ □ Özel karakterler / unicode
154
+ □ Çok büyük input
155
+
156
+ 3. Error Handling:
157
+ □ Invalid input → doğru hata fırlatma
158
+ □ Hata mesajı açıklayıcı mı?
159
+
160
+ 4. Type Safety (TypeScript):
161
+ □ Tip uyumsuzluğu compile-time'da yakalanıyor mu?
162
+ □ Return tipi doğru çıkarılıyor mu?
163
+ ```
164
+
165
+ ### Adım 4: Test Dosyası Oluşturma
166
+
167
+ Test planını onaylandıktan sonra, proje convention'ına uygun test dosyası yaz:
168
+
169
+ ```
170
+ 📄 Test Dosyası Yapısı:
171
+
172
+ [dosya-adı].test.tsx (veya projede kullanılan uzantı)
173
+ ├── Import'lar (test utility, component, mock'lar)
174
+ ├── Mock tanımları (gerekirse)
175
+ ├── describe('[ComponentName]', () => {
176
+ │ ├── describe('Rendering', () => { ... })
177
+ │ ├── describe('User Interaction', () => { ... })
178
+ │ ├── describe('State Changes', () => { ... })
179
+ │ ├── describe('API/Async', () => { ... })
180
+ │ ├── describe('Edge Cases', () => { ... })
181
+ │ └── describe('Accessibility', () => { ... })
182
+ │ })
183
+ └── Helper fonksiyonlar (renderWithProviders vs.)
184
+ ```
185
+
186
+ ---
187
+
188
+ ## Test Yazım Kuralları
189
+
190
+ ### Element Seçim Önceliği (Testing Library)
191
+
192
+ ```
193
+ 1. getByRole → En çok tercih edilen (erişilebilirlik dostu)
194
+ 2. getByLabelText → Form elemanları için
195
+ 3. getByPlaceholderText → Input'lar için (label yoksa)
196
+ 4. getByText → Görünür metin ile seçim
197
+ 5. getByDisplayValue → Form değeri ile seçim
198
+ 6. getByAltText → Görseller için
199
+ 7. getByTitle → title attribute ile
200
+ 8. getByTestId → SON ÇARE — sadece diğerleri işe yaramadığında
201
+ ```
202
+
203
+ ### Async Test Kuralları
204
+
205
+ ```typescript
206
+ // ✅ Doğru — waitFor ile async bekleme
207
+ await waitFor(() => {
208
+ expect(screen.getByText('Loaded')).toBeInTheDocument();
209
+ });
210
+
211
+ // ✅ Doğru — findBy kullanımı (waitFor + getBy kısaltması)
212
+ const element = await screen.findByText('Loaded');
213
+
214
+ // ❌ Yanlış — setTimeout ile bekleme
215
+ await new Promise(resolve => setTimeout(resolve, 1000));
216
+ ```
217
+
218
+ ### Mock Kuralları
219
+
220
+ ```typescript
221
+ // ✅ Doğru — Minimal mock, sadece gerekli kısım
222
+ vi.mock('@/services/api', () => ({
223
+ fetchUser: vi.fn(),
224
+ }));
225
+
226
+ // ✅ Doğru — MSW ile API mock (integration test)
227
+ server.use(
228
+ http.get('/api/users/:id', () => {
229
+ return HttpResponse.json({ id: 1, name: 'Test User' });
230
+ })
231
+ );
232
+
233
+ // ❌ Yanlış — Tüm modülü mock'lama (gereksiz)
234
+ vi.mock('@/services/api'); // Auto-mock tüm export'ları undefined yapar
235
+ ```
236
+
237
+ ### Assertion Best Practice'leri
238
+
239
+ ```typescript
240
+ // ✅ Spesifik assertion
241
+ expect(screen.getByRole('button', { name: 'Submit' })).toBeEnabled();
242
+ expect(screen.getByRole('alert')).toHaveTextContent('Error occurred');
243
+
244
+ // ❌ Genel assertion (ne test ettiği belirsiz)
245
+ expect(container.innerHTML).toContain('Submit');
246
+ expect(document.querySelector('.error')).toBeTruthy();
247
+ ```
248
+
249
+ ---
250
+
251
+ ## Dosya Tipi Bazlı Test Şablonları
252
+
253
+ ### Component Test Şablonu
254
+
255
+ ```typescript
256
+ import { render, screen, within } from '@testing-library/react';
257
+ import userEvent from '@testing-library/user-event';
258
+ import { describe, it, expect, vi } from 'vitest'; // veya jest'ten
259
+ import { ComponentName } from './ComponentName';
260
+
261
+ // Gerekirse wrapper
262
+ function renderComponent(props = {}) {
263
+ const defaultProps = {
264
+ // default prop değerleri
265
+ };
266
+ return render(<ComponentName {...defaultProps} {...props} />);
267
+ }
268
+
269
+ describe('ComponentName', () => {
270
+ describe('Rendering', () => {
271
+ it('should render with default props', () => {
272
+ renderComponent();
273
+ expect(screen.getByRole('...')).toBeInTheDocument();
274
+ });
275
+ });
276
+
277
+ describe('User Interaction', () => {
278
+ it('should handle click event', async () => {
279
+ const user = userEvent.setup();
280
+ const handleClick = vi.fn();
281
+ renderComponent({ onClick: handleClick });
282
+
283
+ await user.click(screen.getByRole('button'));
284
+ expect(handleClick).toHaveBeenCalledTimes(1);
285
+ });
286
+ });
287
+
288
+ describe('Edge Cases', () => {
289
+ it('should handle empty data gracefully', () => {
290
+ renderComponent({ data: [] });
291
+ expect(screen.getByText('No items')).toBeInTheDocument();
292
+ });
293
+ });
294
+ });
295
+ ```
296
+
297
+ ### Hook Test Şablonu
298
+
299
+ ```typescript
300
+ import { renderHook, act, waitFor } from '@testing-library/react';
301
+ import { describe, it, expect, vi } from 'vitest';
302
+ import { useHookName } from './useHookName';
303
+
304
+ describe('useHookName', () => {
305
+ it('should return initial state', () => {
306
+ const { result } = renderHook(() => useHookName());
307
+ expect(result.current.value).toBe(initialValue);
308
+ });
309
+
310
+ it('should update state', () => {
311
+ const { result } = renderHook(() => useHookName());
312
+ act(() => {
313
+ result.current.setValue('new value');
314
+ });
315
+ expect(result.current.value).toBe('new value');
316
+ });
317
+
318
+ it('should handle async operation', async () => {
319
+ const { result } = renderHook(() => useHookName());
320
+ act(() => {
321
+ result.current.fetchData();
322
+ });
323
+ await waitFor(() => {
324
+ expect(result.current.data).toBeDefined();
325
+ });
326
+ });
327
+ });
328
+ ```
329
+
330
+ ### Utility Test Şablonu
331
+
332
+ ```typescript
333
+ import { describe, it, expect } from 'vitest';
334
+ import { functionName } from './functionName';
335
+
336
+ describe('functionName', () => {
337
+ describe('happy path', () => {
338
+ it.each([
339
+ ['input1', 'expected1'],
340
+ ['input2', 'expected2'],
341
+ ])('should return %s for input %s', (input, expected) => {
342
+ expect(functionName(input)).toBe(expected);
343
+ });
344
+ });
345
+
346
+ describe('edge cases', () => {
347
+ it('should handle null input', () => {
348
+ expect(functionName(null)).toBe(defaultValue);
349
+ });
350
+
351
+ it('should handle empty string', () => {
352
+ expect(functionName('')).toBe(defaultValue);
353
+ });
354
+ });
355
+
356
+ describe('error cases', () => {
357
+ it('should throw for invalid input', () => {
358
+ expect(() => functionName(invalidInput)).toThrow('Expected error message');
359
+ });
360
+ });
361
+ });
362
+ ```
363
+
364
+ ---
365
+
366
+ ## Test Coverage Hedefleri
367
+
368
+ ```
369
+ Önerilen Minimum Coverage:
370
+ ├── Statements: %80+
371
+ ├── Branches: %75+
372
+ ├── Functions: %80+
373
+ └── Lines: %80+
374
+
375
+ Kritik Modüller İçin (auth, payment, data):
376
+ ├── Statements: %95+
377
+ ├── Branches: %90+
378
+ ├── Functions: %95+
379
+ └── Lines: %95+
380
+ ```
381
+
382
+ ---
383
+
384
+ ## Çıktı Formatı
385
+
386
+ 1. **Test planı özeti** — Hangi senaryolar test edilecek
387
+ 2. **Kullanıcı onayı** — Plan uygun mu, ekleme/çıkarma var mı?
388
+ 3. **Test dosyası** — Convention'a uygun, çalıştırılabilir test kodu
389
+ 4. **Çalıştırma komutu** — `npx vitest run [dosya]` veya benzeri