create(); $resolver = app(MicrosoftGraphOptionsResolver::class); $call = fn (): array => $resolver->resolveForTenant($tenant); expect($call)->toThrow(ProviderConfigurationRequiredException::class); try { $call(); } catch (ProviderConfigurationRequiredException $exception) { expect($exception->reasonCode)->toBe(ProviderReasonCodes::ProviderConnectionMissing); expect($exception->provider)->toBe('microsoft'); expect($exception->tenantId)->toBe((int) $tenant->getKey()); } }); it('throws when default provider connection needs consent', function (): void { $tenant = Tenant::factory()->create(); ProviderConnection::factory()->create([ 'tenant_id' => $tenant->getKey(), 'workspace_id' => $tenant->workspace_id, 'provider' => 'microsoft', 'is_default' => true, 'status' => 'needs_consent', ]); $resolver = app(MicrosoftGraphOptionsResolver::class); $call = fn (): array => $resolver->resolveForTenant($tenant); expect($call)->toThrow(ProviderConfigurationRequiredException::class); try { $call(); } catch (ProviderConfigurationRequiredException $exception) { expect($exception->reasonCode)->toBe(ProviderReasonCodes::ProviderConsentMissing); } }); it('builds graph options from default provider connection credentials', function (): void { $tenant = Tenant::factory()->create(); $connection = ProviderConnection::factory()->create([ 'tenant_id' => $tenant->getKey(), 'workspace_id' => $tenant->workspace_id, 'provider' => 'microsoft', 'entra_tenant_id' => 'entra-tenant-id', 'is_default' => true, 'status' => 'connected', ]); ProviderCredential::factory()->create([ 'provider_connection_id' => $connection->getKey(), 'type' => 'client_secret', 'payload' => [ 'client_id' => 'client-id', 'client_secret' => 'client-secret', ], ]); $resolver = app(MicrosoftGraphOptionsResolver::class); $options = $resolver->resolveForTenant($tenant, ['query' => ['a' => 'b']]); expect($options['tenant'])->toBe('entra-tenant-id'); expect($options['client_id'])->toBe('client-id'); expect($options['client_secret'])->toBe('client-secret'); expect($options['client_request_id'])->toBeString()->not->toBeEmpty(); expect($options['query'])->toBe(['a' => 'b']); });