TenantAtlas/apps/platform/tests/Feature/EnvironmentReview/Spec360ReviewComposeAdapterOwnershipTest.php

67 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\EnvironmentReview;
use App\Models\OperationRun;
use App\Services\AdapterRunReconciler;
use App\Services\EnvironmentReviews\EnvironmentReviewFingerprint;
use App\Support\EnvironmentReviewStatus;
use App\Support\OperationRunOutcome;
use App\Support\OperationRunStatus;
use Illuminate\Database\QueryException;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('finalizes unique-write review compose failures through the canonical adapter seam in Spec360', function (): void {
[$user, $tenant] = createUserWithTenant(role: 'owner');
$snapshot = seedEnvironmentReviewEvidence($tenant);
$fingerprint = app(EnvironmentReviewFingerprint::class)->forSnapshot($tenant, $snapshot);
$run = OperationRun::factory()->create([
'workspace_id' => (int) $tenant->workspace_id,
'managed_environment_id' => (int) $tenant->getKey(),
'user_id' => (int) $user->getKey(),
'initiator_name' => $user->name,
'type' => 'environment.review.compose',
'status' => OperationRunStatus::Queued->value,
'outcome' => OperationRunOutcome::Pending->value,
'context' => [
'workspace_id' => (int) $tenant->workspace_id,
'managed_environment_id' => (int) $tenant->getKey(),
'evidence_snapshot_id' => (int) $snapshot->getKey(),
'review_fingerprint' => $fingerprint,
],
]);
$review = EnvironmentReview::factory()->create([
'workspace_id' => (int) $tenant->workspace_id,
'managed_environment_id' => (int) $tenant->getKey(),
'evidence_snapshot_id' => (int) $snapshot->getKey(),
'initiated_by_user_id' => (int) $user->getKey(),
'operation_run_id' => (int) $run->getKey(),
'fingerprint' => $fingerprint,
'status' => EnvironmentReviewStatus::Draft->value,
]);
$previous = new \PDOException('duplicate key value violates unique constraint');
$previous->errorInfo = ['23505'];
$exception = new QueryException('pgsql', 'insert into environment_reviews ...', [], $previous);
$change = app(AdapterRunReconciler::class)->reconcileOperationRunFailure($run, $exception);
$run->refresh();
$review->refresh();
expect($change['applied'] ?? null)->toBeTrue()
->and($run->status)->toBe(OperationRunStatus::Completed->value)
->and($run->outcome)->toBe(OperationRunOutcome::Failed->value)
->and($run->reconciliationAdapter())->toBe('environment_review_compose')
->and($run->reconciliationDecision())->toBe('attention_required')
->and(data_get($run->context, 'reconciliation.reason_code'))->toBe('run.adapter_out_of_sync')
->and((string) data_get($run->failure_summary, '0.message'))->not->toContain('SQLSTATE')
->and((string) data_get($run->failure_summary, '0.message'))->not->toContain('duplicate key')
->and($review->status)->toBe(EnvironmentReviewStatus::Draft->value);
});