TenantAtlas/apps/platform/tests/Feature/Filament/WorkspaceOverviewArrivalContextTest.php
ahmido 3ec582a182 feat: retire legacy tenant route surfaces (#352)
## Summary
- retire legacy `/admin/t` and active `/admin/tenants` product surfaces in favor of canonical workspace-scoped managed-environment routes
- centralize runtime URL generation through `ManagedEnvironmentLinks` and update intended URL handling to reject legacy tenant paths
- remove dormant tenant panel runtime, rename test helpers to the admin environment context, and add guard coverage for route/helper regressions

## Validation
- targeted Feature guard, workspace, provider connection, required permissions, and Filament test lanes run under Sail
- browser smoke coverage run for provider connection and workspace RBAC environment access flows
- formatting and diff checks completed with Pint and `git diff --check`

## Notes
- Filament remains on v5 with Livewire v4
- provider registration stays in `apps/platform/bootstrap/providers.php`
- retired tenant resource global search is disabled and destructive action confirmation rules remain unchanged

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #352
2026-05-12 23:35:03 +00:00

74 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Support\BackupHealth\TenantBackupHealthAssessment;
use App\Support\PortfolioTriage\PortfolioArrivalContextToken;
use App\Support\RestoreSafety\RestoreResultAttention;
use App\Support\Workspaces\WorkspaceOverviewBuilder;
use Tests\Feature\Concerns\BuildsPortfolioTriageFixtures;
uses(BuildsPortfolioTriageFixtures::class);
function workspaceOverviewArrivalStateFromUrl(string $url): ?array
{
parse_str((string) parse_url($url, PHP_URL_QUERY), $query);
return PortfolioArrivalContextToken::decode($query[PortfolioArrivalContextToken::QUERY_PARAMETER] ?? null);
}
it('emits bounded arrival tokens for workspace backup and recovery attention drilldowns', function (): void {
[$user, $backupTenant] = $this->makePortfolioTriageActor('Backup Weak ManagedEnvironment');
$recoveryTenant = $this->makePortfolioTriagePeer($user, $backupTenant, 'Recovery Weak ManagedEnvironment');
$this->seedPortfolioRecoveryConcern($recoveryTenant, RestoreResultAttention::STATE_COMPLETED_WITH_FOLLOW_UP);
$workspace = $backupTenant->workspace()->firstOrFail();
$items = collect(app(WorkspaceOverviewBuilder::class)->build($workspace, $user)['attention_items'])->keyBy('key');
$backupArrivalState = workspaceOverviewArrivalStateFromUrl((string) $items->get('tenant_backup_absent')['destination']['url']);
$recoveryArrivalState = workspaceOverviewArrivalStateFromUrl((string) $items->get('tenant_recovery_weakened')['destination']['url']);
expect($backupArrivalState)->toMatchArray([
'sourceSurface' => PortfolioArrivalContextToken::SOURCE_WORKSPACE_OVERVIEW,
'tenantRouteKey' => (string) $backupTenant->external_id,
'workspaceId' => (int) $backupTenant->workspace_id,
'concernFamily' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
'concernState' => TenantBackupHealthAssessment::POSTURE_ABSENT,
'concernReason' => TenantBackupHealthAssessment::REASON_NO_BACKUP_BASIS,
])->and($recoveryArrivalState)->toMatchArray([
'sourceSurface' => PortfolioArrivalContextToken::SOURCE_WORKSPACE_OVERVIEW,
'tenantRouteKey' => (string) $recoveryTenant->external_id,
'workspaceId' => (int) $recoveryTenant->workspace_id,
'concernFamily' => PortfolioArrivalContextToken::FAMILY_RECOVERY_EVIDENCE,
'concernState' => 'weakened',
'concernReason' => RestoreResultAttention::STATE_COMPLETED_WITH_FOLLOW_UP,
]);
});
it('emits summary-metric arrival tokens only when the workspace drilldown lands on a single tenant dashboard', function (): void {
[$user, $backupTenant] = $this->makePortfolioTriageActor('Single Backup ManagedEnvironment');
$recoveryTenantA = $this->makePortfolioTriagePeer($user, $backupTenant, 'Recovery ManagedEnvironment A');
$this->seedPortfolioRecoveryConcern($recoveryTenantA, RestoreResultAttention::STATE_FAILED);
$recoveryTenantB = $this->makePortfolioTriagePeer($user, $backupTenant, 'Recovery ManagedEnvironment B');
$this->seedPortfolioRecoveryConcern($recoveryTenantB, RestoreResultAttention::STATE_PARTIAL);
$workspace = $backupTenant->workspace()->firstOrFail();
$metrics = collect(app(WorkspaceOverviewBuilder::class)->build($workspace, $user)['summary_metrics'])->keyBy('key');
$backupDestinationUrl = (string) $metrics->get('backup_attention_tenants')['destination_url'];
$recoveryDestinationUrl = (string) $metrics->get('recovery_attention_tenants')['destination_url'];
$backupArrivalState = workspaceOverviewArrivalStateFromUrl($backupDestinationUrl);
expect($backupArrivalState)->toMatchArray([
'sourceSurface' => PortfolioArrivalContextToken::SOURCE_WORKSPACE_OVERVIEW,
'tenantRouteKey' => (string) $backupTenant->external_id,
'concernFamily' => PortfolioArrivalContextToken::FAMILY_BACKUP_HEALTH,
'concernState' => TenantBackupHealthAssessment::POSTURE_ABSENT,
])->and($recoveryDestinationUrl)->toContain('/admin/workspaces/')
->and($recoveryDestinationUrl)->toContain('/environments')
->and($recoveryDestinationUrl)->not->toContain(PortfolioArrivalContextToken::QUERY_PARAMETER.'=');
});