set('graph.client_id', 'spec353-platform-client'); config()->set('graph.client_secret', 'spec353-platform-secret'); config()->set('graph.managed_environment_id', 'organizations'); }); function spec353RequiredPermissionsApplicationPermissionKey(): string { $permission = collect(spec283ConfiguredPermissionRows()) ->first(static fn (mixed $row): bool => is_array($row) && ($row['type'] ?? null) === 'application'); expect($permission)->not->toBeNull(); return (string) $permission['key']; } function spec353RequiredPermissionsSeedRows( ManagedEnvironment $environment, array $missingKeys = [], array $errorKeys = [], ?string $lastCheckedAt = null, ): void { foreach (spec283ConfiguredPermissionRows() as $permission) { if (! is_array($permission)) { continue; } $permissionKey = (string) ($permission['key'] ?? ''); if ($permissionKey === '') { continue; } ManagedEnvironmentPermission::query()->updateOrCreate( [ 'managed_environment_id' => (int) $environment->getKey(), 'permission_key' => $permissionKey, 'workspace_id' => (int) $environment->workspace_id, ], [ 'status' => in_array($permissionKey, $errorKeys, true) ? 'error' : (in_array($permissionKey, $missingKeys, true) ? 'missing' : 'granted'), 'details' => ['source' => 'spec353-required-permissions-test'], 'last_checked_at' => $lastCheckedAt ? Carbon::parse($lastCheckedAt) : now(), ], ); } } function spec353RequiredPermissionsComponent(User $user, ManagedEnvironment $environment, array $query = []) { test()->actingAs($user); setAdminPanelContext($environment); session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id); return Livewire::withQueryParams($query)->test(EnvironmentRequiredPermissions::class, [ 'environment' => $environment, ]); } it('renders guidance before the raw permissions matrix on the required-permissions page', function (): void { [$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'owner', ensureDefaultMicrosoftProviderConnection: false); ProviderConnection::factory()->platform()->verifiedHealthy()->create([ 'managed_environment_id' => (int) $environment->getKey(), 'workspace_id' => (int) $environment->workspace_id, 'is_default' => true, ]); $missingPermissionKey = spec353RequiredPermissionsApplicationPermissionKey(); spec353RequiredPermissionsSeedRows($environment, missingKeys: [$missingPermissionKey]); $response = $this->actingAs($user) ->withSession([ WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id, ]) ->get(RequiredPermissionsLinks::requiredPermissions($environment)) ->assertSuccessful(); $content = $response->getContent(); $primaryActionUrl = RequiredPermissionsLinks::adminConsentPrimaryUrl($environment); expect($content)->toContain(__('localization.provider_guidance.required_permissions_missing_title')) ->and($content)->toContain($missingPermissionKey) ->and(strpos($content, 'data-testid="provider-readiness-guidance-card"'))->toBeLessThan(strpos($content, $missingPermissionKey)) ->and($content)->toContain('data-testid="provider-readiness-primary-action"') ->and($content)->toContain('href="'.e($primaryActionUrl).'"'); }); it('shows run-verification guidance when stored verification evidence is stale or absent', function (): void { [$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'owner', ensureDefaultMicrosoftProviderConnection: false); ProviderConnection::factory()->platform()->consentGranted()->create([ 'managed_environment_id' => (int) $environment->getKey(), 'workspace_id' => (int) $environment->workspace_id, 'is_default' => true, 'verification_status' => ProviderVerificationStatus::Unknown->value, 'last_health_check_at' => null, ]); spec353RequiredPermissionsSeedRows( $environment, lastCheckedAt: now()->subDays(45)->toIso8601String(), ); $this->actingAs($user) ->withSession([ WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id, ]) ->get(RequiredPermissionsLinks::requiredPermissions($environment)) ->assertSuccessful() ->assertSee(__('localization.provider_guidance.verification_required_title')) ->assertSee(__('localization.provider_guidance.action_run_provider_verification')) ->assertSee('wire:click="runProviderVerification"', false) ->assertDontSee('Start verification'); }); it('renders required-permissions guidance without Graph, outbound http, or queue dispatches', function (): void { bindFailHardGraphClient(); [$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'owner', ensureDefaultMicrosoftProviderConnection: false); ProviderConnection::factory()->platform()->verifiedHealthy()->create([ 'managed_environment_id' => (int) $environment->getKey(), 'workspace_id' => (int) $environment->workspace_id, 'is_default' => true, ]); spec353RequiredPermissionsSeedRows($environment); Queue::fake(); assertNoOutboundHttp(function () use ($user, $environment): void { $this->actingAs($user) ->withSession([ WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id, ]) ->get(RequiredPermissionsLinks::requiredPermissions($environment)) ->assertSuccessful(); }); Queue::assertNothingPushed(); });