Implemented the output resolution guidance for the customer review workspace and internal views. Added ReviewPackOutputResolutionGuidance, updated CustomerReviewWorkspace and EnvironmentReviewResource, and added related blade views and tests. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #420
144 lines
6.0 KiB
PHP
144 lines
6.0 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['limitations'])->toBeEmpty();
|
|
});
|
|
|
|
/**
|
|
* @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,
|
|
);
|
|
}
|