From 29eaf722c22075b5f6d2da0e92435ebfc3d688d5 Mon Sep 17 00:00:00 2001 From: Tyson McCarney <48730964+J-T-McC@users.noreply.github.com> Date: Mon, 10 Jun 2024 00:40:10 -0700 Subject: [PATCH] Add support for Laravel 11 (#358) * Add support for Laravel 11 - updated composer dependencies to support Laravel 11 - add support for carbon 3 diffIn methods now returning floats - add test coverage for cert check trait - removed support for unmaintained laravel & php versions * Fix styling --------- Co-authored-by: J-T-McC --- .github/workflows/run-tests.yml | 16 +-- composer.json | 30 ++--- phpunit.xml.dist | 7 +- src/Helpers/Period.php | 4 +- .../Traits/SupportsCertificateCheck.php | 2 +- src/Models/Traits/SupportsUptimeCheck.php | 2 +- tests/Integration/Helpers/PeriodTest.php | 4 +- .../Traits/SupportsCertificateCheckTest.php | 117 ++++++++++++++++++ .../Models/Traits/SupportsUptimeCheckTest.php | 11 +- .../Notifications/EventHandlerTest.php | 4 +- tests/TestCase.php | 3 + 11 files changed, 160 insertions(+), 40 deletions(-) create mode 100644 tests/Integration/Models/Traits/SupportsCertificateCheckTest.php diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 3fb2c437..495414a5 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -9,21 +9,17 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - php: [8.1, 8.0] - laravel: [9.*, 8.*, 10.*] + php: [8.1, 8.2, 8.3] + laravel: [10.*, 11.*] dependency-version: [prefer-lowest, prefer-stable] include: - laravel: 10.* testbench: 8.* - - laravel: 9.* - testbench: 7.* - - laravel: 8.* - testbench: ^6.23 + - laravel: 11.* + testbench: 9.* exclude: - - laravel: 10.* - php: 8.0 - - laravel: 9.* - php: 7.4 + - laravel: 11.* + php: 8.1 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.dependency-version }} - ${{ matrix.os }} diff --git a/composer.json b/composer.json index 9208d8fa..b9fc05ab 100644 --- a/composer.json +++ b/composer.json @@ -16,29 +16,29 @@ } ], "require": { - "php": "^8.0", + "php": "^8.1", "ext-intl": "*", "ext-json": "*", - "graham-campbell/guzzle-factory": "^5.0", + "graham-campbell/guzzle-factory": "^5.0|^7.0", "guzzlehttp/guzzle": "^7.4|^7.2", - "illuminate/cache": "^8.73|^9.0|^10.0", - "illuminate/config": "^8.73|^9.0|^10.0", - "illuminate/console": "^8.73|^9.0|^10.0", - "illuminate/container": "^8.73|^9.0|^10.0", - "illuminate/contracts": "^8.73|^9.0|^10.0", - "illuminate/events": "^8.73|^9.0|^10.0", - "illuminate/filesystem": "^8.73|^9.0|^10.0", - "illuminate/notifications": "^8.73|^9.0|^10.0", - "illuminate/support": "^8.73|^9.0|^10.0", - "laravel/slack-notification-channel": "^2.4", + "illuminate/cache": "^10.0|^11.0", + "illuminate/config": "^10.0|^11.0", + "illuminate/console": "^10.0|^11.0", + "illuminate/container": "^10.0|^11.0", + "illuminate/contracts": "^10.0|^11.0", + "illuminate/events": "^10.0|^11.0", + "illuminate/filesystem": "^10.0|^11.0", + "illuminate/notifications": "^10.0|^11.0", + "illuminate/support": "^10.0|^11.0", + "laravel/slack-notification-channel": "^2.4|^3.2", "spatie/ssl-certificate": "^1.22|^2.1.2", "spatie/url": "^2.0.0" }, "require-dev": { "mockery/mockery": "^1.4", - "illuminate/testing": "^8.73|^9.0|^10.0", - "orchestra/testbench": "^6.23|^7.0|^8.0", - "phpunit/phpunit": "^9.5" + "illuminate/testing": "^10.0|^11.0", + "orchestra/testbench": "^8.0|^9.0", + "phpunit/phpunit": "^9.5|^10.5" }, "autoload": { "psr-4": { diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7fd13951..02a7fc9f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,5 @@ - - - - src/ - - + tests diff --git a/src/Helpers/Period.php b/src/Helpers/Period.php index 3225d4af..23784e25 100644 --- a/src/Helpers/Period.php +++ b/src/Helpers/Period.php @@ -26,11 +26,11 @@ public function duration(): string { $interval = $this->startDateTime->diff($this->endDateTime); - if (! $this->startDateTime->diffInHours($this->endDateTime)) { + if ($this->startDateTime->diffInHours($this->endDateTime) < 1) { return $interval->format('%im'); } - if (! $this->startDateTime->diffInDays($this->endDateTime)) { + if ($this->startDateTime->diffInDays($this->endDateTime) < 1) { return $interval->format('%hh %im'); } diff --git a/src/Models/Traits/SupportsCertificateCheck.php b/src/Models/Traits/SupportsCertificateCheck.php index b527e599..235ea676 100644 --- a/src/Models/Traits/SupportsCertificateCheck.php +++ b/src/Models/Traits/SupportsCertificateCheck.php @@ -52,7 +52,7 @@ protected function fireEventsForUpdatedMonitorWithCertificate(Monitor $monitor, if ($this->certificate_status === CertificateStatus::VALID) { event(new CertificateCheckSucceeded($this, $certificate)); - if ($certificate->expirationDate()->diffInDays() <= config('uptime-monitor.certificate_check.fire_expiring_soon_event_if_certificate_expires_within_days')) { + if ($certificate->expirationDate()->diffInDays(absolute: true) <= config('uptime-monitor.certificate_check.fire_expiring_soon_event_if_certificate_expires_within_days')) { event(new CertificateExpiresSoon($monitor, $certificate)); } diff --git a/src/Models/Traits/SupportsUptimeCheck.php b/src/Models/Traits/SupportsUptimeCheck.php index 6d999839..8365f1c4 100644 --- a/src/Models/Traits/SupportsUptimeCheck.php +++ b/src/Models/Traits/SupportsUptimeCheck.php @@ -47,7 +47,7 @@ public function shouldCheckUptime(): bool return true; } - return $this->uptime_last_check_date->diffInMinutes() >= $this->uptime_check_interval_in_minutes; + return (int)$this->uptime_last_check_date->diffInMinutes(absolute: true) >= $this->uptime_check_interval_in_minutes; } public function uptimeRequestSucceeded(ResponseInterface $response): void diff --git a/tests/Integration/Helpers/PeriodTest.php b/tests/Integration/Helpers/PeriodTest.php index 7efbbd3f..dcee5ef1 100644 --- a/tests/Integration/Helpers/PeriodTest.php +++ b/tests/Integration/Helpers/PeriodTest.php @@ -29,7 +29,7 @@ public function it_can_generate_a_string_representation_of_the_duration(int $dif $this->assertEquals($formattedString, $period->duration()); } - public function periodDataProvider(): array + public static function periodDataProvider(): array { return [ [10, '10m'], @@ -54,7 +54,7 @@ public function it_has_a_text_representation(Carbon $startDateTime, Carbon $endD $this->assertEquals($text, $period->toText()); } - public function textDataProvider(): array + public static function textDataProvider(): array { Carbon::setTestNow(Carbon::create(2016, 1, 1, 00, 00, 00)); diff --git a/tests/Integration/Models/Traits/SupportsCertificateCheckTest.php b/tests/Integration/Models/Traits/SupportsCertificateCheckTest.php new file mode 100644 index 00000000..9aac3038 --- /dev/null +++ b/tests/Integration/Models/Traits/SupportsCertificateCheckTest.php @@ -0,0 +1,117 @@ +monitor = Monitor::factory()->create([ + 'certificate_check_enabled' => true, + 'certificate_status' => CertificateStatus::NOT_YET_CHECKED, + 'url' => self::DOMAIN, + ]); + + $this->certificate = Downloader::downloadCertificateFromUrl(self::DOMAIN); + $this->daysBeforeExpiration = config( + 'uptime-monitor.certificate_check.fire_expiring_soon_event_if_certificate_expires_within_days' + ); + } + + /** @test */ + public function it_can_set_valid_certificate_not_within_expiration_range() + { + // Collect + Carbon::setTestNow($this->certificate->expirationDate()->subDays($this->daysBeforeExpiration + 1)); + + // Act + $this->monitor->setCertificate($this->certificate); + + // Assert + $this->monitor->fresh(); + $this->assertSame(CertificateStatus::VALID, $this->monitor->certificate_status); + $this->assertSame($this->certificate->getIssuer(), $this->monitor->certificate_issuer); + $this->assertTrue($this->monitor->certificate_expiration_date->isSameDay($this->certificate->expirationDate())); + Event::assertDispatched(CertificateCheckSucceeded::class); + Event::assertNotDispatched(CertificateCheckFailed::class); + Event::assertNotDispatched(CertificateExpiresSoon::class); + } + + /** @test */ + public function it_can_set_valid_certificate_within_expiration_range() + { + // Collect + Carbon::setTestNow($this->certificate->expirationDate()->subDays($this->daysBeforeExpiration - 1)); + + // Act + $this->monitor->setCertificate($this->certificate); + + // Assert + $this->monitor->fresh(); + $this->assertSame(CertificateStatus::VALID, $this->monitor->certificate_status); + $this->assertSame($this->certificate->getIssuer(), $this->monitor->certificate_issuer); + $this->assertTrue($this->monitor->certificate_expiration_date->isSameDay($this->certificate->expirationDate())); + Event::assertDispatched(CertificateCheckSucceeded::class); + Event::assertDispatched(CertificateExpiresSoon::class); + Event::assertNotDispatched(CertificateCheckFailed::class); + } + + /** @test */ + public function it_can_set_invalid_certificate() + { + // Collect + Carbon::setTestNow($this->certificate->expirationDate()->addDay()); + + // Act + $this->monitor->setCertificate($this->certificate); + + // Assert + $this->monitor->fresh(); + $this->assertSame(CertificateStatus::INVALID, $this->monitor->certificate_status); + $this->assertSame('The certificate has expired', $this->monitor->certificate_check_failure_reason); + $this->assertSame($this->certificate->getIssuer(), $this->monitor->certificate_issuer); + $this->assertTrue($this->monitor->certificate_expiration_date->isSameDay($this->certificate->expirationDate())); + Event::assertDispatched(CertificateCheckFailed::class); + Event::assertNotDispatched(CertificateCheckSucceeded::class); + Event::assertNotDispatched(CertificateExpiresSoon::class); + } + + /** @test */ + public function it_can_set_certificate_exception() + { + // Collect + $exception = new Exception('Certificate check failed'); + + // Act + $this->monitor->setCertificateException($exception); + + // Assert + $this->monitor->fresh(); + $this->assertSame(CertificateStatus::INVALID, $this->monitor->certificate_status); + $this->assertSame('Certificate check failed', $this->monitor->certificate_check_failure_reason); + $this->assertSame('', $this->monitor->certificate_issuer); + $this->assertNull($this->monitor->certificate_expiration_date); + Event::assertDispatched(CertificateCheckFailed::class); + } +} diff --git a/tests/Integration/Models/Traits/SupportsUptimeCheckTest.php b/tests/Integration/Models/Traits/SupportsUptimeCheckTest.php index 2a6cae56..13d5a633 100644 --- a/tests/Integration/Models/Traits/SupportsUptimeCheckTest.php +++ b/tests/Integration/Models/Traits/SupportsUptimeCheckTest.php @@ -3,6 +3,7 @@ namespace Spatie\UptimeMonitor\Test\Integration\Models\Traits; use Carbon\Carbon; +use PHPUnit\Framework\Constraint\IsEqualWithDelta; use Spatie\UptimeMonitor\Models\Enums\UptimeStatus; use Spatie\UptimeMonitor\Models\Monitor; use Spatie\UptimeMonitor\Test\TestCase; @@ -101,6 +102,14 @@ protected function monitorAttributeIsSetToNow(string $attribute): bool { $this->monitor = $this->monitor->fresh(); - return $this->monitor->$attribute->diffInMinutes() === 0; + $constraint = new IsEqualWithDelta( + value: 0, + delta: 1, + ); + + return $constraint->evaluate( + other: $this->monitor->$attribute->diffInMinutes(), + returnResult: true + ); } } diff --git a/tests/Integration/Notifications/EventHandlerTest.php b/tests/Integration/Notifications/EventHandlerTest.php index 723ee28a..c869f7dc 100644 --- a/tests/Integration/Notifications/EventHandlerTest.php +++ b/tests/Integration/Notifications/EventHandlerTest.php @@ -75,7 +75,7 @@ function ($notification) use ($monitor) { } } - public function eventClassDataProvider(): array + public static function eventClassDataProvider(): array { return [ [UptimeCheckSucceededEvent::class, UptimeCheckSucceeded::class, ['uptime_status' => UptimeStatus::UP], true], @@ -127,7 +127,7 @@ function ($notification, $usedChannels) use ($configuredChannels) { ); } - public function channelDataProvider(): array + public static function channelDataProvider(): array { return [ [['mail']], diff --git a/tests/TestCase.php b/tests/TestCase.php index 27c45867..11912433 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -57,6 +57,9 @@ protected function getEnvironmentSetUp($app) 'database' => ':memory:', ]); + $app['config']->set('uptime-monitor.notifications.slack.webhook_url', 'https://hooks.slack.com/fake'); + $app['config']->set('uptime-monitor.certificate_check.fire_expiring_soon_event_if_certificate_expires_within_days', 15); + $this->setUpDatabase(); }