Skip to content

Commit eb67ca8

Browse files
committed
[Platform][HuggingFace] Add tests for Bridge components
1 parent db5ea6e commit eb67ca8

File tree

3 files changed

+452
-0
lines changed

3 files changed

+452
-0
lines changed
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\TestDox;
17+
use PHPUnit\Framework\Attributes\UsesClass;
18+
use PHPUnit\Framework\TestCase;
19+
use Symfony\AI\Platform\Bridge\HuggingFace\ApiClient;
20+
use Symfony\AI\Platform\Model;
21+
use Symfony\Component\HttpClient\MockHttpClient;
22+
use Symfony\Component\HttpClient\Response\JsonMockResponse;
23+
24+
/**
25+
* @author Oskar Stark <[email protected]>
26+
*/
27+
#[CoversClass(ApiClient::class)]
28+
#[Small]
29+
#[UsesClass(Model::class)]
30+
final class ApiClientTest extends TestCase
31+
{
32+
#[TestDox('Returns array of Model objects when API responds with model data')]
33+
public function testModelsWithProviderAndTask()
34+
{
35+
$responseData = [
36+
['id' => 'model-1'],
37+
['id' => 'model-2'],
38+
['id' => 'model-3'],
39+
];
40+
41+
$httpClient = new MockHttpClient(new JsonMockResponse($responseData));
42+
$apiClient = new ApiClient($httpClient);
43+
44+
$models = $apiClient->models('test-provider', 'text-generation');
45+
46+
$this->assertCount(3, $models);
47+
$this->assertInstanceOf(Model::class, $models[0]);
48+
$this->assertSame('model-1', $models[0]->getName());
49+
$this->assertSame('model-2', $models[1]->getName());
50+
$this->assertSame('model-3', $models[2]->getName());
51+
}
52+
53+
#[TestDox('Handles null provider and task parameters correctly')]
54+
public function testModelsWithNullProviderAndTask()
55+
{
56+
$responseData = [
57+
['id' => 'model-1'],
58+
['id' => 'model-2'],
59+
];
60+
61+
$httpClient = new MockHttpClient(new JsonMockResponse($responseData));
62+
$apiClient = new ApiClient($httpClient);
63+
64+
$models = $apiClient->models(null, null);
65+
66+
$this->assertCount(2, $models);
67+
$this->assertInstanceOf(Model::class, $models[0]);
68+
$this->assertSame('model-1', $models[0]->getName());
69+
$this->assertSame('model-2', $models[1]->getName());
70+
}
71+
72+
#[TestDox('Returns empty array when API responds with no models')]
73+
public function testModelsWithEmptyResponse()
74+
{
75+
$responseData = [];
76+
77+
$httpClient = new MockHttpClient(new JsonMockResponse($responseData));
78+
$apiClient = new ApiClient($httpClient);
79+
80+
$models = $apiClient->models('test-provider', 'text-generation');
81+
82+
$this->assertCount(0, $models);
83+
}
84+
85+
#[TestDox('Sends correct HTTP request with provider and task parameters')]
86+
public function testModelsRequestParameters()
87+
{
88+
$httpClient = new MockHttpClient(function (string $method, string $url, array $options): JsonMockResponse {
89+
$this->assertSame('GET', $method);
90+
$this->assertStringStartsWith('https://huggingface.co/api/models', $url);
91+
$this->assertArrayHasKey('query', $options);
92+
$this->assertSame('test-provider', $options['query']['inference_provider']);
93+
$this->assertSame('text-generation', $options['query']['pipeline_tag']);
94+
95+
return new JsonMockResponse([]);
96+
});
97+
98+
$apiClient = new ApiClient($httpClient);
99+
$apiClient->models('test-provider', 'text-generation');
100+
}
101+
102+
#[TestDox('Sends correct HTTP request with null provider and task parameters')]
103+
public function testModelsRequestParametersWithNullValues()
104+
{
105+
$httpClient = new MockHttpClient(function (string $method, string $url, array $options): JsonMockResponse {
106+
$this->assertSame('GET', $method);
107+
$this->assertStringStartsWith('https://huggingface.co/api/models', $url);
108+
$this->assertArrayHasKey('query', $options);
109+
$this->assertNull($options['query']['inference_provider']);
110+
$this->assertNull($options['query']['pipeline_tag']);
111+
112+
return new JsonMockResponse([]);
113+
});
114+
115+
$apiClient = new ApiClient($httpClient);
116+
$apiClient->models(null, null);
117+
}
118+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Platform\Tests\Bridge\HuggingFace;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\TestDox;
17+
use PHPUnit\Framework\Attributes\TestWith;
18+
use PHPUnit\Framework\Attributes\UsesClass;
19+
use PHPUnit\Framework\TestCase;
20+
use Symfony\AI\Platform\Bridge\HuggingFace\Contract\FileNormalizer;
21+
use Symfony\AI\Platform\Bridge\HuggingFace\Contract\MessageBagNormalizer;
22+
use Symfony\AI\Platform\Bridge\HuggingFace\ModelClient;
23+
use Symfony\AI\Platform\Bridge\HuggingFace\PlatformFactory;
24+
use Symfony\AI\Platform\Bridge\HuggingFace\Provider;
25+
use Symfony\AI\Platform\Bridge\HuggingFace\ResultConverter;
26+
use Symfony\AI\Platform\Contract;
27+
use Symfony\AI\Platform\Platform;
28+
use Symfony\Component\HttpClient\EventSourceHttpClient;
29+
use Symfony\Component\HttpClient\MockHttpClient;
30+
31+
/**
32+
* @author Oskar Stark <[email protected]>
33+
*/
34+
#[CoversClass(PlatformFactory::class)]
35+
#[Small]
36+
#[UsesClass(Platform::class)]
37+
#[UsesClass(ModelClient::class)]
38+
#[UsesClass(ResultConverter::class)]
39+
#[UsesClass(Contract::class)]
40+
#[UsesClass(FileNormalizer::class)]
41+
#[UsesClass(MessageBagNormalizer::class)]
42+
final class PlatformFactoryTest extends TestCase
43+
{
44+
#[TestDox('Creates Platform with default provider and auto-generated components')]
45+
public function testCreateWithDefaults()
46+
{
47+
$platform = PlatformFactory::create('test-api-key');
48+
49+
$this->assertInstanceOf(Platform::class, $platform);
50+
}
51+
52+
#[TestDox('Creates Platform with custom provider')]
53+
public function testCreateWithCustomProvider()
54+
{
55+
$platform = PlatformFactory::create('test-api-key', Provider::COHERE);
56+
57+
$this->assertInstanceOf(Platform::class, $platform);
58+
}
59+
60+
#[TestDox('Handles EventSourceHttpClient correctly')]
61+
public function testCreateWithEventSourceHttpClient()
62+
{
63+
$httpClient = new EventSourceHttpClient(new MockHttpClient());
64+
$platform = PlatformFactory::create('test-api-key', Provider::HF_INFERENCE, $httpClient);
65+
66+
$this->assertInstanceOf(Platform::class, $platform);
67+
}
68+
69+
#[TestDox('Creates Platform successfully with all supported providers')]
70+
#[TestWith([Provider::CEREBRAS])]
71+
#[TestWith([Provider::COHERE])]
72+
#[TestWith([Provider::FAL_AI])]
73+
#[TestWith([Provider::FIREWORKS])]
74+
#[TestWith([Provider::HYPERBOLIC])]
75+
#[TestWith([Provider::HF_INFERENCE])]
76+
#[TestWith([Provider::NEBIUS])]
77+
#[TestWith([Provider::NOVITA])]
78+
#[TestWith([Provider::REPLICATE])]
79+
#[TestWith([Provider::SAMBA_NOVA])]
80+
#[TestWith([Provider::TOGETHER])]
81+
public function testCreateWithDifferentProviders(string $provider)
82+
{
83+
$platform = PlatformFactory::create('test-api-key', $provider);
84+
$this->assertInstanceOf(Platform::class, $platform);
85+
}
86+
}

0 commit comments

Comments
 (0)