syncDefaults(); [$user, $environment] = createMinimalUserWithTenant(role: 'owner'); $connection = ProviderConnection::factory()->withCredential()->create([ 'workspace_id' => (int) $environment->workspace_id, 'managed_environment_id' => (int) $environment->getKey(), ]); $graph = spec426IdentityReadinessGraphClient(); app()->instance(GraphClientInterface::class, $graph); $run = OperationRun::factory()->withUser($user)->forTenant($environment)->create([ 'type' => OperationRunType::TenantConfigurationCapture->value, 'status' => OperationRunStatus::Queued->value, 'outcome' => OperationRunOutcome::Pending->value, 'context' => [ 'target_scope' => [ 'workspace_id' => (int) $environment->workspace_id, 'managed_environment_id' => (int) $environment->getKey(), 'provider_connection_id' => (int) $connection->getKey(), ], 'resource_types' => ['appPermissionPolicy'], 'required_capability' => 'evidence.manage', ], ]); $result = app(GenericContentEvidenceCaptureService::class)->capture( tenant: $environment, providerConnection: $connection, operationRun: $run, canonicalTypes: ['appPermissionPolicy'], ); expect($graph->calls)->toBe([]) ->and($result['summary_counts'])->toMatchArray([ 'total' => 1, 'processed' => 1, 'succeeded' => 0, 'skipped' => 1, 'failed' => 0, ]) ->and($result['run_outcome'])->toBe(OperationRunOutcome::Blocked->value) ->and($result['outcomes'][0]['outcome'])->toBe(CaptureOutcome::BlockedMissingContract->value) ->and($result['outcomes'][0]['reason_code'])->toBe('missing_source_contract_mapping') ->and(TenantConfigurationResource::query()->count())->toBe(0) ->and(TenantConfigurationResourceEvidence::query()->count())->toBe(0); }); function spec426IdentityReadinessGraphClient(): GraphClientInterface { return new class implements GraphClientInterface { /** * @var list}> */ public array $calls = []; public function listPolicies(string $policyType, array $options = []): GraphResponse { $this->calls[] = ['policy_type' => $policyType, 'options' => $options]; return new GraphResponse(true, [[ 'DisplayName' => 'Display-only policy', 'Name' => 'Display-only policy', 'Identity' => 'Global', 'GlobalCatalogAppsType' => 'AllowAllApps', ]]); } public function getPolicy(string $policyType, string $policyId, array $options = []): GraphResponse { return new GraphResponse(false, [], 501); } public function getOrganization(array $options = []): GraphResponse { return new GraphResponse(false, [], 501); } public function applyPolicy(string $policyType, string $policyId, array $payload, array $options = []): GraphResponse { return new GraphResponse(false, [], 501); } public function getServicePrincipalPermissions(array $options = []): GraphResponse { return new GraphResponse(false, [], 501); } public function request(string $method, string $path, array $options = []): GraphResponse { return new GraphResponse(false, [], 501); } }; }