feat: add routes, lang, tests, stubs, docs, and docker configurations
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
<?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();
|
||||
});
|
||||
Reference in New Issue
Block a user