TenantAtlas/apps/platform/tests/Unit/ResolutionGuidance/Spec350ReviewPackResolutionAdapterTest.php
ahmido 4cf2712f92 feat: operator resolution guidance framework v1 (spec 350) (#421)
Implemented the first version of the operator resolution guidance framework. Added new foundation classes (ResolutionCase, ResolutionAction) and a ReviewPackOutputResolutionAdapter. Updated the Customer Review Workspace and Environment Review Resource to use the new adapter. Added extensive test coverage for the framework and UI integrations.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #421
2026-06-03 15:35:25 +00:00

110 lines
4.4 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\EnvironmentReview;
use App\Models\EvidenceSnapshot;
use App\Models\ReviewPack;
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\ResolutionGuidance\Adapters\ReviewPackOutputResolutionAdapter;
use App\Support\ResolutionGuidance\ResolutionAction;
use App\Support\ReviewPacks\ReviewPackOutputReadiness;
use App\Support\ReviewPacks\ReviewPackOutputResolutionGuidance;
it('maps publication-blocked review output guidance into one shared resolution case', function (): void {
$readiness = ReviewPackOutputReadiness::derive(
reviewStatus: 'published',
reviewCompletenessState: EnvironmentReviewCompletenessState::Complete->value,
evidenceCompletenessState: EnvironmentReviewCompletenessState::Partial->value,
sectionStateCounts: [
EnvironmentReviewCompletenessState::Complete->value => 3,
EnvironmentReviewCompletenessState::Missing->value => 2,
],
requiredSectionCount: 5,
requiredSectionStateCounts: [
EnvironmentReviewCompletenessState::Complete->value => 3,
EnvironmentReviewCompletenessState::Missing->value => 2,
],
publishBlockers: ['Operator approval note is still missing.'],
hasReadyExport: false,
includePii: false,
protectedValuesHidden: true,
disclosurePresent: true,
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'download' => '/admin/review-packs/8/download',
'review' => '/admin/reviews/6',
'evidence' => '/admin/evidence/8',
]);
$review = new EnvironmentReview;
$review->forceFill([
'id' => 6,
'workspace_id' => 1,
'managed_environment_id' => 41,
]);
$review->setRelation('evidenceSnapshot', tap(new EvidenceSnapshot, function (EvidenceSnapshot $snapshot): void {
$snapshot->forceFill(['id' => 8]);
}));
$review->setRelation('currentExportReviewPack', tap(new ReviewPack, function (ReviewPack $pack): void {
$pack->forceFill(['id' => 8]);
}));
$case = ReviewPackOutputResolutionAdapter::fromGuidance($review, $guidance, 'customer_review_workspace');
expect($case['key'])->toBe('review_output.publication_blocked')
->and($case['severity'])->toBe('critical')
->and($case['status'])->toBe('blocked')
->and($case['title'])->toBe('Output not customer-ready')
->and($case['primary_action']['key'])->toBe('resolve_review_blockers')
->and($case['primary_action']['type'])->toBe(ResolutionAction::TYPE_NAVIGATION)
->and($case['source_refs'])->toEqual([
['type' => 'environment_review', 'id' => 6],
['type' => 'review_pack', 'id' => 8],
])
->and($case['evidence_refs'])->toEqual([
['type' => 'evidence_snapshot', 'id' => 8],
]);
});
it('maps ready customer-safe exports to a download-first shared resolution case', function (): void {
$readiness = ReviewPackOutputReadiness::derive(
reviewStatus: 'published',
reviewCompletenessState: EnvironmentReviewCompletenessState::Complete->value,
evidenceCompletenessState: EnvironmentReviewCompletenessState::Complete->value,
sectionStateCounts: [
EnvironmentReviewCompletenessState::Complete->value => 5,
],
requiredSectionCount: 5,
requiredSectionStateCounts: [
EnvironmentReviewCompletenessState::Complete->value => 5,
],
publishBlockers: [],
hasReadyExport: true,
includePii: false,
protectedValuesHidden: true,
disclosurePresent: true,
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'download' => '/admin/review-packs/8/download',
'review' => '/admin/reviews/6',
]);
$review = new EnvironmentReview;
$review->forceFill([
'id' => 6,
'workspace_id' => 1,
'managed_environment_id' => 41,
]);
$case = ReviewPackOutputResolutionAdapter::fromGuidance($review, $guidance, 'customer_review_workspace');
expect($case['key'])->toBe('review_output.customer_safe_ready')
->and($case['severity'])->toBe('success')
->and($case['status'])->toBe('ready')
->and($case['primary_action']['key'])->toBe('download_customer_safe_review_pack')
->and($case['primary_action']['type'])->toBe(ResolutionAction::TYPE_DOWNLOAD);
});