TenantAtlas/apps/platform/tests/Feature/Filament/TenantRegistryArrivalContextTest.php
ahmido e64bae9cfc feat: cut over tenant core to managed environments (#335)
## Summary
- replace the legacy Tenant and TenantMembership core models with ManagedEnvironment and ManagedEnvironmentMembership
- propagate the managed environment naming and key changes across Filament resources, pages, controllers, jobs, models, and supporting runtime paths
- add feature 279 spec artifacts and focused managed-environment test coverage for model behavior, route binding, panel context, authorization, and legacy guardrails

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ManagedEnvironment/LegacyTenantCoreGuardTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentAuthorizationTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentPanelContextTest.php tests/Feature/ManagedEnvironment/ManagedEnvironmentRouteBindingTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentContextResolverTest.php tests/Unit/ManagedEnvironment/ManagedEnvironmentModelTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`

## Notes
- branch pushed from commit `1123b122`
- browser smoke test file was added but not run in this pass

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #335
2026-05-07 06:38:14 +00:00

95 lines
4.5 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\TenantDashboard;
use App\Filament\Resources\TenantResource;
use App\Support\BackupHealth\TenantBackupHealthAssessment;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\RestoreSafety\RestoreResultAttention;
use App\Support\Tenants\TenantRecoveryTriagePresentation;
use Tests\Feature\Concerns\BuildsPortfolioTriageFixtures;
uses(BuildsPortfolioTriageFixtures::class);
function tenantRegistryArrivalStateFromUrl(string $url): ?array
{
parse_str((string) parse_url($url, PHP_URL_QUERY), $query);
return PortfolioArrivalContextToken::decode($query[PortfolioArrivalContextToken::QUERY_PARAMETER] ?? null);
}
it('adds arrival context and bounded return state to triage-driven tenant opens', function (): void {
[$user, $anchorTenant] = $this->makePortfolioTriageActor('Anchor ManagedEnvironment');
$weakenedTenant = $this->makePortfolioTriagePeer($user, $anchorTenant, 'Weakened ManagedEnvironment');
$backupSet = $this->seedPortfolioBackupConcern($weakenedTenant, TenantBackupHealthAssessment::POSTURE_STALE);
$this->seedPortfolioRecoveryConcern($weakenedTenant, RestoreResultAttention::STATE_COMPLETED_WITH_FOLLOW_UP, $backupSet);
$triageState = [
'backup_posture' => [TenantBackupHealthAssessment::POSTURE_STALE],
'recovery_evidence' => [TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED],
'triage_sort' => TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST,
];
$this->usePortfolioTriageWorkspace($user, $anchorTenant);
$expectedUrl = TenantResource::tenantDashboardOpenUrl($weakenedTenant, $triageState);
$this->portfolioTriageRegistryList($user, $anchorTenant, $triageState)
->assertTableActionHasUrl('openTenant', $expectedUrl, $weakenedTenant);
expect(tenantRegistryArrivalStateFromUrl($expectedUrl))->toMatchArray([
'sourceSurface' => PortfolioArrivalContextToken::SOURCE_TENANT_REGISTRY,
'tenantRouteKey' => (string) $weakenedTenant->external_id,
'workspaceId' => (int) $weakenedTenant->workspace_id,
'concernFamily' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
'concernState' => TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED,
'concernReason' => RestoreResultAttention::STATE_COMPLETED_WITH_FOLLOW_UP,
'returnFilters' => [
'backup_posture' => [TenantBackupHealthAssessment::POSTURE_STALE],
'recovery_evidence' => [TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED],
'triage_sort' => TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST,
],
]);
});
it('keeps generic registry opens free of arrival context when triage intent is not active', function (): void {
[$user, $tenant] = $this->makePortfolioTriageActor('Generic Registry ManagedEnvironment');
$expectedUrl = TenantDashboard::getUrl(panel: 'tenant', tenant: $tenant);
$this->usePortfolioTriageWorkspace($user, $tenant);
$this->get(TenantResource::getUrl('index', panel: 'admin'))
->assertOk()
->assertSee($expectedUrl, false);
expect($expectedUrl)->not->toContain(PortfolioArrivalContextToken::QUERY_PARAMETER.'=');
});
it('chooses the leading visible concern when worst-first triage is active without explicit family filters', function (): void {
[$user, $anchorTenant] = $this->makePortfolioTriageActor('Worst First Anchor');
$priorityTenant = $this->makePortfolioTriagePeer($user, $anchorTenant, 'Priority ManagedEnvironment');
$this->seedPortfolioBackupConcern($priorityTenant, TenantBackupHealthAssessment::POSTURE_STALE);
$this->seedPortfolioRecoveryConcern($priorityTenant, RestoreResultAttention::STATE_PARTIAL);
$this->usePortfolioTriageWorkspace($user, $anchorTenant);
$expectedUrl = TenantResource::tenantDashboardOpenUrl($priorityTenant, [
'triage_sort' => TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST,
]);
$this->portfolioTriageRegistryList($user, $anchorTenant, [
'triage_sort' => TenantRecoveryTriagePresentation::TRIAGE_SORT_WORST_FIRST,
])
->assertTableActionHasUrl('openTenant', $expectedUrl, $priorityTenant);
expect(tenantRegistryArrivalStateFromUrl($expectedUrl))->toMatchArray([
'sourceSurface' => PortfolioArrivalContextToken::SOURCE_TENANT_REGISTRY,
'concernFamily' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
'concernState' => TenantRecoveryTriagePresentation::RECOVERY_EVIDENCE_WEAKENED,
'concernReason' => RestoreResultAttention::STATE_PARTIAL,
]);
});