fix(storage): split S3 endpoint input and persist stopped status

Persist exited status across application, database, service, and preview stop paths, and reuse the split host/port/path input for S3 endpoints with linked validation feedback.
This commit is contained in:
Andras Bacsai committed 2026-08-15 11:46:49 +02:00
1 parent ec8a24d178
commit 2677e47138
12 files changed
+132 -30

No files matched your search

+39
View File
@@ -0,0 +1,39 @@
<?php
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\Facades\View;
use Illuminate\Support\MessageBag;
use Illuminate\Support\ViewErrorBag;
it('renders configurable host copy for S3 endpoints', function () {
View::share('errors', new ViewErrorBag);
$html = Blade::render(<<<'BLADE'
<x-forms.domain-input id="endpoint" :wire="false" value="http://192.168.1.50:9000/s3"
host-label="Host" host-placeholder="minio.internal or 192.168.1.50" />
BLADE);
expect($html)
->toContain('Host')
->toContain('minio.internal or 192.168.1.50')
->toContain("scheme: 'https'")
->toContain("host: ''")
->toContain("port: ''")
->toContain("path: ''");
});
it('keeps validation errors attached to the composed endpoint', function () {
$settingsUrl = route('settings.advanced').'#endpoint-section';
$errors = new ViewErrorBag;
$errors->put('default', new MessageBag([
'endpoint' => "The endpoint is invalid. Configure allowed internal targets: {$settingsUrl}",
]));
View::share('errors', $errors);
$html = Blade::render('<x-forms.domain-input id="endpoint" :wire="false" />');
expect($html)
->toContain('The endpoint is invalid.')
->toContain('href="'.$settingsUrl.'"')
->toContain('Set them here.');
});
@@ -5,14 +5,18 @@ 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'));
it('uses the shared split URL input without a Livewire blur request', function () {
$createView = file_get_contents(resource_path('views/livewire/storage/create.blade.php'));
$editView = file_get_contents(resource_path('views/livewire/storage/form.blade.php'));
expect($view)
expect($createView)
->not->toContain('wire:model.blur="endpoint"')
->toContain('x-on:blur')
->toContain('const hasScheme')
->toContain('dispatchEvent');
->toContain('<x-forms.domain-input id="endpoint"')
->toContain('host-label="Host"')
->toContain('host-placeholder="minio.internal or 192.168.1.50"')
->and($editView)
->toContain('<x-forms.domain-input id="endpoint"')
->toContain('@can(\'update\', $storage)');
});
it('normalizes endpoints again on the backend', function (string $endpoint, string $expected) {
@@ -0,0 +1,40 @@
<?php
it('persists exited status when stopping standalone databases', function () {
$action = file_get_contents(__DIR__.'/../../app/Actions/Database/StopDatabase.php');
expect($action)->toContain("'status' => 'exited'");
});
it('persists exited status for every full application stop path', function () {
$action = file_get_contents(__DIR__.'/../../app/Actions/Application/StopApplication.php');
expect($action)
->toContain("\$status = ['status' => 'exited'];")
->toContain('$application->update($status);')
->not->toMatch('/docker stack rm .*?return;/s');
});
it('persists exited status for all children when stopping a service', function () {
$action = file_get_contents(__DIR__.'/../../app/Actions/Service/StopService.php');
expect($action)
->toContain("\$applications->each->update(['status' => 'exited']);")
->toContain("\$dbs->each->update(['status' => 'exited']);");
});
it('persists exited status when stopping an individual service resource', function () {
$action = file_get_contents(__DIR__.'/../../app/Actions/Service/StopServiceApplication.php');
expect($action)
->toContain("\$serviceApplication->update(['status' => 'exited']);")
->toContain('ServiceStatusChanged::dispatch($service->environment->project->team->id);');
});
it('persists exited status when stopping a preview deployment', function () {
$component = file_get_contents(__DIR__.'/../../app/Livewire/Project/Application/Previews.php');
expect($component)
->toContain("->update(['status' => 'exited']);")
->toContain('ServiceStatusChanged::dispatch($this->application->environment->project->team->id);');
});