Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Helpers/ConsoleOutput.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

class ConsoleOutput
{
public static Command $runningCommand;
public static ?Command $runningCommand = null;

public function setOutput(Command $runningCommand)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Models/Traits/SupportsCertificateCheck.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace Spatie\UptimeMonitor\Models\Traits;

use Exception;
use Spatie\SslCertificate\SslCertificate;
use Spatie\UptimeMonitor\Events\CertificateCheckFailed;
use Spatie\UptimeMonitor\Events\CertificateCheckSucceeded;
use Spatie\UptimeMonitor\Events\CertificateExpiresSoon;
use Spatie\UptimeMonitor\Models\Enums\CertificateStatus;
use Spatie\UptimeMonitor\Models\Monitor;
use Throwable;

trait SupportsCertificateCheck
{
Expand All @@ -18,7 +18,7 @@ public function checkCertificate(): void
$certificate = SslCertificate::createForHostName($this->url->getHost());

$this->setCertificate($certificate);
} catch (Exception $exception) {
} catch (Throwable $exception) {
$this->setCertificateException($exception);
}
}
Expand All @@ -36,7 +36,7 @@ public function setCertificate(SslCertificate $certificate): void
$this->fireEventsForUpdatedMonitorWithCertificate($this, $certificate);
}

public function setCertificateException(Exception $exception): void
public function setCertificateException(Throwable $exception): void
{
$this->certificate_status = CertificateStatus::INVALID;
$this->certificate_expiration_date = null;
Expand Down
47 changes: 47 additions & 0 deletions tests/Integration/Models/Traits/SupportsCertificateCheckTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Spatie\UptimeMonitor\Test\Integration\Models\Traits;

use Carbon\Carbon;
use Error;
use Exception;
use Illuminate\Support\Facades\Event;
use Spatie\SslCertificate\Downloader;
Expand Down Expand Up @@ -114,4 +115,50 @@ public function it_can_set_certificate_exception()
$this->assertNull($this->monitor->certificate_expiration_date);
Event::assertDispatched(CertificateCheckFailed::class);
}

/** @test */
public function it_can_set_certificate_error()
{
// Collect
// Error is a PHP 7+ class that implements Throwable but doesn't extend Exception
// This simulates DNS resolution failures and SSL errors that can throw Error in PHP 8+
$error = new Error('DNS resolution failed: getaddrinfo failed');

// Act
$this->monitor->setCertificateException($error);

// Assert
$this->monitor->fresh();
$this->assertSame(CertificateStatus::INVALID, $this->monitor->certificate_status);
$this->assertSame('DNS resolution failed: getaddrinfo failed', $this->monitor->certificate_check_failure_reason);
$this->assertSame('', $this->monitor->certificate_issuer);
$this->assertNull($this->monitor->certificate_expiration_date);
Event::assertDispatched(CertificateCheckFailed::class);
}

/** @test */
public function it_catches_error_exceptions_during_certificate_check()
{
// Arrange
// Use an invalid hostname that will cause DNS resolution to fail
// In PHP 8+, DNS failures can throw Error exceptions (not Exception)
$monitor = Monitor::factory()->create([
'certificate_check_enabled' => true,
'certificate_status' => CertificateStatus::NOT_YET_CHECKED,
'url' => 'https://this-domain-definitely-does-not-exist-12345.invalid',
]);

// Act
$monitor->checkCertificate();

// Assert
$monitor->fresh();
$this->assertSame(CertificateStatus::INVALID, $monitor->certificate_status);
$this->assertNotNull($monitor->certificate_check_failure_reason);
$this->assertSame('', $monitor->certificate_issuer);
$this->assertNull($monitor->certificate_expiration_date);
Event::assertDispatched(CertificateCheckFailed::class, function ($event) use ($monitor) {
return $event->monitor->id === $monitor->id;
});
}
}