## Summary - harden nested Filament and Livewire tenant-context handling across the backup schedule operation runs relation manager, managed-environment triage arrival continuity, the backup set policy picker table, and the Operate Hub shell - add architecture, feature, and browser coverage for nested Filament tenant-context continuity and restore-run resource behavior - add the Spec 334 artifacts (`spec.md`, `plan.md`, `tasks.md`, and the requirements checklist) ## Testing - Not run as part of this commit/push/PR workflow Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #395
91 lines
2.6 KiB
PHP
91 lines
2.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Filament\Resources\RestoreRunResource;
|
|
use App\Models\BackupSet;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function (): void {
|
|
Http::preventStrayRequests();
|
|
});
|
|
|
|
it('does not crash when restore create wizard Livewire update loses route parameters', function (): void {
|
|
[$user, $tenant] = createMinimalUserWithTenant(role: 'owner');
|
|
|
|
$this->actingAs($user);
|
|
|
|
BackupSet::factory()->create([
|
|
'managed_environment_id' => (int) $tenant->getKey(),
|
|
'name' => 'Restore fixture backup set',
|
|
]);
|
|
|
|
$createUrl = RestoreRunResource::getUrl('create', panel: 'admin', tenant: $tenant);
|
|
|
|
$response = $this
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
|
->get($createUrl);
|
|
|
|
$response->assertSuccessful();
|
|
|
|
$html = (string) $response->getContent();
|
|
|
|
preg_match_all('/wire:snapshot="([^"]+)"/', $html, $snapshotMatches);
|
|
|
|
$snapshots = $snapshotMatches[1] ?? [];
|
|
|
|
expect($snapshots)->not->toBeEmpty('No Livewire snapshot found in restore create HTML');
|
|
|
|
$expectedPath = sprintf(
|
|
'admin/workspaces/%s/environments/%s/restore-runs/create',
|
|
$tenant->workspace_id,
|
|
$tenant->getRouteKey(),
|
|
);
|
|
|
|
$snapshotJson = null;
|
|
|
|
foreach ($snapshots as $encodedSnapshot) {
|
|
$candidateJson = htmlspecialchars_decode($encodedSnapshot);
|
|
$candidate = json_decode($candidateJson, true);
|
|
|
|
if (! is_array($candidate)) {
|
|
continue;
|
|
}
|
|
|
|
if (($candidate['memo']['path'] ?? null) === $expectedPath) {
|
|
$snapshotJson = $candidateJson;
|
|
break;
|
|
}
|
|
}
|
|
|
|
expect($snapshotJson)->toBeString("No snapshot with memo.path [$expectedPath] found.");
|
|
|
|
$updatePayload = [
|
|
'components' => [[
|
|
'snapshot' => $snapshotJson,
|
|
'updates' => new stdClass,
|
|
'calls' => [],
|
|
]],
|
|
];
|
|
|
|
$updateUri = '/'.collect(app('router')->getRoutes()->getRoutes())
|
|
->first(fn ($route): bool => str_contains((string) $route->getName(), 'livewire.update'))
|
|
?->uri();
|
|
|
|
expect($updateUri)->toBeString('Livewire update route must exist');
|
|
|
|
$updateResponse = $this
|
|
->withSession([WorkspaceContext::SESSION_KEY => (int) $tenant->workspace_id])
|
|
->withHeaders([
|
|
'X-Livewire' => 'true',
|
|
'Referer' => $createUrl,
|
|
])
|
|
->postJson($updateUri, $updatePayload);
|
|
|
|
$updateResponse->assertSuccessful();
|
|
});
|