From f9e3c6423826ba2c1fea1e5530454c8b28c32931 Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Fri, 3 Jul 2026 07:55:35 +0000 Subject: [PATCH] R0.3: Newsletter-Sync-Binding config-aware + ehrliche Test-Sync-Meldung Bisher wurde der NullNewsletterSyncClient unbedingt gebunden - NEWSLETTER_SYNC_ENABLED=true mit echtem Provider haette stumm nichts getan. Jetzt: Platzhalter-Provider -> No-Op-Client, aktivierter aber nicht implementierter Provider -> RuntimeException (fail fast). Das Admin-UI weist beim Test-Sync auf den Platzhalter hin. Co-Authored-By: Claude Fable 5 --- app/Providers/AppServiceProvider.php | 15 ++++++++++- .../livewire/admin/newsletter/sync.blade.php | 4 +++ tests/Feature/NewsletterSyncBindingTest.php | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/Feature/NewsletterSyncBindingTest.php diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 00bca29b..d0f6e00d 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -44,7 +44,20 @@ class AppServiceProvider extends ServiceProvider */ public function register(): void { - $this->app->bind(NewsletterSyncClient::class, NullNewsletterSyncClient::class); + $this->app->bind(NewsletterSyncClient::class, function (): NewsletterSyncClient { + $provider = (string) config('newsletter.sync.provider', 'placeholder'); + + // Es existiert bislang nur der No-Op-Client. Ein aktivierter, aber + // nicht implementierter Provider soll laut schlagen statt stumm + // ins Leere zu synchronisieren. + if (config('newsletter.sync.enabled') && $provider !== 'placeholder') { + throw new \RuntimeException( + "Newsletter-Sync-Provider [{$provider}] ist nicht implementiert – es existiert nur der Platzhalter-Client." + ); + } + + return new NullNewsletterSyncClient; + }); $this->app->singleton(PressReleaseService::class); $this->app->singleton(AdminRequestPerformanceMetrics::class); } diff --git a/resources/views/livewire/admin/newsletter/sync.blade.php b/resources/views/livewire/admin/newsletter/sync.blade.php index 18338285..804cee61 100644 --- a/resources/views/livewire/admin/newsletter/sync.blade.php +++ b/resources/views/livewire/admin/newsletter/sync.blade.php @@ -47,6 +47,10 @@ new #[Layout('components.layouts.app'), Title('Newsletter Sync')] class extends : 'unsubscribe'; $this->syncMessage = "Test-Sync ausgefuehrt ({$action}) fuer Subscription #{$subscription->id}."; + + if ((string) config('newsletter.sync.provider') === 'placeholder') { + $this->syncMessage .= ' Hinweis: Platzhalter-Provider – es wurde kein externes System aufgerufen.'; + } } public function with(): array diff --git a/tests/Feature/NewsletterSyncBindingTest.php b/tests/Feature/NewsletterSyncBindingTest.php new file mode 100644 index 00000000..6165c6c0 --- /dev/null +++ b/tests/Feature/NewsletterSyncBindingTest.php @@ -0,0 +1,26 @@ +set('newsletter.sync.enabled', false); + config()->set('newsletter.sync.provider', 'placeholder'); + + expect(app(NewsletterSyncClient::class))->toBeInstanceOf(NullNewsletterSyncClient::class); +}); + +test('newsletter sync resolves to the null client for the placeholder provider even when enabled', function () { + config()->set('newsletter.sync.enabled', true); + config()->set('newsletter.sync.provider', 'placeholder'); + + expect(app(NewsletterSyncClient::class))->toBeInstanceOf(NullNewsletterSyncClient::class); +}); + +test('an enabled but unimplemented sync provider fails fast instead of silently doing nothing', function () { + config()->set('newsletter.sync.enabled', true); + config()->set('newsletter.sync.provider', 'mailchimp'); + + expect(fn () => app(NewsletterSyncClient::class)) + ->toThrow(RuntimeException::class, 'mailchimp'); +});