TenantAtlas/apps/platform/tests/Feature/Navigation/Spec341CanonicalLinkQueryCleanupTest.php
ahmido e324bd7bd6 feat: canonicalize admin scope links and queries (341) (#413)
## Summary
- remove remaining legacy scope query hint parsing from shared workspace and environment scoping seams so hubs only narrow via explicit `environment_id`
- align canonical link generation across workspace hubs, provider connections, audit log, alerts, and decision register flows
- add focused Spec 341 regression coverage for canonical link/query behavior and legacy alias rejection
- include the Spec 341 artifacts and move the review screenshots into `specs/341-canonical-link-query-cleanup/artifacts/screenshots/`
- ignore local `.playwright-mcp` browser tool output so it does not pollute future commits or pull requests

## Validation
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Navigation --filter=Spec341`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Navigation/Spec341CanonicalLinkQueryCleanupTest.php tests/Feature/Navigation/WorkspaceHubEnvironmentFilterContractTest.php tests/Feature/ProviderConnections/ProviderConnectionsWorkspaceHubContractTest.php`
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `git diff --check`

## Notes
- Livewire v4 compliance unchanged
- Filament provider registration remains in `apps/platform/bootstrap/providers.php`
- no globally searchable resource behavior was changed in this slice
- no destructive action behavior was changed
- no new Filament assets; deploy `filament:assets` posture is unchanged

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #413
2026-05-31 22:46:39 +00:00

131 lines
5.2 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\EnvironmentRequiredPermissions;
use App\Models\ManagedEnvironment;
use App\Support\ManagedEnvironmentLinks;
use App\Support\Navigation\WorkspaceHubNavigation;
use App\Support\OperateHub\OperateHubShell;
use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament;
use Illuminate\Http\Request;
it('Spec341 OperateHubShell ignores legacy tenant query hints', function (): void {
$environment = ManagedEnvironment::factory()->active()->create([
'name' => 'Spec341 Environment A',
'external_id' => 'spec341-environment-a',
]);
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'owner');
$workspace = $environment->workspace()->firstOrFail();
$this->actingAs($user);
setAdminPanelContext();
session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
session()->forget(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY);
$shell = app(OperateHubShell::class);
$queryCases = [
'tenant' => ['tenant' => (string) $environment->getRouteKey()],
'managed_environment_id' => ['managed_environment_id' => (int) $environment->getKey()],
];
foreach ($queryCases as $query) {
$request = Request::create('/admin/onboarding', 'GET', $query);
$request->setUserResolver(fn () => $user);
$resolved = $shell->resolvedContext($request);
expect($resolved->hasTenant())->toBeFalse()
->and($resolved->tenantSource)->not->toBe('query_hint');
}
});
it('Spec341 EnvironmentRequiredPermissions does not resolve tenant from legacy query keys', function (): void {
$environment = ManagedEnvironment::factory()->active()->create([
'name' => 'Spec341 Permissions Environment',
'external_id' => 'spec341-permissions-environment',
]);
$originalRequest = app('request');
try {
$request = Request::create('/livewire/update', 'GET', [
'tenant' => (string) $environment->getRouteKey(),
]);
app()->instance('request', $request);
$method = new ReflectionMethod(EnvironmentRequiredPermissions::class, 'resolveScopedTenant');
$method->setAccessible(true);
/** @var ManagedEnvironment|null $resolvedTenant */
$resolvedTenant = $method->invoke(null, null);
expect($resolvedTenant)->toBeNull();
} finally {
app()->instance('request', $originalRequest);
}
});
it('Spec341 environment-bound routes remain route-owned even when legacy tenant query hints are present', function (): void {
$environmentA = ManagedEnvironment::factory()->active()->create([
'name' => 'Spec341 Baseline Environment A',
'external_id' => 'spec341-baseline-environment-a',
]);
[$user, $environmentA] = createUserWithTenant(tenant: $environmentA, role: 'owner', workspaceRole: 'owner');
$environmentB = ManagedEnvironment::factory()->active()->create([
'workspace_id' => (int) $environmentA->workspace_id,
'name' => 'Spec341 Baseline Environment B',
'external_id' => 'spec341-baseline-environment-b',
]);
createUserWithTenant(tenant: $environmentB, user: $user, role: 'owner', workspaceRole: 'owner');
$this->actingAs($user);
setAdminPanelContext();
session()->put(WorkspaceContext::SESSION_KEY, (int) $environmentA->workspace_id);
baselineCompareLandingLivewire($environmentB, ['tenant' => (string) $environmentA->getRouteKey()], $user)
->assertSet('scopedEnvironmentId', (int) $environmentB->getKey());
});
it('Spec341 WorkspaceHubNavigation carries route-owned environment context into workspace hub URLs', function (): void {
$environment = ManagedEnvironment::factory()->active()->create([
'name' => 'Spec341 Hub Navigation Environment',
'external_id' => 'spec341-hub-navigation-environment',
]);
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'owner');
$workspace = $environment->workspace()->firstOrFail();
$this->actingAs($user);
setAdminPanelContext();
Filament::setTenant(null, true);
session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey());
session()->forget(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY);
$originalRequest = app('request');
try {
$workspaceKey = ManagedEnvironmentLinks::workspaceRouteKey($workspace);
$environmentKey = ManagedEnvironmentLinks::environmentRouteKey($environment);
$request = Request::create('/livewire/update', 'POST');
$request->headers->set('x-livewire', '1');
$request->headers->set('referer', url("/admin/workspaces/{$workspaceKey}/environments/{$environmentKey}/required-permissions"));
$request->setUserResolver(fn () => $user);
app()->instance('request', $request);
$url = WorkspaceHubNavigation::environmentFilteredUrl(url('/admin/provider-connections'));
$query = [];
parse_str((string) parse_url($url, PHP_URL_QUERY), $query);
expect((int) ($query['environment_id'] ?? 0))->toBe((int) $environment->getKey());
} finally {
app()->instance('request', $originalRequest);
}
});