110 lines
3.5 KiB
PHP
110 lines
3.5 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Tests\Feature\Admin;
|
||
|
|
|
||
|
|
use App\Models\Role;
|
||
|
|
use App\Models\User;
|
||
|
|
use App\Models\Permission;
|
||
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
|
|
use Illuminate\Http\UploadedFile;
|
||
|
|
use Illuminate\Support\Facades\File;
|
||
|
|
use Tests\TestCase;
|
||
|
|
use ZipArchive;
|
||
|
|
|
||
|
|
class ThemeUploadTest extends TestCase
|
||
|
|
{
|
||
|
|
use RefreshDatabase;
|
||
|
|
|
||
|
|
protected User $admin;
|
||
|
|
protected string $themesPath;
|
||
|
|
|
||
|
|
protected function setUp(): void
|
||
|
|
{
|
||
|
|
parent::setUp();
|
||
|
|
$this->seed(\Database\Seeders\PermissionSeeder::class);
|
||
|
|
$this->seed(\Database\Seeders\RoleSeeder::class);
|
||
|
|
|
||
|
|
$this->admin = User::factory()->create();
|
||
|
|
$adminRole = Role::where('slug', 'admin')->first();
|
||
|
|
$this->admin->roles()->attach($adminRole);
|
||
|
|
|
||
|
|
$this->themesPath = base_path('themes');
|
||
|
|
if (!File::exists($this->themesPath)) {
|
||
|
|
File::makeDirectory($this->themesPath);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_admin_can_upload_valid_theme_zip(): void
|
||
|
|
{
|
||
|
|
$themeName = 'test-upload-theme';
|
||
|
|
$zipPath = storage_path('app/test_theme.zip');
|
||
|
|
|
||
|
|
$this->createTestThemeZip($zipPath, $themeName);
|
||
|
|
|
||
|
|
$file = new UploadedFile($zipPath, 'test_theme.zip', 'application/zip', null, true);
|
||
|
|
|
||
|
|
$response = $this->actingAs($this->admin)->postJson('/loom/themes/upload', [
|
||
|
|
'theme_zip' => $file,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response->assertStatus(200);
|
||
|
|
$response->assertJsonPath('message', 'Theme uploaded successfully.');
|
||
|
|
|
||
|
|
$this->assertTrue(File::exists(base_path("themes/{$themeName}/theme.md")));
|
||
|
|
|
||
|
|
// Cleanup
|
||
|
|
File::delete($zipPath);
|
||
|
|
if (File::exists(base_path("themes/{$themeName}"))) {
|
||
|
|
File::deleteDirectory(base_path("themes/{$themeName}"));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_upload_fails_if_theme_md_is_missing(): void
|
||
|
|
{
|
||
|
|
$zipPath = storage_path('app/invalid_theme.zip');
|
||
|
|
$tempDir = storage_path('app/temp_invalid_' . uniqid());
|
||
|
|
File::makeDirectory($tempDir);
|
||
|
|
File::put($tempDir . '/somefile.txt', 'content');
|
||
|
|
|
||
|
|
shell_exec("cd {$tempDir} && zip -r {$zipPath} .");
|
||
|
|
File::deleteDirectory($tempDir);
|
||
|
|
|
||
|
|
$file = new UploadedFile($zipPath, 'invalid_theme.zip', 'application/zip', null, true);
|
||
|
|
|
||
|
|
$response = $this->actingAs($this->admin)->postJson('/loom/themes/upload', [
|
||
|
|
'theme_zip' => $file,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response->assertStatus(422);
|
||
|
|
$response->assertJsonPath('message', 'Invalid theme: theme.md is missing.');
|
||
|
|
|
||
|
|
// Cleanup
|
||
|
|
File::delete($zipPath);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_non_admin_cannot_upload_themes(): void
|
||
|
|
{
|
||
|
|
$user = User::factory()->create();
|
||
|
|
// Regular user role doesn't have upload-themes permission
|
||
|
|
$user->roles()->attach(Role::where('slug', 'user')->first());
|
||
|
|
|
||
|
|
$response = $this->actingAs($user)->postJson('/loom/themes/upload', [
|
||
|
|
'theme_zip' => UploadedFile::fake()->create('theme.zip', 100, 'application/zip'),
|
||
|
|
]);
|
||
|
|
|
||
|
|
$response->assertStatus(403);
|
||
|
|
}
|
||
|
|
|
||
|
|
protected function createTestThemeZip(string $path, string $themeName): void
|
||
|
|
{
|
||
|
|
$tempDir = storage_path('app/temp_' . $themeName);
|
||
|
|
File::makeDirectory($tempDir . '/' . $themeName, 0755, true);
|
||
|
|
File::put($tempDir . '/' . $themeName . '/theme.md', "Title: Test Upload Theme\nAuthor: Junie\nDescription: A test theme.");
|
||
|
|
File::put($tempDir . '/' . $themeName . '/index.blade.php', "<h1>Test Theme</h1>");
|
||
|
|
|
||
|
|
shell_exec("cd {$tempDir} && zip -r {$path} {$themeName}");
|
||
|
|
|
||
|
|
File::deleteDirectory($tempDir);
|
||
|
|
}
|
||
|
|
}
|