166 lines
5.4 KiB
PHP
166 lines
5.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Concerns;
|
|
|
|
use App\Filament\Resources\TenantResource\Pages\ListTenants;
|
|
use App\Models\BackupSet;
|
|
use App\Models\RestoreRun;
|
|
use App\Models\Tenant;
|
|
use App\Models\User;
|
|
use App\Support\BackupHealth\TenantBackupHealthAssessment;
|
|
use App\Support\RestoreSafety\RestoreResultAttention;
|
|
use App\Support\Tenants\TenantRecoveryTriagePresentation;
|
|
use App\Support\Workspaces\WorkspaceContext;
|
|
use Filament\Facades\Filament;
|
|
use Livewire\Livewire;
|
|
|
|
trait BuildsPortfolioTriageFixtures
|
|
{
|
|
/**
|
|
* @return array{0: User, 1: Tenant}
|
|
*/
|
|
protected function makePortfolioTriageActor(
|
|
string $tenantName = 'Anchor Tenant',
|
|
string $role = 'owner',
|
|
string $workspaceRole = 'readonly',
|
|
): array {
|
|
$tenant = Tenant::factory()->create([
|
|
'status' => 'active',
|
|
'name' => $tenantName,
|
|
]);
|
|
|
|
[$user, $tenant] = createUserWithTenant(
|
|
tenant: $tenant,
|
|
role: $role,
|
|
workspaceRole: $workspaceRole,
|
|
);
|
|
|
|
workspaceOverviewSeedQuietTenantTruth($tenant);
|
|
|
|
return [$user, $tenant];
|
|
}
|
|
|
|
protected function makePortfolioTriagePeer(User $user, Tenant $workspaceTenant, string $name): Tenant
|
|
{
|
|
$tenant = Tenant::factory()->create([
|
|
'status' => 'active',
|
|
'workspace_id' => (int) $workspaceTenant->workspace_id,
|
|
'name' => $name,
|
|
]);
|
|
|
|
createUserWithTenant(
|
|
tenant: $tenant,
|
|
user: $user,
|
|
role: 'owner',
|
|
workspaceRole: 'readonly',
|
|
);
|
|
|
|
workspaceOverviewSeedQuietTenantTruth($tenant);
|
|
|
|
return $tenant;
|
|
}
|
|
|
|
protected function seedPortfolioBackupConcern(Tenant $tenant, string $state): ?BackupSet
|
|
{
|
|
return match ($state) {
|
|
TenantBackupHealthAssessment::POSTURE_ABSENT => null,
|
|
TenantBackupHealthAssessment::POSTURE_STALE => BackupSet::factory()
|
|
->for($tenant)
|
|
->staleCompleted()
|
|
->create([
|
|
'name' => 'Portfolio stale backup',
|
|
]),
|
|
TenantBackupHealthAssessment::POSTURE_DEGRADED => BackupSet::factory()
|
|
->for($tenant)
|
|
->degradedCompleted()
|
|
->create([
|
|
'name' => 'Portfolio degraded backup',
|
|
]),
|
|
default => workspaceOverviewSeedHealthyBackup($tenant, [
|
|
'name' => 'Portfolio healthy backup',
|
|
]),
|
|
};
|
|
}
|
|
|
|
protected function seedPortfolioRecoveryConcern(
|
|
Tenant $tenant,
|
|
string $reason = 'no_history',
|
|
?BackupSet $backupSet = null,
|
|
): ?RestoreRun {
|
|
$backupSet ??= workspaceOverviewSeedHealthyBackup($tenant, [
|
|
'name' => 'Portfolio recovery backup',
|
|
]);
|
|
|
|
return match ($reason) {
|
|
'no_history' => null,
|
|
RestoreResultAttention::STATE_FAILED => RestoreRun::factory()
|
|
->for($tenant)
|
|
->for($backupSet)
|
|
->failedOutcome()
|
|
->create([
|
|
'completed_at' => now()->subMinutes(10),
|
|
]),
|
|
RestoreResultAttention::STATE_PARTIAL => RestoreRun::factory()
|
|
->for($tenant)
|
|
->for($backupSet)
|
|
->partialOutcome()
|
|
->create([
|
|
'completed_at' => now()->subMinutes(10),
|
|
]),
|
|
RestoreResultAttention::STATE_COMPLETED_WITH_FOLLOW_UP => RestoreRun::factory()
|
|
->for($tenant)
|
|
->for($backupSet)
|
|
->completedWithFollowUp()
|
|
->create([
|
|
'completed_at' => now()->subMinutes(10),
|
|
]),
|
|
default => RestoreRun::factory()
|
|
->for($tenant)
|
|
->for($backupSet)
|
|
->completedOutcome()
|
|
->create([
|
|
'completed_at' => now()->subMinutes(10),
|
|
]),
|
|
};
|
|
}
|
|
|
|
protected function usePortfolioTriageWorkspace(User $user, Tenant $tenant): void
|
|
{
|
|
test()->actingAs($user);
|
|
session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
|
|
Filament::setTenant(null, true);
|
|
request()->attributes->remove('tenant_resource.posture_snapshot');
|
|
session()->forget('tables.'.md5(ListTenants::class).'_filters');
|
|
session()->forget('tables.'.md5(ListTenants::class).'_search');
|
|
session()->forget('tables.'.md5(ListTenants::class).'_sort');
|
|
}
|
|
|
|
protected function portfolioTriageRegistryList(User $user, Tenant $workspaceTenant, array $query = []): mixed
|
|
{
|
|
$this->usePortfolioTriageWorkspace($user, $workspaceTenant);
|
|
|
|
$factory = $query !== []
|
|
? Livewire::withQueryParams($query)->actingAs($user)
|
|
: Livewire::actingAs($user);
|
|
|
|
return $factory->test(ListTenants::class);
|
|
}
|
|
|
|
/**
|
|
* @return array{backup_posture: list<string>, recovery_evidence: list<string>, triage_sort: string|null}
|
|
*/
|
|
protected function portfolioReturnFilters(
|
|
array $backupPosture = [],
|
|
array $recoveryEvidence = [],
|
|
?string $triageSort = TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST,
|
|
): array {
|
|
return [
|
|
'backup_posture' => $backupPosture,
|
|
'recovery_evidence' => $recoveryEvidence,
|
|
'triage_sort' => $triageSort,
|
|
];
|
|
}
|
|
}
|