Files
prn2026/tests/Feature/ExportPurgeCommandTest.php
2026-06-03 08:51:22 +08:00

181 lines
5.9 KiB
PHP

<?php
namespace Tests\Feature;
use App\Models\ExportLog;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class ExportPurgeCommandTest extends TestCase
{
use RefreshDatabase;
public function test_command_purges_files_older_than_retention_period(): void
{
Storage::fake('local');
$this->seed(DatabaseSeeder::class);
$path = 'exports/finance/old-export.xlsx';
Storage::disk('local')->put($path, 'export content');
$log = ExportLog::query()->create([
'generated_at' => now()->subDays(31),
'report_type' => 'finance_verification_list',
'file_name' => 'old-export.xlsx',
'disk' => 'local',
'path' => $path,
'created_at' => now()->subDays(31),
'updated_at' => now()->subDays(31),
]);
$this->artisan('exports:purge', ['--days' => 30])
->assertSuccessful()
->expectsOutputToContain('Purged 1 export file(s).');
Storage::disk('local')->assertMissing($path);
$this->assertNotNull($log->fresh()->purged_at);
}
public function test_command_does_not_purge_files_within_retention_period(): void
{
Storage::fake('local');
$this->seed(DatabaseSeeder::class);
$path = 'exports/finance/recent-export.xlsx';
Storage::disk('local')->put($path, 'export content');
$log = ExportLog::query()->create([
'generated_at' => now()->subDays(10),
'report_type' => 'finance_verification_list',
'file_name' => 'recent-export.xlsx',
'disk' => 'local',
'path' => $path,
]);
$this->artisan('exports:purge', ['--days' => 30])
->assertSuccessful()
->expectsOutputToContain('No export files eligible');
Storage::disk('local')->assertExists($path);
$this->assertNull($log->fresh()->purged_at);
}
public function test_command_marks_log_as_purged_even_when_file_missing(): void
{
$this->seed(DatabaseSeeder::class);
$log = ExportLog::query()->create([
'generated_at' => now()->subDays(40),
'report_type' => 'attendance_detail_by_pusat',
'file_name' => 'missing-file.xlsx',
'disk' => 'local',
'path' => 'exports/attendance/missing-file.xlsx',
'created_at' => now()->subDays(40),
'updated_at' => now()->subDays(40),
]);
$this->artisan('exports:purge', ['--days' => 30])
->assertSuccessful()
->expectsOutputToContain('1 record(s) had no file on disk');
$this->assertNotNull($log->fresh()->purged_at);
}
public function test_command_does_not_re_purge_already_purged_records(): void
{
Storage::fake('local');
$this->seed(DatabaseSeeder::class);
$path = 'exports/finance/already-purged.xlsx';
$log = ExportLog::query()->create([
'generated_at' => now()->subDays(60),
'report_type' => 'finance_verification_list',
'file_name' => 'already-purged.xlsx',
'disk' => 'local',
'path' => $path,
'purged_at' => now()->subDays(5),
'created_at' => now()->subDays(60),
'updated_at' => now()->subDays(60),
]);
$this->artisan('exports:purge', ['--days' => 30])
->assertSuccessful()
->expectsOutputToContain('No export files eligible');
// purged_at should not change
$this->assertEquals(
$log->fresh()->purged_at->toDateString(),
now()->subDays(5)->toDateString()
);
}
public function test_command_accepts_custom_retention_days(): void
{
Storage::fake('local');
$this->seed(DatabaseSeeder::class);
$path = 'exports/finance/week-old.xlsx';
Storage::disk('local')->put($path, 'export content');
$log = ExportLog::query()->create([
'generated_at' => now()->subDays(8),
'report_type' => 'finance_verification_list',
'file_name' => 'week-old.xlsx',
'disk' => 'local',
'path' => $path,
'created_at' => now()->subDays(8),
'updated_at' => now()->subDays(8),
]);
// With default 30 days — should NOT purge
$this->artisan('exports:purge', ['--days' => 30])
->assertSuccessful()
->expectsOutputToContain('No export files eligible');
$this->assertNull($log->fresh()->purged_at);
// With 7 days — should purge
$this->artisan('exports:purge', ['--days' => 7])
->assertSuccessful()
->expectsOutputToContain('Purged 1 export file(s).');
$this->assertNotNull($log->fresh()->purged_at);
Storage::disk('local')->assertMissing($path);
}
public function test_command_records_activity_log_on_purge(): void
{
Storage::fake('local');
$this->seed(DatabaseSeeder::class);
$path = 'exports/finance/log-test.xlsx';
Storage::disk('local')->put($path, 'export content');
ExportLog::query()->create([
'generated_at' => now()->subDays(31),
'report_type' => 'finance_verification_list',
'file_name' => 'log-test.xlsx',
'disk' => 'local',
'path' => $path,
'created_at' => now()->subDays(31),
'updated_at' => now()->subDays(31),
]);
$this->artisan('exports:purge', ['--days' => 30])->assertSuccessful();
$this->assertDatabaseHas('activity_log', [
'log_name' => 'exports',
'description' => 'export_file_purged',
]);
}
public function test_command_rejects_invalid_days_option(): void
{
$this->artisan('exports:purge', ['--days' => 0])
->assertFailed();
}
}