New_Micro_Learning/backend/tests/Feature/AI/AiProviderResolverTest.php

80 خطوط
3.1 KiB
PHP

<?php
namespace Tests\Feature\AI;
use App\Modules\AI\Application\AiProviderResolver;
use App\Modules\Organizations\Domain\Organization;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use RuntimeException;
use Tests\TestCase;
class AiProviderResolverTest extends TestCase
{
use RefreshDatabase;
public function test_resolver_deterministically_selects_the_default_enabled_connection(): void
{
$organization = Organization::factory()->create();
$this->connection($organization->id, '01J00000000000000000000001', enabled: true, default: false, createdAt: '2026-01-01 00:00:00');
$this->connection($organization->id, '01J00000000000000000000002', enabled: true, default: true, createdAt: '2026-01-02 00:00:00');
$provider = app(AiProviderResolver::class)->forOrganization($organization->id);
$this->assertSame('connection:01J00000000000000000000002', $provider->id());
}
public function test_disabled_deleted_and_cross_tenant_connections_cannot_be_resolved(): void
{
$first = Organization::factory()->create();
$second = Organization::factory()->create();
$id = '01J00000000000000000000003';
$this->connection($first->id, $id, enabled: false, default: false);
$resolver = app(AiProviderResolver::class);
foreach ([$first->id, $second->id] as $organizationId) {
try {
$resolver->byId('connection:'.$id, $organizationId);
$this->fail('Unavailable connection must not resolve.');
} catch (RuntimeException) {
$this->addToAssertionCount(1);
}
}
DB::table('ai_provider_connections')->where('id', $id)->delete();
$this->expectException(RuntimeException::class);
$resolver->byId('connection:'.$id, $first->id);
}
public function test_failed_external_provider_falls_back_to_the_local_provider_deterministically(): void
{
$organization = Organization::factory()->create();
$fallback = app(AiProviderResolver::class)->fallbackForOrganization($organization->id, 'connection:failed');
$this->assertNotNull($fallback);
$this->assertSame('local-structuring-v1', $fallback->id());
$this->assertNull(app(AiProviderResolver::class)->fallbackForOrganization($organization->id, 'local'));
}
private function connection(string $organizationId, string $id, bool $enabled, bool $default, string $createdAt = '2026-01-01 00:00:00'): void
{
DB::table('ai_provider_connections')->insert([
'id' => $id,
'organization_id' => $organizationId,
'name' => $id,
'provider' => 'ollama',
'mode' => 'local',
'base_url' => 'http://127.0.0.1:11434/v1',
'models' => json_encode(['qwen']),
'default_model' => 'qwen',
'timeout_seconds' => 30,
'enabled' => $enabled,
'is_default' => $default,
'created_at' => $createdAt,
'updated_at' => $createdAt,
]);
}
}