319-environment-owned-surface-routing-shell-context-contract (#382)

## Reopened validation note

Baseline Compare residual test failures discovered during the Spec 322 broader regression pass were fixed in Spec 319 because they belong to the Environment-owned Baseline Compare route contract.

No runtime code was changed. The affected tests now mount `BaselineCompareLanding` through the explicit environment route-owned helper instead of relying on implicit/remembered context.

Validation:
- 5 previously failing tests: 5 passed, 42 assertions
- additional baseline/action/gap/action-surface tests: 20 passed, 199 assertions
- broader Unit/Feature slice: 233 passed, 1826 assertions
- pint --dirty: pass
- git diff --check: pass

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #382
This commit is contained in:
ahmido 2026-05-17 14:28:12 +00:00
parent ec4ff1074c
commit 094fff87b6
8 changed files with 37 additions and 21 deletions

View File

@ -2,14 +2,12 @@
declare(strict_types=1); declare(strict_types=1);
use App\Filament\Pages\BaselineCompareLanding;
use App\Models\BaselineProfile; use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot; use App\Models\BaselineSnapshot;
use App\Models\BaselineTenantAssignment; use App\Models\BaselineTenantAssignment;
use App\Support\Baselines\BaselineCompareStats; use App\Support\Baselines\BaselineCompareStats;
use App\Support\Ui\OperatorExplanation\ExplanationFamily; use App\Support\Ui\OperatorExplanation\ExplanationFamily;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Livewire\Livewire;
it('shows an unavailable explanation before any baseline compare result exists', function (): void { it('shows an unavailable explanation before any baseline compare result exists', function (): void {
[$user, $tenant] = createUserWithTenant(role: 'owner'); [$user, $tenant] = createUserWithTenant(role: 'owner');
@ -43,8 +41,7 @@
->and($explanation->family)->toBe(ExplanationFamily::Unavailable) ->and($explanation->family)->toBe(ExplanationFamily::Unavailable)
->and($explanation->nextActionText)->toBe('Run the baseline compare to generate a result'); ->and($explanation->nextActionText)->toBe('Run the baseline compare to generate a result');
Livewire::actingAs($user) baselineCompareLandingLivewire($tenant, user: $user)
->test(BaselineCompareLanding::class)
->assertSee($summary->headline) ->assertSee($summary->headline)
->assertSee($summary->nextActionLabel()) ->assertSee($summary->nextActionLabel())
->assertSee($explanation->coverageStatement ?? ''); ->assertSee($explanation->coverageStatement ?? '');

View File

@ -2,7 +2,6 @@
declare(strict_types=1); declare(strict_types=1);
use App\Filament\Pages\BaselineCompareLanding;
use App\Filament\Resources\BaselineProfileResource\Pages\ViewBaselineProfile; use App\Filament\Resources\BaselineProfileResource\Pages\ViewBaselineProfile;
use App\Support\Workspaces\WorkspaceContext; use App\Support\Workspaces\WorkspaceContext;
use Filament\Facades\Filament; use Filament\Facades\Filament;
@ -37,12 +36,10 @@
$tenant->makeCurrent(); $tenant->makeCurrent();
Filament::setTenant($tenant, true); Filament::setTenant($tenant, true);
Livewire::actingAs($readonlyUser) baselineCompareLandingLivewire($tenant, user: $readonlyUser)
->test(BaselineCompareLanding::class)
->assertActionDisabled('compareNow'); ->assertActionDisabled('compareNow');
Livewire::actingAs($ownerUser) baselineCompareLandingLivewire($tenant, user: $ownerUser)
->test(BaselineCompareLanding::class)
->assertActionEnabled('compareNow'); ->assertActionEnabled('compareNow');
}); });

View File

@ -2,7 +2,6 @@
declare(strict_types=1); declare(strict_types=1);
use App\Filament\Pages\BaselineCompareLanding;
use App\Models\BaselineProfile; use App\Models\BaselineProfile;
use App\Models\BaselineSnapshot; use App\Models\BaselineSnapshot;
use App\Models\BaselineTenantAssignment; use App\Models\BaselineTenantAssignment;
@ -12,7 +11,6 @@
use App\Support\ReasonTranslation\ReasonPresenter; use App\Support\ReasonTranslation\ReasonPresenter;
use App\Support\Ui\OperatorExplanation\ExplanationFamily; use App\Support\Ui\OperatorExplanation\ExplanationFamily;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Livewire\Livewire;
it('renders suppressed baseline-compare results as explanation-first output instead of an implicit all-clear', function (): void { it('renders suppressed baseline-compare results as explanation-first output instead of an implicit all-clear', function (): void {
[$user, $tenant] = createUserWithTenant(role: 'owner'); [$user, $tenant] = createUserWithTenant(role: 'owner');
@ -82,8 +80,7 @@
expect($explanation->family)->toBe(ExplanationFamily::SuppressedOutput); expect($explanation->family)->toBe(ExplanationFamily::SuppressedOutput);
expect($reasonSemantics)->not->toBeNull(); expect($reasonSemantics)->not->toBeNull();
Livewire::actingAs($user) baselineCompareLandingLivewire($tenant, user: $user)
->test(BaselineCompareLanding::class)
->assertSee($summary->headline) ->assertSee($summary->headline)
->assertSee($explanation->trustworthinessLabel()) ->assertSee($explanation->trustworthinessLabel())
->assertSee($summary->nextActionLabel()) ->assertSee($summary->nextActionLabel())

View File

@ -2,7 +2,6 @@
declare(strict_types=1); declare(strict_types=1);
use App\Filament\Pages\BaselineCompareLanding;
use App\Filament\Widgets\Dashboard\BaselineCompareNow; use App\Filament\Widgets\Dashboard\BaselineCompareNow;
use App\Filament\Widgets\ManagedEnvironment\BaselineCompareCoverageBanner; use App\Filament\Widgets\ManagedEnvironment\BaselineCompareCoverageBanner;
use App\Models\BaselineProfile; use App\Models\BaselineProfile;
@ -91,7 +90,7 @@ function createBaselineCompareSummaryConsistencyTenant(): array
->assertSee('The last compare finished, but normal result output was suppressed.') ->assertSee('The last compare finished, but normal result output was suppressed.')
->assertDontSee('Aligned'); ->assertDontSee('Aligned');
Livewire::test(BaselineCompareLanding::class) baselineCompareLandingLivewire($tenant)
->assertSee('Needs review') ->assertSee('Needs review')
->assertSee('The last compare finished, but normal result output was suppressed.') ->assertSee('The last compare finished, but normal result output was suppressed.')
->assertSee('Limited confidence') ->assertSee('Limited confidence')
@ -141,7 +140,7 @@ function createBaselineCompareSummaryConsistencyTenant(): array
->assertSee('overdue finding') ->assertSee('overdue finding')
->assertSee('Open findings'); ->assertSee('Open findings');
Livewire::test(BaselineCompareLanding::class) baselineCompareLandingLivewire($tenant)
->assertSee('Action required') ->assertSee('Action required')
->assertSee('overdue finding') ->assertSee('overdue finding')
->assertSee('Open findings'); ->assertSee('Open findings');
@ -174,7 +173,7 @@ function createBaselineCompareSummaryConsistencyTenant(): array
->assertSee('Baseline compare is in progress.') ->assertSee('Baseline compare is in progress.')
->assertSee('Open operation'); ->assertSee('Open operation');
Livewire::test(BaselineCompareLanding::class) baselineCompareLandingLivewire($tenant)
->assertSee('In progress') ->assertSee('In progress')
->assertSee('Baseline compare is in progress.') ->assertSee('Baseline compare is in progress.')
->assertSee('Open operation'); ->assertSee('Open operation');

View File

@ -123,7 +123,7 @@ function structuredGapSurfaceContext(): array
'completed_at' => now(), 'completed_at' => now(),
]); ]);
Livewire::test(BaselineCompareLanding::class) baselineCompareLandingLivewire($tenant)
->assertSee('Evidence gap details') ->assertSee('Evidence gap details')
->assertSee('Subject class') ->assertSee('Subject class')
->assertSee('Outcome') ->assertSee('Outcome')

View File

@ -2452,8 +2452,7 @@ function actionSurfaceSystemPanelContext(array $capabilities): PlatformUser
'baseline_profile_id' => (int) $profile->getKey(), 'baseline_profile_id' => (int) $profile->getKey(),
]); ]);
Livewire::actingAs($approver) baselineCompareLandingLivewire($tenant, user: $approver)
->test(BaselineCompareLanding::class)
->assertActionExists('compareNow', function (Action $action): bool { ->assertActionExists('compareNow', function (Action $action): bool {
return $action->isConfirmationRequired() return $action->isConfirmationRequired()
&& $action->getModalDescription() === 'This will refresh content evidence on demand (redacted) before comparing the current tenant inventory against the assigned baseline snapshot.'; && $action->getModalDescription() === 'This will refresh content evidence on demand (redacted) before comparing the current tenant inventory against the assigned baseline snapshot.';

View File

@ -818,12 +818,20 @@ function createUserWithTenant(
return [$user, $tenant]; return [$user, $tenant];
} }
function baselineCompareLandingLivewire(ManagedEnvironment $tenant, array $queryParams = []): mixed function baselineCompareLandingLivewire(
ManagedEnvironment $tenant,
array $queryParams = [],
?\Illuminate\Contracts\Auth\Authenticatable $user = null,
): mixed
{ {
$manager = \Livewire\Livewire::withHeaders([ $manager = \Livewire\Livewire::withHeaders([
'Referer' => \App\Support\ManagedEnvironmentLinks::baselineCompareUrl($tenant), 'Referer' => \App\Support\ManagedEnvironmentLinks::baselineCompareUrl($tenant),
]); ]);
if ($user instanceof \Illuminate\Contracts\Auth\Authenticatable) {
$manager = $manager->actingAs($user);
}
if ($queryParams !== []) { if ($queryParams !== []) {
$manager = $manager->withQueryParams($queryParams); $manager = $manager->withQueryParams($queryParams);
} }

View File

@ -172,3 +172,22 @@ ## Implementation Evidence
- scoped Pint on touched PHP files. - scoped Pint on touched PHP files.
- `git diff --check` - `git diff --check`
- Broader `./vendor/bin/sail artisan test --filter=DecisionRegister` surfaced an existing unrelated failure in `FindingExceptionDecisionRegisterNavigationTest` where the expected back URL still includes `managed_environment_id`; no Spec 319 files or Decision Register code were changed for that. - Broader `./vendor/bin/sail artisan test --filter=DecisionRegister` surfaced an existing unrelated failure in `FindingExceptionDecisionRegisterNavigationTest` where the expected back URL still includes `managed_environment_id`; no Spec 319 files or Decision Register code were changed for that.
## Reopened Validation Note
Spec 322's broader no-drift regression split exposed five Baseline Compare tests that still mounted `BaselineCompareLanding` without route-owned Environment context. That direct Livewire mount contradicted the Spec 319 hard cutover even though the runtime route contract was already canonical.
Fix applied on the 319 session branch:
- Extended the existing `baselineCompareLandingLivewire()` test helper so tests can pass an explicit acting user while preserving the canonical Baseline Compare referer and `environment` mount parameter.
- Updated Baseline Compare explanation, summary-consistency, authorization, gap-surface, and action-surface tests to mount through explicit Environment ownership instead of remembered/implicit panel tenant state.
- Confirmed no direct `Livewire::test(BaselineCompareLanding::class)` Feature/Unit mount remains.
Validation after reopening:
- `./vendor/bin/sail artisan test tests/Feature/Baselines/BaselineCompareExplanationFallbackTest.php tests/Feature/Filament/BaselineCompareExplanationSurfaceTest.php tests/Feature/Filament/BaselineCompareSummaryConsistencyTest.php --compact`
- Result: 5 passed, 42 assertions.
- `./vendor/bin/sail artisan test tests/Feature/Filament/BaselineActionAuthorizationTest.php tests/Feature/Filament/BaselineGapSurfacesDbOnlyRenderTest.php tests/Feature/Guards/ActionSurfaceContractTest.php --filter='baseline|compareNow|full content' --compact`
- Result: 20 passed, 199 assertions.
- `./vendor/bin/sail artisan test tests/Unit tests/Feature --filter='WorkspaceHub|EnvironmentFilter|ClearFilter|LegacyTenant|BaselineCompare|WorkspaceOwnedAnalysis|AlertsAudit' --compact`
- Result: 233 passed, 1826 assertions.