collect($tenant); expect($payload['state'])->toBe(EvidenceCompletenessState::Missing->value) ->and($payload['summary_payload']['drift_count'])->toBe(0) ->and($payload['summary_payload']['latest_compare_run_id'])->toBeNull(); }); it('marks no baseline drift as complete when the latest compare succeeded', function (): void { [, $tenant] = createUserWithTenant(role: 'owner'); [$profile, $snapshot] = seedActiveBaselineForTenant($tenant); $run = seedBaselineCompareRun( tenant: $tenant, profile: $profile, snapshot: $snapshot, compareContext: ['reason_code' => 'baseline.compare.no_drift_detected'], outcome: OperationRunOutcome::Succeeded->value, ); $payload = app(BaselineDriftPostureSource::class)->collect($tenant); expect($payload['state'])->toBe(EvidenceCompletenessState::Complete->value) ->and($payload['measured_at']?->equalTo($run->completed_at))->toBeTrue() ->and($payload['summary_payload']['drift_count'])->toBe(0) ->and($payload['summary_payload']['latest_compare_run_id'])->toBe((int) $run->getKey()) ->and($payload['summary_payload']['latest_compare_outcome'])->toBe(OperationRunOutcome::Succeeded->value); }); it('marks no baseline drift as partial when the latest compare completed with warnings', function (): void { [, $tenant] = createUserWithTenant(role: 'owner'); [$profile, $snapshot] = seedActiveBaselineForTenant($tenant); $run = seedBaselineCompareRun( tenant: $tenant, profile: $profile, snapshot: $snapshot, compareContext: [ 'reason_code' => 'baseline.compare.no_drift_detected', 'evidence_gaps' => ['count' => 3], ], outcome: OperationRunOutcome::PartiallySucceeded->value, ); $payload = app(BaselineDriftPostureSource::class)->collect($tenant); expect($payload['state'])->toBe(EvidenceCompletenessState::Partial->value) ->and($payload['measured_at']?->equalTo($run->completed_at))->toBeTrue() ->and($payload['summary_payload']['drift_count'])->toBe(0) ->and($payload['summary_payload']['latest_compare_run_id'])->toBe((int) $run->getKey()) ->and($payload['summary_payload']['latest_compare_outcome'])->toBe(OperationRunOutcome::PartiallySucceeded->value); });