seed(\Database\Seeders\PermissionSeeder::class); $this->seed(\Database\Seeders\RoleSeeder::class); $adminRole = Role::where('slug', 'admin')->first(); $this->user = User::factory()->create(); $this->user->roles()->attach($adminRole); } #[Test] public function admin_can_create_backup_via_cli() { // Setup some themes and media $themesPath = base_path('themes/test-backup-theme'); if (!File::isDirectory($themesPath)) { File::makeDirectory($themesPath, 0755, true); } File::put($themesPath . '/theme.md', 'title: Test'); Storage::disk('public')->put('media/test.jpg', 'content'); $exitCode = Artisan::call('sw:site:backup'); $this->assertEquals(0, $exitCode); $backupDir = storage_path('app/backups'); $this->assertTrue(File::isDirectory($backupDir)); $files = File::files($backupDir); $this->assertNotEmpty($files); // Cleanup File::deleteDirectory($themesPath); File::deleteDirectory($backupDir); } #[Test] public function admin_can_trigger_backup_via_web() { $response = $this->actingAs($this->user) ->post(route('admin.backups.store')); $response->assertStatus(302); $response->assertSessionHas('success'); $backupDir = storage_path('app/backups'); $this->assertTrue(File::isDirectory($backupDir)); // Cleanup File::deleteDirectory($backupDir); } #[Test] public function admin_can_restore_via_web() { // 1. Create a backup first $this->actingAs($this->user)->post(route('admin.backups.store')); $backupDir = storage_path('app/backups'); $files = File::files($backupDir); $this->assertNotEmpty($files); $filename = $files[0]->getFilename(); // 2. Mocking restoration for tests because it overwrites DB/Files // In this environment, we just want to ensure the controller calls the command. // But let's try a real call to see if it works with our SiteRestore logic. $response = $this->actingAs($this->user) ->post(route('admin.backups.restore'), [ 'filename' => $filename, ]); $response->assertStatus(302); $response->assertSessionHas('success'); // Cleanup File::deleteDirectory($backupDir); } #[Test] public function admin_can_download_backup() { $this->actingAs($this->user); Artisan::call('sw:site:backup'); $backupDir = storage_path('app/backups'); $files = File::files($backupDir); $filename = $files[0]->getFilename(); $response = $this->get(route('admin.backups.download', ['filename' => $filename])); $response->assertOk(); $response->assertHeader('Content-Disposition', 'attachment; filename=' . $filename); // Cleanup File::deleteDirectory($backupDir); } #[Test] public function admin_can_upload_backup() { $backupDir = storage_path('app/backups'); if (File::exists($backupDir)) { File::deleteDirectory($backupDir); } $filename = 'test_upload.gz'; $file = \Illuminate\Http\Testing\File::create($filename, 10); // 10KB dummy gz $response = $this->actingAs($this->user) ->post(route('admin.backups.upload'), [ 'backup_file' => $file, ]); $response->assertStatus(302); $response->assertSessionHas('success'); $this->assertTrue(File::exists($backupDir . '/' . $filename)); // Cleanup File::deleteDirectory($backupDir); } #[Test] public function security_audit_finds_suspect_code() { $tempPluginPath = base_path('plugins/temp-audit-plugin'); if (!File::isDirectory($tempPluginPath)) { File::makeDirectory($tempPluginPath, 0755, true); } File::put($tempPluginPath . '/unsafe.php', ''); $exitCode = Artisan::call('sw:plugins:audit', ['--path' => 'plugins/temp-audit-plugin']); // It returns 1 if issues found $this->assertEquals(1, $exitCode); // Cleanup File::deleteDirectory($tempPluginPath); } #[Test] public function media_cleanup_removes_orphaned_files() { Storage::fake('public'); // 1. Create referenced media $referencedMedia = Media::create([ 'filename' => 'referenced.jpg', 'path' => 'media/referenced.jpg', 'mime_type' => 'image/jpeg', 'size' => 100, ]); Storage::disk('public')->put('media/referenced.jpg', 'content'); Page::create([ 'title' => 'Test Page', 'slug' => 'test', 'content' => [ ['type' => 'media', 'media_id' => $referencedMedia->id] ], 'is_published' => true, 'user_id' => $this->user->id, ]); // 2. Create orphaned media $orphanedMedia = Media::create([ 'filename' => 'orphaned.jpg', 'path' => 'media/orphaned.jpg', 'mime_type' => 'image/jpeg', 'size' => 100, ]); Storage::disk('public')->put('media/orphaned.jpg', 'content'); // Verify they exist before cleanup $this->assertDatabaseHas('media', ['id' => $referencedMedia->id]); $this->assertDatabaseHas('media', ['id' => $orphanedMedia->id]); Storage::disk('public')->assertExists('media/referenced.jpg'); Storage::disk('public')->assertExists('media/orphaned.jpg'); // 3. Run cleanup Artisan::call('sw:media:cleanup'); // 4. Verify $this->assertDatabaseHas('media', ['id' => $referencedMedia->id]); $this->assertDatabaseMissing('media', ['id' => $orphanedMedia->id]); Storage::disk('public')->assertExists('media/referenced.jpg'); Storage::disk('public')->assertMissing('media/orphaned.jpg'); } }