create(); $user = User::factory()->create(); WorkspaceMembership::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'user_id' => (int) $user->getKey(), 'role' => 'owner', ]); session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey()); $tenant = Tenant::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'status' => Tenant::STATUS_ONBOARDING, ]); $connection = ProviderConnection::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'is_default' => true, ]); TenantOnboardingSession::query()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'entra_tenant_id' => (string) $tenant->tenant_id, 'current_step' => 'verify', 'state' => [ 'provider_connection_id' => (int) $connection->getKey(), ], 'started_by_user_id' => (int) $user->getKey(), 'updated_by_user_id' => (int) $user->getKey(), ]); $this->actingAs($user) ->get('/admin/onboarding') ->assertSuccessful() ->assertSee('Start verification') ->assertDontSee('Refresh'); $runningRun = OperationRun::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'type' => 'provider.connection.check', 'status' => 'running', 'outcome' => 'pending', 'context' => [ 'provider_connection_id' => (int) $connection->getKey(), ], ]); TenantOnboardingSession::query() ->where('workspace_id', (int) $workspace->getKey()) ->where('tenant_id', (int) $tenant->getKey()) ->update([ 'state' => [ 'provider_connection_id' => (int) $connection->getKey(), 'verification_operation_run_id' => (int) $runningRun->getKey(), ], ]); $this->actingAs($user) ->get('/admin/onboarding') ->assertSuccessful() ->assertSee('Refresh') ->assertDontSee('Start verification'); }); it('orders issues deterministically and groups acknowledged issues', function (): void { $workspace = Workspace::factory()->create(); $user = User::factory()->create(); WorkspaceMembership::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'user_id' => (int) $user->getKey(), 'role' => 'owner', ]); session()->put(WorkspaceContext::SESSION_KEY, (int) $workspace->getKey()); $tenant = Tenant::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'status' => Tenant::STATUS_ONBOARDING, ]); $connection = ProviderConnection::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'is_default' => true, ]); $checks = [ [ 'key' => 'acknowledged_fail', 'title' => 'Acked failure', 'status' => 'fail', 'severity' => 'medium', 'blocking' => false, 'reason_code' => 'invalid_state', 'message' => 'Already known.', 'evidence' => [], 'next_steps' => [], ], [ 'key' => 'warning', 'title' => 'Warning check', 'status' => 'warn', 'severity' => 'low', 'blocking' => false, 'reason_code' => 'not_applicable', 'message' => 'Something is slightly off.', 'evidence' => [], 'next_steps' => [], ], [ 'key' => 'failure', 'title' => 'Failure check', 'status' => 'fail', 'severity' => 'high', 'blocking' => false, 'reason_code' => 'missing_configuration', 'message' => 'This must be fixed.', 'evidence' => [], 'next_steps' => [], ], [ 'key' => 'blocker', 'title' => 'Blocker check', 'status' => 'fail', 'severity' => 'critical', 'blocking' => true, 'reason_code' => 'permission_denied', 'message' => 'Cannot proceed.', 'evidence' => [], 'next_steps' => [ ['label' => 'First step', 'url' => '/admin/help/first'], ['label' => 'Second step', 'url' => '/admin/help/second'], ['label' => 'Third step', 'url' => '/admin/help/third'], ], ], [ 'key' => 'pass', 'title' => 'Passed check', 'status' => 'pass', 'severity' => '', 'blocking' => false, 'reason_code' => 'ok', 'message' => 'Looks good.', 'evidence' => [], 'next_steps' => [], ], ]; $report = VerificationReportWriter::build('provider.connection.check', $checks); $run = OperationRun::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'type' => 'provider.connection.check', 'status' => 'completed', 'outcome' => 'failed', 'context' => [ 'provider_connection_id' => (int) $connection->getKey(), 'verification_report' => $report, ], ]); VerificationCheckAcknowledgement::factory()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'operation_run_id' => (int) $run->getKey(), 'check_key' => 'acknowledged_fail', 'ack_reason' => 'Known issue accepted.', 'acknowledged_by_user_id' => (int) $user->getKey(), 'acknowledged_at' => now(), ]); TenantOnboardingSession::query()->create([ 'workspace_id' => (int) $workspace->getKey(), 'tenant_id' => (int) $tenant->getKey(), 'entra_tenant_id' => (string) $tenant->tenant_id, 'current_step' => 'verify', 'state' => [ 'provider_connection_id' => (int) $connection->getKey(), 'verification_operation_run_id' => (int) $run->getKey(), ], 'started_by_user_id' => (int) $user->getKey(), 'updated_by_user_id' => (int) $user->getKey(), ]); $this->actingAs($user) ->get('/admin/onboarding') ->assertSuccessful() ->assertSee('Read-only') ->assertSeeInOrder([ 'Blocker check', 'Failure check', 'Warning check', 'Acknowledged issues', 'Acked failure', ]) ->assertSee('Known issue accepted.') ->assertSee('First step') ->assertSee('Second step') ->assertDontSee('Third step'); });