Files
portal/app/tests/Feature/Admin/AdminTenantAlivenessTest.php
T

108 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\Tenant;
use App\Models\User;
use App\Services\Admin\TenantAlivenessService;
use Carbon\CarbonImmutable;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
uses(DatabaseTransactions::class);
/** Кладёт строку в журнал входов на указанное московское время. */
function alivenessLog(int $tenantId, ?int $userId, string $event, string $mskTime): void
{
DB::table('auth_log')->insert([
'actor_type' => 'tenant_user',
'tenant_id' => $tenantId,
'user_id' => $userId,
'email' => 'client@example.test',
'event' => $event,
'ip_address' => '5.166.40.65',
'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)',
'created_at' => CarbonImmutable::parse($mskTime, 'Europe/Moscow')->utc(),
]);
}
function alivenessTenant(): array
{
$tenant = Tenant::factory()->create();
$user = User::factory()->create(['tenant_id' => $tenant->id]);
return [(int) $tenant->id, (int) $user->id];
}
it('считает клиента живым, если он заходил не позже трёх суток назад', function () {
[$tenantId, $userId] = alivenessTenant();
$now = CarbonImmutable::parse('2026-08-07 12:00:00', 'Europe/Moscow');
alivenessLog($tenantId, $userId, 'login_success', '2026-08-04 09:00:00');
$result = app(TenantAlivenessService::class)->forTenant($tenantId, $now);
expect($result['state'])->toBe('active');
expect($result['days_since_login'])->toBe(3);
});
it('считает клиента остывающим на четвёртые сутки', function () {
[$tenantId, $userId] = alivenessTenant();
$now = CarbonImmutable::parse('2026-08-07 12:00:00', 'Europe/Moscow');
alivenessLog($tenantId, $userId, 'login_success', '2026-08-03 09:00:00');
$result = app(TenantAlivenessService::class)->forTenant($tenantId, $now);
expect($result['state'])->toBe('cooling');
expect($result['days_since_login'])->toBe(4);
});
it('считает клиента пропавшим на четырнадцатые сутки', function () {
[$tenantId, $userId] = alivenessTenant();
$now = CarbonImmutable::parse('2026-08-07 12:00:00', 'Europe/Moscow');
alivenessLog($tenantId, $userId, 'login_success', '2026-07-24 09:00:00');
$result = app(TenantAlivenessService::class)->forTenant($tenantId, $now);
expect($result['state'])->toBe('lost');
expect($result['days_since_login'])->toBe(14);
});
it('не путает сутки в первые три часа ночи по Москве', function () {
[$tenantId, $userId] = alivenessTenant();
// 01:30 МСК седьмого августа — это ещё 22:30 UTC шестого.
// Наивная граница дала бы «вчера» вместо «сегодня».
$now = CarbonImmutable::parse('2026-08-07 01:30:00', 'Europe/Moscow');
alivenessLog($tenantId, $userId, 'login_success', '2026-08-07 01:00:00');
$result = app(TenantAlivenessService::class)->forTenant($tenantId, $now);
expect($result['days_since_login'])->toBe(0);
expect($result['state'])->toBe('active');
});
it('отличает зарегистрировавшегося без единого входа', function () {
[$tenantId, $userId] = alivenessTenant();
$now = CarbonImmutable::parse('2026-08-07 12:00:00', 'Europe/Moscow');
alivenessLog($tenantId, $userId, 'register_success', '2026-08-06 09:00:00');
$result = app(TenantAlivenessService::class)->forTenant($tenantId, $now);
expect($result['state'])->toBe('never_logged_in');
});
it('отдаёт no_data, когда в журнале нет ни одной строки', function () {
[$tenantId] = alivenessTenant();
$now = CarbonImmutable::parse('2026-08-07 12:00:00', 'Europe/Moscow');
$result = app(TenantAlivenessService::class)->forTenant($tenantId, $now);
expect($result['state'])->toBe('no_data');
expect($result['last_login_at'])->toBeNull();
expect($result['days'])->toBe([]);
});