Indigo (the default), Blue, Teal, Green, Amber, Rose and Violet in the Vibrant style and Graphite in the Neutral style are generated from config into the stylesheet. Admin settings opens with a colour profile card: a swatch previews the profile on the page, and Save Settings stores it as color_profile, which AppServiceProvider hands to the package's resolver, so every page, mail and error page wears it. An unknown profile is refused, and a saved one that disappears falls back to indigo. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V9NnLxnPp8vaaurb3Z1MFy
160 lines
5.3 KiB
PHP
160 lines
5.3 KiB
PHP
<?php
|
|
|
|
use App\Livewire\Admin\AdminSettings;
|
|
use App\Models\Setting;
|
|
use App\Models\User;
|
|
use Illuminate\Http\UploadedFile;
|
|
use Illuminate\Support\Facades\Hash;
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Livewire\Livewire;
|
|
|
|
test('admin settings requires authentication', function () {
|
|
$response = $this->get(route('admin.settings'));
|
|
|
|
$response->assertRedirect(route('login'));
|
|
});
|
|
|
|
test('non-admin user cannot access settings', function () {
|
|
$user = User::factory()->create(['is_admin' => false]);
|
|
|
|
$response = $this->actingAs($user)->get(route('admin.settings'));
|
|
|
|
$response->assertForbidden();
|
|
});
|
|
|
|
test('admin can access settings page', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
|
|
$response = $this->actingAs($admin)->get(route('admin.settings'));
|
|
|
|
$response->assertOk();
|
|
});
|
|
|
|
test('admin can save settings', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
|
|
$phpMaxMb = AdminSettings::phpMaxUploadMb();
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->set('maxFileSize', min(200, $phpMaxMb))
|
|
->set('maxStorageQuota', 50)
|
|
->set('maxFilesPerShare', 100)
|
|
->set('maxSizePerShare', 5)
|
|
->set('defaultExpiration', '7d')
|
|
->call('saveSettings')
|
|
->assertHasNoErrors()
|
|
->assertDispatched('toast', type: 'success', title: 'Settings saved successfully.');
|
|
|
|
expect(Setting::get('max_file_size'))->toBe((string) (min(200, $phpMaxMb) * 1024 * 1024));
|
|
expect(Setting::get('max_storage_quota'))->toBe((string) (50 * 1024 * 1024 * 1024));
|
|
expect(Setting::get('max_files_per_share'))->toBe('100');
|
|
expect(Setting::get('max_size_per_share'))->toBe((string) (5 * 1024 * 1024 * 1024));
|
|
expect(Setting::get('default_expiration'))->toBe('7d');
|
|
});
|
|
|
|
test('admin can set system password', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
$phpMaxMb = AdminSettings::phpMaxUploadMb();
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->set('maxFileSize', $phpMaxMb)
|
|
->set('systemPassword', 'new-system-password')
|
|
->call('saveSettings')
|
|
->assertHasNoErrors();
|
|
|
|
$storedPassword = Setting::get('system_password');
|
|
expect($storedPassword)->not->toBeNull();
|
|
expect(Hash::check('new-system-password', $storedPassword))->toBeTrue();
|
|
});
|
|
|
|
test('admin can clear system password', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
|
|
Setting::set('system_password', bcrypt('existing-password'));
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->set('confirmingPasswordRemoval', true)
|
|
->call('clearSystemPassword')
|
|
->assertHasNoErrors()
|
|
->assertSet('confirmingPasswordRemoval', false)
|
|
->assertDispatched('toast', type: 'success', title: 'System password cleared.');
|
|
|
|
expect(Setting::get('system_password'))->toBeNull();
|
|
});
|
|
|
|
test('settings page loads existing values', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
$phpMaxMb = AdminSettings::phpMaxUploadMb();
|
|
$testSize = min(40, $phpMaxMb);
|
|
|
|
Setting::set('max_file_size', $testSize * 1024 * 1024);
|
|
Setting::set('max_files_per_share', 75);
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->assertSet('maxFileSize', $testSize)
|
|
->assertSet('maxFilesPerShare', 75);
|
|
});
|
|
|
|
test('settings validation rejects invalid values', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->set('maxFileSize', 0)
|
|
->set('maxStorageQuota', 0)
|
|
->call('saveSettings')
|
|
->assertHasErrors(['maxFileSize', 'maxStorageQuota']);
|
|
});
|
|
|
|
test('admin can remove the logo through its dialog', function () {
|
|
Storage::fake('public');
|
|
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
$path = UploadedFile::fake()->image('logo.png')->store('branding', 'public');
|
|
Setting::set('site_logo', $path);
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->assertSeeHtml('data-test="remove-logo"')
|
|
->set('confirmingLogoRemoval', true)
|
|
->call('removeLogo')
|
|
->assertSet('confirmingLogoRemoval', false)
|
|
->assertDispatched('toast', type: 'success', title: 'Logo removed.');
|
|
|
|
expect(Setting::get('site_logo'))->toBeNull();
|
|
Storage::disk('public')->assertMissing($path);
|
|
});
|
|
|
|
test('admin chooses the colour profile, starting from the saved one', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->assertSet('colorProfile', 'indigo')
|
|
->set('colorProfile', 'teal')
|
|
->call('saveSettings')
|
|
->assertHasNoErrors();
|
|
|
|
expect(Setting::get('color_profile'))->toBe('teal');
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->assertSet('colorProfile', 'teal');
|
|
});
|
|
|
|
test('a colour profile that was not generated is refused', function () {
|
|
$admin = User::query()->where('is_admin', true)->first();
|
|
|
|
Livewire::actingAs($admin)
|
|
->test(AdminSettings::class)
|
|
->set('colorProfile', 'ocean')
|
|
->call('saveSettings')
|
|
->assertHasErrors(['colorProfile' => 'in']);
|
|
|
|
expect(Setting::get('color_profile'))->toBeNull();
|
|
});
|