TenantAtlas/apps/platform/tests/Feature/ReviewPack/Spec349ReviewPackResolutionGuidanceTest.php
Ahmed Darrazi fb2642e941
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m9s
feat(resources): implement provider resource identity binding
Added ProviderResourceBinding model, migrations, policies, and supporting framework for canonical resource identity mapping as defined in Spec 381.
2026-06-15 17:37:06 +02:00

152 lines
6.4 KiB
PHP

<?php
declare(strict_types=1);
use App\Support\EnvironmentReviewCompletenessState;
use App\Support\ReviewPacks\ReviewPackOutputReadiness;
use App\Support\ReviewPacks\ReviewPackOutputResolutionGuidance;
it('maps publication blockers into one primary guidance state and groups the remaining limitations', function (): void {
$readiness = spec349Readiness(
evidenceState: EnvironmentReviewCompletenessState::Partial->value,
hasReadyExport: false,
includePii: true,
publishBlockers: ['Operator approval note is still missing.'],
requiredSectionStates: [
EnvironmentReviewCompletenessState::Complete->value => 3,
EnvironmentReviewCompletenessState::Missing->value => 2,
],
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'download' => '/review-packs/1/download',
'review' => '/environment-reviews/1',
'evidence' => '/evidence/1',
'operation' => '/operations/1',
]);
expect($guidance['state'])->toBe('publication_blocked')
->and($guidance['label'])->toBe('Output not customer-ready')
->and($guidance['primary_action']['label'])->toBe('Inspect review blockers')
->and($guidance['action_help'])->toContain('opens the review detail with blockers, evidence status, and next steps')
->and($guidance['limitations'])->toHaveCount(5)
->and($guidance['limitations'][0]['key'])->toBe('publish_blockers_present')
->and(collect($guidance['secondary_actions'])->pluck('label')->all())->not->toContain('Open review')
->and(collect($guidance['limitations'])->pluck('key')->all())->toEqual([
'publish_blockers_present',
'export_not_ready',
'evidence_basis_incomplete',
'required_sections_incomplete',
'contains_pii',
]);
});
it('maps incomplete evidence to a published-with-limitations guidance item', function (): void {
$readiness = spec349Readiness(
evidenceState: EnvironmentReviewCompletenessState::Missing->value,
hasReadyExport: true,
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'review' => '/environment-reviews/1',
'evidence' => '/evidence/1',
]);
expect($guidance['state'])->toBe('published_with_limitations')
->and($guidance['primary_reason'])->toBe('Evidence basis is incomplete.')
->and($guidance['primary_action']['label'])->toBe('Open evidence basis')
->and($guidance['limitations'])->toHaveCount(1)
->and($guidance['limitations'][0]['label'])->toBe('Evidence basis incomplete');
});
it('renders required section limitation reasons through pluralization instead of raw translation ranges', function (): void {
$readiness = spec349Readiness(
hasReadyExport: true,
requiredSectionStates: [
EnvironmentReviewCompletenessState::Complete->value => 1,
EnvironmentReviewCompletenessState::Partial->value => 4,
EnvironmentReviewCompletenessState::Missing->value => 2,
],
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'review' => '/environment-reviews/1',
]);
expect($guidance['limitations'])->toHaveCount(1)
->and($guidance['limitations'][0]['key'])->toBe('required_sections_incomplete')
->and($guidance['limitations'][0]['reason'])->toBe('6 required sections are partial, missing, or stale.')
->and($guidance['limitations'][0]['reason'])->not->toContain('{1}')
->and($guidance['limitations'][0]['reason'])->not->toContain('[2,*]');
});
it('marks pii-bearing ready exports as internal-only and qualifies the download action', function (): void {
$readiness = spec349Readiness(
includePii: true,
hasReadyExport: true,
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'download' => '/review-packs/1/download',
'review' => '/environment-reviews/1',
]);
expect($guidance['state'])->toBe('internal_only')
->and($guidance['label'])->toBe('Internal review package available')
->and($guidance['primary_action']['label'])->toBe('Review PII/redaction state')
->and(collect($guidance['secondary_actions'])->pluck('label')->all())->toContain('Download internal review pack');
});
it('marks complete non-pii exports as customer-safe ready', function (): void {
$readiness = spec349Readiness(
hasReadyExport: true,
);
$guidance = ReviewPackOutputResolutionGuidance::fromReadiness($readiness, [
'download' => '/review-packs/1/download',
'review' => '/environment-reviews/1',
]);
expect($guidance['state'])->toBe('customer_safe_ready')
->and($guidance['label'])->toBe('Customer-safe review pack ready')
->and($guidance['primary_action']['label'])->toBe('Download customer-safe review pack')
->and($guidance)->not->toHaveKey('provider_resource_bindings')
->and($guidance['limitations'])->toBeEmpty();
});
it('keeps review pack output guidance independent from provider resource bindings', function (): void {
$guidanceFile = (new ReflectionClass(ReviewPackOutputResolutionGuidance::class))->getFileName();
expect($guidanceFile)->toBeString()
->and(file_get_contents((string) $guidanceFile))->not->toContain('ProviderResourceBinding');
});
/**
* @param array<string, int> $requiredSectionStates
* @param list<string> $publishBlockers
* @return array<string, mixed>
*/
function spec349Readiness(
string $evidenceState = EnvironmentReviewCompletenessState::Complete->value,
bool $hasReadyExport = true,
bool $includePii = false,
array $publishBlockers = [],
array $requiredSectionStates = [
EnvironmentReviewCompletenessState::Complete->value => 5,
],
): array {
return ReviewPackOutputReadiness::derive(
reviewStatus: 'published',
reviewCompletenessState: EnvironmentReviewCompletenessState::Complete->value,
evidenceCompletenessState: $evidenceState,
sectionStateCounts: $requiredSectionStates,
requiredSectionCount: array_sum($requiredSectionStates),
requiredSectionStateCounts: $requiredSectionStates,
publishBlockers: $publishBlockers,
hasReadyExport: $hasReadyExport,
includePii: $includePii,
protectedValuesHidden: true,
disclosurePresent: true,
);
}