112 lines
4 KiB
PHP
112 lines
4 KiB
PHP
<?php
|
|
|
|
use App\Mail\PaymentIncidentAlert;
|
|
use App\Models\IncidentActivity;
|
|
use App\Models\PaymentIncident;
|
|
use App\Models\ProviderUptimeLog;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Illuminate\Support\Facades\Mail;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
// ─── Uptime-Command: Erfolgsfall ──────────────────────────────────────────────
|
|
|
|
it('schreibt einen positiven ProviderUptimeLog wenn PAYONE erreichbar ist', function () {
|
|
Http::fake([
|
|
'api.pay1.de/*' => Http::response('', 200),
|
|
]);
|
|
|
|
$this->artisan('payment:check-uptime')->assertSuccessful();
|
|
|
|
$log = ProviderUptimeLog::where('provider', 'payone')->latest()->first();
|
|
expect($log)->not->toBeNull();
|
|
expect($log->is_up)->toBeTrue();
|
|
expect($log->error_message)->toBeNull();
|
|
});
|
|
|
|
it('schreibt einen negativen ProviderUptimeLog und legt Incident an wenn PAYONE nicht erreichbar ist', function () {
|
|
Http::fake([
|
|
'api.pay1.de/*' => Http::response('Server Error', 503),
|
|
]);
|
|
|
|
$this->artisan('payment:check-uptime')->assertSuccessful();
|
|
|
|
$log = ProviderUptimeLog::where('provider', 'payone')->latest()->first();
|
|
expect($log)->not->toBeNull();
|
|
expect($log->is_up)->toBeFalse();
|
|
|
|
$incident = PaymentIncident::where('provider', 'payone')->where('type', 'outage')->first();
|
|
expect($incident)->not->toBeNull();
|
|
expect($incident->severity)->toBe('critical');
|
|
expect($incident->status)->toBe('open');
|
|
});
|
|
|
|
it('erstellt keine doppelten Outage-Incidents bei mehrfachem Ausfall in derselben Stunde', function () {
|
|
Http::fake([
|
|
'api.pay1.de/*' => Http::response('', 503),
|
|
]);
|
|
|
|
$this->artisan('payment:check-uptime');
|
|
$this->artisan('payment:check-uptime');
|
|
|
|
expect(PaymentIncident::where('provider', 'payone')->where('type', 'outage')->count())->toBe(1);
|
|
});
|
|
|
|
it('löst offene Outage-Incidents automatisch auf wenn PAYONE wieder erreichbar ist', function () {
|
|
PaymentIncident::create([
|
|
'title' => 'Automatischer Ausfall',
|
|
'provider' => 'payone',
|
|
'type' => 'outage',
|
|
'severity' => 'critical',
|
|
'status' => 'open',
|
|
'detected_at' => now()->subMinutes(10),
|
|
]);
|
|
|
|
Http::fake([
|
|
'api.pay1.de/*' => Http::response('', 200),
|
|
]);
|
|
|
|
$this->artisan('payment:check-uptime')->assertSuccessful();
|
|
|
|
$incident = PaymentIncident::where('provider', 'payone')->where('type', 'outage')->first();
|
|
expect($incident->fresh()->status)->toBe('resolved');
|
|
expect($incident->fresh()->resolved_at)->not->toBeNull();
|
|
|
|
$activity = IncidentActivity::where('incident_id', $incident->id)
|
|
->where('type', 'status_change')
|
|
->first();
|
|
expect($activity)->not->toBeNull();
|
|
});
|
|
|
|
it('verarbeitet Verbindungsfehler als Ausfall', function () {
|
|
Http::fake([
|
|
'api.pay1.de/*' => fn () => throw new \Exception('Connection refused'),
|
|
]);
|
|
|
|
$this->artisan('payment:check-uptime')->assertSuccessful();
|
|
|
|
$log = ProviderUptimeLog::where('provider', 'payone')->latest()->first();
|
|
expect($log->is_up)->toBeFalse();
|
|
expect($log->error_message)->toContain('Connection refused');
|
|
});
|
|
|
|
// ─── Mailable ────────────────────────────────────────────────────────────────
|
|
|
|
it('sendet PaymentIncidentAlert-Mail wenn critical Incident angelegt wird', function () {
|
|
Mail::fake();
|
|
|
|
$incident = PaymentIncident::create([
|
|
'title' => 'Kritischer Test-Incident',
|
|
'provider' => 'payone',
|
|
'type' => 'outage',
|
|
'severity' => 'critical',
|
|
'detected_at' => now(),
|
|
]);
|
|
|
|
Mail::to(config('app.exception_mail'))->queue(new PaymentIncidentAlert($incident));
|
|
|
|
Mail::assertQueued(PaymentIncidentAlert::class, function (PaymentIncidentAlert $mail) use ($incident) {
|
|
return $mail->incident->id === $incident->id;
|
|
});
|
|
});
|