Laravel projelerinde Flux UI kullanırken karşılaşılan en sinir bozucu hatalardan biri, tüm testlerin geçtiği halde üretim ortamında ortaya çıkan çöküşlerdir. Bugün Flux tarafından yönetilen bir admin arayüzünde çalışırken, aslında basit bir ikon adı hatasının derin bir sorunu ortaya çıkardığını gördüm: mevcut testler bu hatayı asla yakalayamayacaktı.
Flux UI'da ikon adı hatası: sadece çalışma zamanında ortaya çıkıyor
Flux UI, ikonları icon.ellipsis gibi adlarla çözer ve var olmayan bir ikon adıyla karşılaştığında doğrudan bir hata fırlatır:
Flux component [icon.ellipsis] does not exist.Bu hata son derece yaygın çünkü Flux Heroicons ikon setini kullanırken, birçok geliştirici alışkanlıkla Lucide ikon adlarını yazıyor. Örneğin:
- Lucide alışkanlığıyla
ellipsisyazarken, Flux `ellipsis-horizontal` bekliyor trash-2yerine `trash` gerekiyoreye-offyerine `eye-slash` kullanılması gerekiyor
Bu basit bir tip hatası gibi görünse de, Flux'un ikon çözümleme sistemi titiz olduğu için üretimde doğrudan uygulamanın çökmesine neden oluyor.
Neden feature testleri bu hataları yakalayamıyor?
Mevcut test stratejimde, admin rotasına yapılan bir feature testi sonucu 200 HTTP durumu dönüyordu. Tüm testler yeşil kalıyordu. Ancak gerçek kullanıcı arayüzü çalıştırıldığında çöküyordu. Peki neden?
Flux, ikonları headless test ortamında no-op olarak işliyor. Yani {{ $this->icon('name') }} ifadesi test sırasında gerçekten render edilmiyor ve ikon adı hiçbir zaman çözümlenmeye çalışılmıyor. Çöküş sadece tam bir Laravel ortamında (testbench serve) ortaya çıkıyor — otomatik testlerimizin kapsamadığı bir senaryoda.
Bu durumu bir analojiye benzetebiliriz: klavyede yazarken çalışan bir yazım denetleyicisi düşünün. Testler sadece klavyede yazarken çalışıyor ve hataları göstermiyor. Oysa gerçek belgeyi bastığınızda (üretim ortamında) tüm hatalar ortaya çıkıyor. Testlerimiz sadece "yazarken" çalışıyor, "bastırırken" değil.
Kaynak koda dayalı bir test: ikon adlarını doğrulama
Bu sorunu çözmek için, Blade görünümündeki tüm ikon adlarını statik olarak okuyan ve varlıklarını doğrulayan bir Pest testi yazdım. Test, Flux'un ikon stublarına doğrudan başvurarak çalışıyor ve aşağıdaki adımları izliyor:
- Flux ikon stublarının bulunduğu dizini doğrula
- Blade dosyasını oku ve hem statik hem de dinamik ikon ifadelerini yakala
- Tüm benzersiz ikon adlarını topla
- Her bir adın Flux tarafından desteklenen bir Heroicon olduğunu doğrula
İşte test kodunun Türkçeleştirilmiş ve açıklanmış versiyonu:
$fluxIconStubs = base_path('vendor/livewire/flux/stubs/resources/views/flux/icon');
it('sadece var olan Flux ikonlarını referans almalıdır', function () use ($fluxIconStubs) {
// Flux ikon stublarının var olup olmadığını doğrula
expect(is_dir($fluxIconStubs))->toBeTrue("Flux ikon stubları bulunamadı");
// Blade dosyasını oku
$view = file_get_contents(__DIR__.'/../../resources/views/livewire/sso-providers.blade.php');
// Statik ikon referanslarını yakala: icon="name"
// Dinamik ifadelerdeki ikonları da yakala: icon="{{ $cond ? 'eye-slash' : 'eye' }}"
preg_match_all('/icon="([a-z][a-z0-9-]*)"/', $view, $static);
preg_match_all('/icon="\{\{(.+?)\}\}"/', $view, $dynamic);
// Statik ikonları al
$names = $static[1];
// Dinamik ifadelerdeki ikon adlarını ayıkla
foreach ($dynamic[1] as $expression) {
preg_match_all("/'([a-z][a-z0-9-]*)'"/, $expression, $tokens);
$names = array_merge($names, $tokens[1]);
}
// Benzersiz adları al
$names = array_values(array_unique($names));
expect($names)->not->toBeEmpty();
// Her bir ikon adının Flux'ta var olup olmadığını kontrol et
foreach ($names as $name) {
expect(is_file("{$fluxIconStubs}/{$name}.blade.php"))
->toBeTrue("Flux, [{$name}] ikonunu tanımıyor — Heroicon adı kullanın (Flux Lucide yerine Heroicons kullanır).");
}
});Bu testin avantajları neler?
Bu yaklaşımın birkaç önemli avantajı bulunuyor:
- Kaynak doğruluğu: Test, Flux'un ikon kaydını doğrudan
vendor/dizinindeki stublardan kontrol ediyor. Böylece statik bir listeden bağımsız olarak her zaman güncel kalıyor.
- Dinamik ikon desteği: Geliştiricilerin en çok kaçırdığı durumlar, koşullu ifadeler içindeki ikon seçimleri. Örneğin
eyeveeye-slasharasında geçiş yapan toggle bileşenleri. İkinci regex ifadesi bu dinamik yapıları da yakalıyor.
- Öğretici hata mesajları: Test başarısız olduğunda, sadece "hata" demiyor. "Flux Lucide yerine Heroicons kullanır" şeklinde açıklayıcı bir mesaj veriyor. Bu, gelecekteki benim için değerli bir rehber olacak.
Bu testin uygulamasını yaptığım aynı gün, Flux'un ücretsiz ve Pro versiyonları arasındaki ikon farklılıkları nedeniyle başka bir pakette de aynı hatanın oluştuğunu gördüm. Örneğin webhook, ellipsis ve list ikonları sadece Flux Pro'da bulunuyor. Bu koruyucu test sayesinde, üretimde çöküş yerine CI sürecinde hatayı yakalamak mümkün hale geliyor.
Bu deseni ne zaman kullanmalısınız?
Her küçük hata için bir test yazmak gerekmiyor. Bu desen özellikle çalışma zamanında testlerinizin size yalan söylediği durumlarda devreye giriyor:
- Bir bileşen headless ortamda no-op olarak işleniyor
- Bir adaptör mock'lanmış durumda
- Ortam üretimden farklı davranıyor
Bu gibi durumlarda, kaynak dosyaları üzerinde statik bir test yapmak — Blade görünümünü, config dosyasını veya migration'ı okuyarak — dinamik testlerin yakalayamadığı hataları yakalamanızı sağlıyor.
Kendime koyduğum kural şu: Eğer bir hata sadece tam bir boot sırasında ortaya çıkıyorsa ancak testleriniz headless çalışıyorsa, CI ortamında tam boot yerine problemi erken yakalayın. Kaynak dosyalar üzerinde yapılan statik bir doğrulama, daha ucuz, daha hızlı ve hiçbir zaman no-op olarak render edilmeyecek. Unutmayın: testler sadece problemleri erkenden yakalamak içindir, üretimde ortaya çıktıklarında değil.
Yapay zeka özeti
Flux UI entegrasyonunda Heroicon ve Lucide ikon adlarını karıştırdığınızda üretimde çöküş yaşanır. Bu testi yazarak hataları CI sürecinde yakalayın ve sorunları erkenden çözün.