TenantAtlas/tests/Feature/Verification/VerificationReportFingerprintTest.php
ahmido 53dc89e6ef Spec 075: Verification Checklist Framework V1.5 (fingerprint + acknowledgements) (#93)
Implements Spec 075 (V1.5) on top of Spec 074.

Highlights
- Deterministic report fingerprint (sha256) + previous_report_id linkage
- Viewer change indicator: "No changes" vs "Changed" when previous exists
- Check acknowledgements (fail|warn|block) with capability-first auth, confirmation, and audit event
- Verify-step UX polish (issues-first, primary CTA)

Testing
- Focused Pest coverage for fingerprint, previous resolver, change indicator, acknowledgements, badge semantics, DB-only viewer guard.

Notes
- Viewing remains DB-only (no external calls while rendering).

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #93
2026-02-05 21:44:19 +00:00

48 lines
1.9 KiB
PHP

<?php
declare(strict_types=1);
use App\Support\Verification\VerificationReportFingerprint;
it('computes the same fingerprint regardless of check ordering', function (): void {
$checksA = [
['key' => 'b', 'status' => 'fail', 'blocking' => false, 'reason_code' => 'missing_configuration', 'severity' => 'high'],
['key' => 'a', 'status' => 'pass', 'blocking' => false, 'reason_code' => 'ok', 'severity' => 'info'],
];
$checksB = [
['key' => 'a', 'status' => 'pass', 'blocking' => false, 'reason_code' => 'ok', 'severity' => 'info'],
['key' => 'b', 'status' => 'fail', 'blocking' => false, 'reason_code' => 'missing_configuration', 'severity' => 'high'],
];
expect(VerificationReportFingerprint::forChecks($checksA))
->toBe(VerificationReportFingerprint::forChecks($checksB));
});
it('treats missing severity as empty string for fingerprint determinism', function (): void {
$withMissingSeverity = [
['key' => 'a', 'status' => 'fail', 'blocking' => true, 'reason_code' => 'permission_denied'],
];
$withEmptySeverity = [
['key' => 'a', 'status' => 'fail', 'blocking' => true, 'reason_code' => 'permission_denied', 'severity' => ''],
];
expect(VerificationReportFingerprint::forChecks($withMissingSeverity))
->toBe(VerificationReportFingerprint::forChecks($withEmptySeverity));
});
it('treats severity-only changes as different fingerprints (missing != info)', function (): void {
$missingSeverity = [
['key' => 'a', 'status' => 'fail', 'blocking' => false, 'reason_code' => 'unknown_error'],
];
$infoSeverity = [
['key' => 'a', 'status' => 'fail', 'blocking' => false, 'reason_code' => 'unknown_error', 'severity' => 'info'],
];
expect(VerificationReportFingerprint::forChecks($missingSeverity))
->not->toBe(VerificationReportFingerprint::forChecks($infoSeverity));
});