89 lines
2.9 KiB
PHP
89 lines
2.9 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature;
|
|
|
|
use Illuminate\Http\Client\Request;
|
|
use Illuminate\Support\Facades\Http;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* health:check reports to healthchecks.io: a plain ping when every service is
|
|
* fine, /fail with the reasons when one is not (see HealthCheck).
|
|
*/
|
|
class HealthCheckCommandTest extends TestCase
|
|
{
|
|
private const PING = 'https://hc-ping.test/abc-123';
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
config([
|
|
'cache.default' => 'array',
|
|
'timebank_cc.health_monitor.enabled' => true,
|
|
'timebank_cc.health_monitor.healthcheck_url' => self::PING,
|
|
'timebank_cc.health_monitor.website_url' => 'https://site.test',
|
|
'timebank_cc.health_monitor.disk_max_percent' => 100,
|
|
'elasticsearch.host' => 'es.test:9200',
|
|
]);
|
|
}
|
|
|
|
public function test_a_healthy_run_sends_a_plain_ping(): void
|
|
{
|
|
Http::fake([
|
|
'es.test:9200/*' => Http::response(['status' => 'yellow']),
|
|
'site.test*' => Http::response('ok'),
|
|
'hc-ping.test/*' => Http::response('OK'),
|
|
]);
|
|
|
|
$this->artisan('health:check')->assertExitCode(0);
|
|
|
|
Http::assertSent(fn (Request $r) => $r->url() === self::PING);
|
|
Http::assertNotSent(fn (Request $r) => str_ends_with($r->url(), '/fail'));
|
|
}
|
|
|
|
public function test_a_failing_service_is_reported_with_its_reason(): void
|
|
{
|
|
Http::fake([
|
|
'es.test:9200/*' => Http::response(['status' => 'red']),
|
|
'site.test*' => Http::response('down', 500),
|
|
'hc-ping.test/*' => Http::response('OK'),
|
|
]);
|
|
|
|
$this->artisan('health:check')->assertExitCode(1);
|
|
|
|
Http::assertSent(function (Request $r) {
|
|
return $r->url() === self::PING . '/fail'
|
|
&& str_contains($r->body(), 'elasticsearch: cluster status red')
|
|
&& str_contains($r->body(), 'website: https://site.test answered HTTP 500');
|
|
});
|
|
}
|
|
|
|
public function test_a_full_disk_fails(): void
|
|
{
|
|
config(['timebank_cc.health_monitor.disk_max_percent' => 1]);
|
|
|
|
Http::fake([
|
|
'es.test:9200/*' => Http::response(['status' => 'green']),
|
|
'site.test*' => Http::response('ok'),
|
|
'hc-ping.test/*' => Http::response('OK'),
|
|
]);
|
|
|
|
$this->artisan('health:check')->assertExitCode(1);
|
|
|
|
Http::assertSent(fn (Request $r) => $r->url() === self::PING . '/fail'
|
|
&& str_contains($r->body(), 'disk:'));
|
|
}
|
|
|
|
public function test_it_runs_every_five_minutes(): void
|
|
{
|
|
$this->artisan('schedule:list')->expectsOutputToContain('health:check');
|
|
|
|
$event = collect(app(\Illuminate\Console\Scheduling\Schedule::class)->events())
|
|
->first(fn ($e) => str_contains($e->command ?? '', 'health:check'));
|
|
|
|
$this->assertNotNull($event);
|
|
$this->assertSame('*/5 * * * *', $event->expression);
|
|
}
|
|
}
|