163 lines
5.1 KiB
PHP
163 lines
5.1 KiB
PHP
<?php
|
|
|
|
namespace Tests\Feature\Jobs;
|
|
|
|
use App\Enums\AccountStatusEnum;
|
|
use App\Enums\NotificationTypeEnum;
|
|
use App\Jobs\CheckPlatformCredentialsJob;
|
|
use App\Models\Notification;
|
|
use App\Models\PlatformAccount;
|
|
use App\Modules\Lemmy\Services\LemmyApiService;
|
|
use App\Services\Notification\NotificationService;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Mockery;
|
|
use Tests\TestCase;
|
|
|
|
class CheckPlatformCredentialsJobTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
private function runJob(bool $loginSucceeds): void
|
|
{
|
|
$api = Mockery::mock(LemmyApiService::class);
|
|
$api->shouldReceive('login')->andReturn($loginSucceeds ? 'a-token' : null);
|
|
|
|
$job = new class($api) extends CheckPlatformCredentialsJob
|
|
{
|
|
public function __construct(private LemmyApiService $api) {}
|
|
|
|
protected function makeApiService(PlatformAccount $account): LemmyApiService
|
|
{
|
|
return $this->api;
|
|
}
|
|
};
|
|
|
|
$job->handle(app(NotificationService::class));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $attributes
|
|
*/
|
|
private function account(array $attributes = []): PlatformAccount
|
|
{
|
|
return PlatformAccount::factory()->create(array_merge(['is_active' => true], $attributes));
|
|
}
|
|
|
|
public function test_a_successful_login_marks_the_account_healthy(): void
|
|
{
|
|
$account = $this->account(['status' => AccountStatusEnum::UNTESTED]);
|
|
|
|
$this->runJob(true);
|
|
|
|
$account->refresh();
|
|
$this->assertSame(AccountStatusEnum::HEALTHY, $account->status);
|
|
$this->assertSame(0, $account->consecutive_failures);
|
|
$this->assertNotNull($account->last_tested_at);
|
|
}
|
|
|
|
public function test_a_successful_login_clears_earlier_failures(): void
|
|
{
|
|
$account = $this->account(['status' => AccountStatusEnum::UNHEALTHY, 'consecutive_failures' => 2]);
|
|
|
|
$this->runJob(true);
|
|
|
|
$account->refresh();
|
|
$this->assertSame(AccountStatusEnum::HEALTHY, $account->status);
|
|
$this->assertSame(0, $account->consecutive_failures);
|
|
}
|
|
|
|
public function test_a_single_failure_does_not_mark_the_account_unhealthy(): void
|
|
{
|
|
$account = $this->account(['status' => AccountStatusEnum::HEALTHY]);
|
|
|
|
$this->runJob(false);
|
|
|
|
$account->refresh();
|
|
$this->assertSame(AccountStatusEnum::HEALTHY, $account->status);
|
|
$this->assertSame(1, $account->consecutive_failures);
|
|
}
|
|
|
|
public function test_the_threshold_failure_marks_the_account_unhealthy(): void
|
|
{
|
|
$account = $this->account([
|
|
'status' => AccountStatusEnum::HEALTHY,
|
|
'consecutive_failures' => PlatformAccount::FAILURES_BEFORE_UNHEALTHY - 1,
|
|
]);
|
|
|
|
$this->runJob(false);
|
|
|
|
$this->assertSame(AccountStatusEnum::UNHEALTHY, $account->refresh()->status);
|
|
}
|
|
|
|
public function test_a_single_failure_does_not_notify(): void
|
|
{
|
|
$this->account(['status' => AccountStatusEnum::HEALTHY]);
|
|
|
|
$this->runJob(false);
|
|
|
|
$this->assertDatabaseCount('notifications', 0);
|
|
}
|
|
|
|
public function test_becoming_unhealthy_notifies(): void
|
|
{
|
|
$account = $this->account([
|
|
'status' => AccountStatusEnum::HEALTHY,
|
|
'consecutive_failures' => PlatformAccount::FAILURES_BEFORE_UNHEALTHY - 1,
|
|
'username' => 'newsbot',
|
|
]);
|
|
|
|
$this->runJob(false);
|
|
|
|
$this->assertDatabaseHas('notifications', [
|
|
'type' => NotificationTypeEnum::CREDENTIAL_EXPIRED->value,
|
|
'notifiable_type' => $account->getMorphClass(),
|
|
'notifiable_id' => $account->id,
|
|
]);
|
|
$this->assertStringContainsString('newsbot', Notification::first()->title);
|
|
}
|
|
|
|
public function test_an_account_already_unhealthy_does_not_notify_again(): void
|
|
{
|
|
$this->account([
|
|
'status' => AccountStatusEnum::UNHEALTHY,
|
|
'consecutive_failures' => PlatformAccount::FAILURES_BEFORE_UNHEALTHY,
|
|
]);
|
|
|
|
$this->runJob(false);
|
|
|
|
$this->assertDatabaseCount('notifications', 0);
|
|
}
|
|
|
|
public function test_inactive_accounts_are_not_checked(): void
|
|
{
|
|
$account = $this->account(['is_active' => false, 'status' => AccountStatusEnum::UNTESTED]);
|
|
|
|
$this->runJob(false);
|
|
|
|
$account->refresh();
|
|
$this->assertSame(AccountStatusEnum::UNTESTED, $account->status);
|
|
$this->assertNull($account->last_tested_at);
|
|
}
|
|
|
|
public function test_an_exception_during_login_counts_as_a_failure(): void
|
|
{
|
|
$account = $this->account(['status' => AccountStatusEnum::HEALTHY]);
|
|
|
|
$api = Mockery::mock(LemmyApiService::class);
|
|
$api->shouldReceive('login')->andThrow(new \RuntimeException('instance unreachable'));
|
|
|
|
$job = new class($api) extends CheckPlatformCredentialsJob
|
|
{
|
|
public function __construct(private LemmyApiService $api) {}
|
|
|
|
protected function makeApiService(PlatformAccount $account): LemmyApiService
|
|
{
|
|
return $this->api;
|
|
}
|
|
};
|
|
|
|
$job->handle(app(NotificationService::class));
|
|
|
|
$this->assertSame(1, $account->refresh()->consecutive_failures);
|
|
}
|
|
}
|