TenantAtlas/apps/platform/tests/Feature/Governance/DecisionRegisterWorkspaceHubContractTest.php
ahmido d85ef4cc1c Spec 314: enforce workspace hub navigation context contract (#369)
## Summary
- add a shared workspace hub registry for canonical workspace-scoped navigation entry
- keep sidebar and global workspace hub URLs free of inherited environment query and filter state
- add focused feature and browser coverage for workspace hub shell and data-scope contracts

## Validation
- 54 focused feature tests passed (205 assertions)
- 1 browser smoke test passed (361 assertions)
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `git diff --check`

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #369
2026-05-16 09:54:29 +00:00

76 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
use App\Filament\Pages\Governance\DecisionRegister;
use App\Models\Finding;
use App\Models\FindingException;
use App\Models\FindingExceptionDecision;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Workspaces\WorkspaceContext;
function spec314DecisionException(ManagedEnvironment $environment, User $actor, string $reason): FindingException
{
$finding = Finding::factory()->for($environment)->create([
'workspace_id' => (int) $environment->workspace_id,
]);
$exception = FindingException::query()->create([
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'finding_id' => (int) $finding->getKey(),
'requested_by_user_id' => (int) $actor->getKey(),
'owner_user_id' => (int) $actor->getKey(),
'status' => FindingException::STATUS_PENDING,
'current_validity_state' => FindingException::VALIDITY_MISSING_SUPPORT,
'request_reason' => $reason,
'requested_at' => now()->subDay(),
'review_due_at' => now()->addDay(),
'evidence_summary' => ['reference_count' => 0],
]);
$decision = $exception->decisions()->create([
'workspace_id' => (int) $environment->workspace_id,
'managed_environment_id' => (int) $environment->getKey(),
'actor_user_id' => (int) $actor->getKey(),
'decision_type' => FindingExceptionDecision::TYPE_REQUESTED,
'reason' => $reason,
'metadata' => [],
'decided_at' => now()->subDay(),
]);
$exception->forceFill(['current_decision_id' => (int) $decision->getKey()])->save();
return $exception->fresh(['currentDecision']);
}
it('Spec314 decision register clean workspace url opens for authorized workspace users', function (): void {
$environment = ManagedEnvironment::factory()->active()->create();
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'readonly', workspaceRole: 'readonly');
spec314DecisionException($environment, $user, 'Spec314 clean decision register');
$url = DecisionRegister::getUrl(panel: 'admin');
expect($url)->not->toContain('managed_environment_id');
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id])
->get($url)
->assertOk()
->assertSee('Decision register');
});
it('Spec314 decision register clean workspace url shows an empty state instead of 403', function (): void {
$environment = ManagedEnvironment::factory()->active()->create();
[$user, $environment] = createUserWithTenant(tenant: $environment, role: 'readonly', workspaceRole: 'readonly');
$this->actingAs($user)
->withSession([WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id])
->get(DecisionRegister::getUrl(panel: 'admin'))
->assertOk()
->assertSee('Decision register')
->assertSee('No open decisions match this filter right now.');
});