Files
laravel-llm-gateway/laravel-app/tests/Unit/Services/DeepSeekProviderTest.php
wtrinkl 6573e15ba4 Add complete Laravel LLM Gateway implementation
Core Features:
- Multi-provider support (OpenAI, Anthropic, DeepSeek, Gemini, Mistral)
- Provider service architecture with abstract base class
- Dynamic model discovery from provider APIs
- Encrypted per-user provider credentials storage

Admin Interface:
- Complete admin panel with Livewire components
- User management with CRUD operations
- API key management with testing capabilities
- Budget system with limits and reset schedules
- Usage logs with filtering and CSV export
- Model pricing management with cost calculator
- Dashboard with Chart.js visualizations

Database Schema:
- MariaDB migrations for all tables
- User provider credentials (encrypted)
- LLM request logging
- Budget tracking and rate limiting
- Model pricing configuration

API Implementation:
- OpenAI-compatible endpoints
- Budget checking middleware
- Rate limit enforcement
- Request logging jobs
- Cost calculation service

Testing:
- Unit tests for all provider services
- Provider factory tests
- Cost calculator tests

Documentation:
- Admin user seeder
- Model pricing seeder
- Configuration files
2025-11-18 22:18:36 +01:00

129 lines
4.0 KiB
PHP

<?php
namespace Tests\Unit\Services;
use Tests\TestCase;
use App\Services\LLM\Providers\DeepSeekProvider;
use App\Models\ModelPricing;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Cache;
use Illuminate\Foundation\Testing\RefreshDatabase;
class DeepSeekProviderTest extends TestCase
{
use RefreshDatabase;
private DeepSeekProvider $provider;
protected function setUp(): void
{
parent::setUp();
$this->provider = new DeepSeekProvider('test-api-key');
}
public function test_builds_request_correctly(): void
{
$messages = [
['role' => 'user', 'content' => 'Write a function']
];
$options = [
'model' => 'deepseek-coder',
'temperature' => 0.5,
'max_tokens' => 1500
];
$reflection = new \ReflectionClass($this->provider);
$method = $reflection->getMethod('buildRequest');
$method->setAccessible(true);
$result = $method->invoke($this->provider, $messages, $options);
$this->assertEquals('deepseek-coder', $result['model']);
$this->assertEquals(0.5, $result['temperature']);
$this->assertEquals(1500, $result['max_tokens']);
$this->assertEquals($messages, $result['messages']);
$this->assertFalse($result['stream']);
}
public function test_normalizes_response_correctly(): void
{
$rawResponse = [
'id' => 'deepseek-123',
'model' => 'deepseek-coder',
'choices' => [
[
'message' => [
'role' => 'assistant',
'content' => 'def hello_world():\n print("Hello, World!")'
],
'finish_reason' => 'stop'
]
],
'usage' => [
'prompt_tokens' => 8,
'completion_tokens' => 22,
'total_tokens' => 30
]
];
$normalized = $this->provider->normalizeResponse($rawResponse);
$this->assertEquals('deepseek-123', $normalized['id']);
$this->assertEquals('deepseek-coder', $normalized['model']);
$this->assertStringContainsString('def hello_world()', $normalized['content']);
$this->assertEquals('assistant', $normalized['role']);
$this->assertEquals('stop', $normalized['finish_reason']);
$this->assertEquals(8, $normalized['usage']['prompt_tokens']);
$this->assertEquals(22, $normalized['usage']['completion_tokens']);
$this->assertEquals(30, $normalized['usage']['total_tokens']);
}
public function test_calculates_cost_correctly(): void
{
ModelPricing::updateOrCreate(
[
'provider' => 'deepseek',
'model' => 'deepseek-chat',
'effective_from' => now()->toDateString(),
],
[
'input_price_per_million' => 0.14,
'output_price_per_million' => 0.28,
'is_active' => true,
]
);
Cache::flush();
$cost = $this->provider->calculateCost(1000, 500, 'deepseek-chat');
// Expected: (1000/1M * 0.14) + (500/1M * 0.28) = 0.00014 + 0.00014 = 0.00028
$this->assertEquals(0.00028, $cost);
}
public function test_handles_api_errors(): void
{
Http::fake([
'https://api.deepseek.com/*' => Http::response(['error' => 'Invalid API key'], 401)
]);
$this->expectException(\App\Exceptions\ProviderException::class);
$this->expectExceptionMessage('Invalid API key');
$this->provider->chatCompletion([
['role' => 'user', 'content' => 'test']
]);
}
public function test_get_supported_models(): void
{
$models = $this->provider->getSupportedModels();
$this->assertIsArray($models);
$this->assertContains('deepseek-chat', $models);
$this->assertContains('deepseek-coder', $models);
$this->assertContains('deepseek-reasoner', $models);
}
}