## Summary - integrate the current `platform-dev` branch into `dev` - bring the latest platform work from the integration branch into the main development branch - include the recent findings lifecycle backfill removal slice together with the already accumulated `platform-dev` changes ## Scope - source branch: `platform-dev` - target branch: `dev` - branch role: integration PR, not a single-feature PR ## Validation - branch state reviewed before PR creation - `platform-dev` is ahead of `dev` with the expected integration history - this PR intentionally carries the accumulated `platform-dev` commits into `dev` ## Notes - this is the correct merge direction for the current workflow, where feature branches land in `platform-dev` first and `platform-dev` is then merged into `dev` - after merging, `platform-dev` can be recreated fresh from `dev` as usual Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #295
62 lines
2.7 KiB
PHP
62 lines
2.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\Finding;
|
|
use App\Models\User;
|
|
use App\Services\Findings\FindingWorkflowService;
|
|
use App\Support\Audit\AuditActionId;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('keeps canonical findings workflow behavior after removing the backfill runtime surfaces', function (): void {
|
|
[$owner, $tenant] = createUserWithTenant(role: 'owner');
|
|
$assignee = User::factory()->create();
|
|
createUserWithTenant(tenant: $tenant, user: $assignee, role: 'operator');
|
|
|
|
$service = app(FindingWorkflowService::class);
|
|
$finding = $this->makeFindingForWorkflow($tenant, Finding::STATUS_NEW, [
|
|
'owner_user_id' => null,
|
|
'assignee_user_id' => null,
|
|
'sla_days' => 14,
|
|
'due_at' => now()->addDays(14),
|
|
]);
|
|
|
|
$triaged = $service->triage($finding, $tenant, $owner);
|
|
$assigned = $service->assign(
|
|
finding: $triaged,
|
|
tenant: $tenant,
|
|
actor: $owner,
|
|
assigneeUserId: (int) $assignee->getKey(),
|
|
ownerUserId: (int) $owner->getKey(),
|
|
);
|
|
$inProgress = $service->startProgress($assigned, $tenant, $owner);
|
|
$resolved = $service->resolve($inProgress, $tenant, $owner, Finding::RESOLVE_REASON_REMEDIATED);
|
|
$riskAccepted = $service->riskAccept(
|
|
$this->makeFindingForWorkflow($tenant, Finding::STATUS_NEW),
|
|
$tenant,
|
|
$owner,
|
|
Finding::CLOSE_REASON_ACCEPTED_RISK,
|
|
);
|
|
|
|
expect($triaged->status)->toBe(Finding::STATUS_TRIAGED)
|
|
->and($triaged->triaged_at)->not->toBeNull()
|
|
->and((int) $assigned->owner_user_id)->toBe((int) $owner->getKey())
|
|
->and((int) $assigned->assignee_user_id)->toBe((int) $assignee->getKey())
|
|
->and($assigned->sla_days)->toBe(14)
|
|
->and($assigned->due_at)->not->toBeNull()
|
|
->and($inProgress->status)->toBe(Finding::STATUS_IN_PROGRESS)
|
|
->and($inProgress->in_progress_at)->not->toBeNull()
|
|
->and($resolved->status)->toBe(Finding::STATUS_RESOLVED)
|
|
->and($resolved->resolved_reason)->toBe(Finding::RESOLVE_REASON_REMEDIATED)
|
|
->and($riskAccepted->status)->toBe(Finding::STATUS_RISK_ACCEPTED)
|
|
->and($riskAccepted->closed_reason)->toBe(Finding::CLOSE_REASON_ACCEPTED_RISK);
|
|
|
|
expect($this->latestFindingAudit($triaged, AuditActionId::FindingTriaged))->not->toBeNull()
|
|
->and($this->latestFindingAudit($assigned, AuditActionId::FindingAssigned))->not->toBeNull()
|
|
->and($this->latestFindingAudit($inProgress, AuditActionId::FindingInProgress))->not->toBeNull()
|
|
->and($this->latestFindingAudit($resolved, AuditActionId::FindingResolved))->not->toBeNull()
|
|
->and($this->latestFindingAudit($riskAccepted, AuditActionId::FindingRiskAccepted))->not->toBeNull();
|
|
});
|