fix(ui): normalize S3 endpoints and remove duplicate config warnings

Normalize endpoints on blur and submit, link internal-target errors to settings, and target the S3 submit loading state.
This commit is contained in:
Andras Bacsai committed 2026-08-14 18:48:34 +02:00
1 parent a257224bb7
commit b3789d4a36
9 files changed
+127 -31

No files matched your search

+6
View File
@@ -30,6 +30,12 @@ it('uses an explicit wire target for submit buttons without wire click', functio
->toContain('Validate and add');
});
it('targets the S3 connection validation submit action', function () {
$view = file_get_contents(resource_path('views/livewire/storage/create.blade.php'));
expect($view)->toContain('<x-forms.button class="mt-4" type="submit" wire:target="submit">');
});
it('keeps method arguments when deriving the loading target', function () {
$html = Blade::render(
'<x-forms.button wire:click="setPrivateKey(42)">Use this key</x-forms.button>'
@@ -334,6 +334,32 @@ it('renders configuration warnings as navbar popovers instead of floating notifi
->toContain("\$dispatch('open-configuration-diff')");
});
it('renders only one configuration warning on database runtime logs', function () {
$logs = file_get_contents(resource_path('views/livewire/project/shared/logs.blade.php'));
$databaseHeading = file_get_contents(resource_path('views/livewire/project/database/heading.blade.php'));
expect($logs)
->not->toContain(" <livewire:project.shared.configuration-checker :resource=\"\$resource\" />\n\n @if (\$type === 'application')")
->and($databaseHeading)
->toContain('<livewire:project.shared.configuration-checker :resource="$database" />');
});
it('renders only one configuration warning on database and service terminal pages', function () {
$terminal = file_get_contents(resource_path('views/livewire/project/shared/execute-container-command.blade.php'));
expect($terminal)
->not->toContain("@elseif (\$type === 'database')\n <livewire:project.shared.configuration-checker :resource=\"\$resource\" />")
->not->toContain("@elseif (\$type === 'service')\n <livewire:project.shared.configuration-checker :resource=\"\$resource\" />");
});
it('renders only one configuration warning on the service volume backups page', function () {
$volumeBackups = file_get_contents(resource_path('views/livewire/project/service/volume-backup/index.blade.php'));
expect($volumeBackups)
->not->toContain('<livewire:project.shared.configuration-checker :resource="$service" />')
->toContain('<livewire:project.service.heading :service="$service"');
});
it('moves application backups from the top tabs into the settings sidebar', function () {
$heading = file_get_contents(resource_path('views/livewire/project/application/heading.blade.php'));
$configuration = file_get_contents(resource_path('views/livewire/project/application/configuration.blade.php'));
@@ -0,0 +1,16 @@
<?php
use App\Livewire\Storage\Create;
it('formats the internal target settings route as a clickable link', function () {
$settingsUrl = route('settings.advanced').'#endpoint-section';
$exception = new RuntimeException("Private target. Configure allowed internal targets: {$settingsUrl}");
$method = new ReflectionMethod(Create::class, 'connectionErrorDescription');
$description = $method->invoke(new Create, $exception);
expect($description)
->toContain('href="'.$settingsUrl.'"')
->toContain('Set them here.')
->not->toContain('targets: '.$settingsUrl);
});
@@ -0,0 +1,29 @@
<?php
use App\Livewire\Storage\Create;
use Tests\TestCase;
uses(TestCase::class);
it('normalizes S3 endpoints without a Livewire blur request', function () {
$view = file_get_contents(resource_path('views/livewire/storage/create.blade.php'));
expect($view)
->not->toContain('wire:model.blur="endpoint"')
->toContain('x-on:blur')
->toContain('const hasScheme')
->toContain('dispatchEvent');
});
it('normalizes endpoints again on the backend', function (string $endpoint, string $expected) {
$method = new ReflectionMethod(Create::class, 'normalizeEndpoint');
expect($method->invoke(new Create, $endpoint))->toBe($expected);
})->with([
'missing scheme' => ['s3.example.com', 'https://s3.example.com'],
'existing HTTP scheme' => ['http://192.168.1.50:9000', 'http://192.168.1.50:9000'],
'malformed HTTP scheme' => ['http:/192.168.1.50:9000', 'http:/192.168.1.50:9000'],
'hostname with port' => ['minio.internal:9000', 'https://minio.internal:9000'],
'unsupported scheme' => ['ftp://s3.example.com', 'ftp://s3.example.com'],
'DigitalOcean bucket endpoint' => ['https://bucket.nyc3.digitaloceanspaces.com', 'https://nyc3.digitaloceanspaces.com'],
]);