Files
biiproject-kit-v1/tests/Feature/Models/PrunableModelsTest.php
T

181 lines
7.4 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\AI\AiUsageLog;
use App\Models\AiHealingLog;
use App\Models\MobileErrorLog;
use App\Models\MobileSyncLog;
use App\Models\Notification;
use App\Models\OtpCode;
use App\Models\PasswordHistory;
use App\Models\User;
use App\Models\UserTrustedDevice;
use Illuminate\Database\Eloquent\Builder;
// ── OtpCode ───────────────────────────────────────────────────────────────────
test('OtpCode prunable selects only expired records', function () {
OtpCode::create(['identifier' => 'a@a.com', 'code' => '111111', 'expires_at' => now()->subMinute()]);
OtpCode::create(['identifier' => 'b@b.com', 'code' => '222222', 'expires_at' => now()->addHour()]);
$prunableIds = (new OtpCode)->prunable()->pluck('id');
expect($prunableIds)->toHaveCount(1);
});
test('OtpCode prunable returns a Builder instance', function () {
expect((new OtpCode)->prunable())->toBeInstanceOf(Builder::class);
});
// ── UserTrustedDevice ─────────────────────────────────────────────────────────
test('UserTrustedDevice prunable selects expired devices only', function () {
$user = User::factory()->create();
UserTrustedDevice::create([
'user_id' => $user->id,
'device_id' => 'old-device',
'token' => 'tok1',
'expires_at' => now()->subDay(),
]);
UserTrustedDevice::create([
'user_id' => $user->id,
'device_id' => 'fresh-device',
'token' => 'tok2',
'expires_at' => now()->addDays(30),
]);
$ids = (new UserTrustedDevice)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
test('UserTrustedDevice prunable returns a Builder instance', function () {
expect((new UserTrustedDevice)->prunable())->toBeInstanceOf(Builder::class);
});
// ── PasswordHistory ───────────────────────────────────────────────────────────
test('PasswordHistory prunable selects records older than 365 days', function () {
$user = User::factory()->create();
\DB::table('password_histories')->insert([
['user_id' => $user->id, 'password' => 'h1', 'created_at' => now()->subDays(400), 'updated_at' => now()],
['user_id' => $user->id, 'password' => 'h2', 'created_at' => now()->subDays(100), 'updated_at' => now()],
]);
$ids = (new PasswordHistory)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
test('PasswordHistory prunable returns a Builder instance', function () {
expect((new PasswordHistory)->prunable())->toBeInstanceOf(Builder::class);
});
// ── MobileSyncLog ─────────────────────────────────────────────────────────────
test('MobileSyncLog prunable selects records older than 30 days', function () {
\DB::table('mobile_sync_logs')->insert([
['synced_at' => now()->subDays(35)],
['synced_at' => now()->subDays(10)],
]);
$ids = (new MobileSyncLog)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
test('MobileSyncLog prunable returns a Builder instance', function () {
expect((new MobileSyncLog)->prunable())->toBeInstanceOf(Builder::class);
});
// ── MobileErrorLog ────────────────────────────────────────────────────────────
test('MobileErrorLog prunable selects records older than 90 days', function () {
\DB::table('mobile_error_logs')->insert([
['message' => 'old error', 'occurred_at' => now()->subDays(100)],
['message' => 'new error', 'occurred_at' => now()->subDays(5)],
]);
$ids = (new MobileErrorLog)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
test('MobileErrorLog prunable returns a Builder instance', function () {
expect((new MobileErrorLog)->prunable())->toBeInstanceOf(Builder::class);
});
// ── Notification (system_notifications) ──────────────────────────────────────
test('Notification prunable selects records older than 30 days', function () {
\DB::table('system_notifications')->insert([
['title' => 'old', 'message' => 'x', 'recipient' => 'all', 'type' => 'info', 'created_at' => now()->subDays(40), 'updated_at' => now()],
['title' => 'new', 'message' => 'y', 'recipient' => 'all', 'type' => 'info', 'created_at' => now()->subDays(5), 'updated_at' => now()],
]);
$ids = (new Notification)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
test('Notification prunable returns a Builder instance', function () {
expect((new Notification)->prunable())->toBeInstanceOf(Builder::class);
});
// ── AiHealingLog ──────────────────────────────────────────────────────────────
test('AiHealingLog prunable selects records older than 90 days', function () {
\DB::table('ai_healing_logs')->insert([
['error_message' => 'old', 'created_at' => now()->subDays(100), 'updated_at' => now()],
['error_message' => 'new', 'created_at' => now()->subDays(10), 'updated_at' => now()],
]);
$ids = (new AiHealingLog)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
test('AiHealingLog prunable returns a Builder instance', function () {
expect((new AiHealingLog)->prunable())->toBeInstanceOf(Builder::class);
});
// ── AiUsageLog ────────────────────────────────────────────────────────────────
test('AiUsageLog prunable selects records older than 3 months', function () {
\DB::table('ai_usage_logs')->insert([
['provider' => 'openai', 'model' => 'gpt-4', 'status' => 'success', 'created_at' => now()->subMonths(4), 'updated_at' => now()],
['provider' => 'openai', 'model' => 'gpt-4', 'status' => 'success', 'created_at' => now()->subWeek(), 'updated_at' => now()],
]);
$ids = (new AiUsageLog)->prunable()->pluck('id');
expect($ids)->toHaveCount(1);
});
// ── Edge cases ────────────────────────────────────────────────────────────────
test('OtpCode prunable returns empty when all codes are still valid', function () {
OtpCode::create(['identifier' => 'c@c.com', 'code' => '333333', 'expires_at' => now()->addHour()]);
$ids = (new OtpCode)->prunable()->pluck('id');
expect($ids)->toBeEmpty();
});
test('UserTrustedDevice prunable returns empty when no devices are expired', function () {
$user = User::factory()->create();
UserTrustedDevice::create([
'user_id' => $user->id,
'device_id' => 'good-device',
'token' => 'tok3',
'expires_at' => now()->addDays(7),
]);
$ids = (new UserTrustedDevice)->prunable()->pluck('id');
expect($ids)->toBeEmpty();
});