Skip to content

Commit 17f0bd1

Browse files
committed
minor #410 [Platform][OpenAI] Add tests (OskarStark)
This PR was squashed before being merged into the main branch. Discussion ---------- [Platform][OpenAI] Add tests | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | Docs? | no | Issues | -- | License | MIT Commits ------- 4b6eb99 [Platform][OpenAI] Add tests
2 parents 5f5d18d + 4b6eb99 commit 17f0bd1

File tree

6 files changed

+411
-0
lines changed

6 files changed

+411
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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\OpenAi\Embeddings;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\TestWith;
17+
use PHPUnit\Framework\Attributes\UsesClass;
18+
use PHPUnit\Framework\TestCase;
19+
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
20+
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings\ModelClient;
21+
use Symfony\AI\Platform\Exception\InvalidArgumentException;
22+
use Symfony\Component\HttpClient\MockHttpClient;
23+
use Symfony\Component\HttpClient\Response\MockResponse;
24+
use Symfony\Contracts\HttpClient\ResponseInterface as HttpResponse;
25+
26+
/**
27+
* @author Oskar Stark <[email protected]>
28+
*/
29+
#[CoversClass(ModelClient::class)]
30+
#[UsesClass(Embeddings::class)]
31+
#[Small]
32+
final class ModelClientTest extends TestCase
33+
{
34+
public function testItThrowsExceptionWhenApiKeyIsEmpty()
35+
{
36+
$this->expectException(InvalidArgumentException::class);
37+
$this->expectExceptionMessage('The API key must not be empty.');
38+
39+
new ModelClient(new MockHttpClient(), '');
40+
}
41+
42+
#[TestWith(['api-key-without-prefix'])]
43+
#[TestWith(['pk-api-key'])]
44+
#[TestWith(['SK-api-key'])]
45+
#[TestWith(['skapikey'])]
46+
#[TestWith(['sk api-key'])]
47+
#[TestWith(['sk'])]
48+
public function testItThrowsExceptionWhenApiKeyDoesNotStartWithSk(string $invalidApiKey)
49+
{
50+
$this->expectException(InvalidArgumentException::class);
51+
$this->expectExceptionMessage('The API key must start with "sk-".');
52+
53+
new ModelClient(new MockHttpClient(), $invalidApiKey);
54+
}
55+
56+
public function testItAcceptsValidApiKey()
57+
{
58+
$modelClient = new ModelClient(new MockHttpClient(), 'sk-valid-api-key');
59+
60+
$this->assertInstanceOf(ModelClient::class, $modelClient);
61+
}
62+
63+
public function testItIsSupportingTheCorrectModel()
64+
{
65+
$modelClient = new ModelClient(new MockHttpClient(), 'sk-api-key');
66+
67+
$this->assertTrue($modelClient->supports(new Embeddings()));
68+
}
69+
70+
public function testItIsExecutingTheCorrectRequest()
71+
{
72+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
73+
self::assertSame('POST', $method);
74+
self::assertSame('https://api.openai.com/v1/embeddings', $url);
75+
self::assertSame('Authorization: Bearer sk-api-key', $options['normalized_headers']['authorization'][0]);
76+
self::assertSame('{"model":"text-embedding-3-small","input":"test text"}', $options['body']);
77+
78+
return new MockResponse();
79+
};
80+
$httpClient = new MockHttpClient([$resultCallback]);
81+
$modelClient = new ModelClient($httpClient, 'sk-api-key');
82+
$modelClient->request(new Embeddings(), 'test text', []);
83+
}
84+
85+
public function testItIsExecutingTheCorrectRequestWithCustomOptions()
86+
{
87+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
88+
self::assertSame('POST', $method);
89+
self::assertSame('https://api.openai.com/v1/embeddings', $url);
90+
self::assertSame('Authorization: Bearer sk-api-key', $options['normalized_headers']['authorization'][0]);
91+
self::assertSame('{"dimensions":256,"model":"text-embedding-3-large","input":"test text"}', $options['body']);
92+
93+
return new MockResponse();
94+
};
95+
$httpClient = new MockHttpClient([$resultCallback]);
96+
$modelClient = new ModelClient($httpClient, 'sk-api-key');
97+
$modelClient->request(new Embeddings(Embeddings::TEXT_3_LARGE), 'test text', ['dimensions' => 256]);
98+
}
99+
100+
public function testItIsExecutingTheCorrectRequestWithArrayInput()
101+
{
102+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
103+
self::assertSame('POST', $method);
104+
self::assertSame('https://api.openai.com/v1/embeddings', $url);
105+
self::assertSame('Authorization: Bearer sk-api-key', $options['normalized_headers']['authorization'][0]);
106+
self::assertSame('{"model":"text-embedding-3-small","input":["text1","text2","text3"]}', $options['body']);
107+
108+
return new MockResponse();
109+
};
110+
$httpClient = new MockHttpClient([$resultCallback]);
111+
$modelClient = new ModelClient($httpClient, 'sk-api-key');
112+
$modelClient->request(new Embeddings(), ['text1', 'text2', 'text3'], []);
113+
}
114+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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\OpenAi;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\TestCase;
17+
use Symfony\AI\Platform\Bridge\OpenAi\Embeddings;
18+
19+
/**
20+
* @author Oskar Stark <[email protected]>
21+
*/
22+
#[CoversClass(Embeddings::class)]
23+
#[Small]
24+
final class EmbeddingsTest extends TestCase
25+
{
26+
public function testItCreatesEmbeddingsWithDefaultSettings()
27+
{
28+
$embeddings = new Embeddings();
29+
30+
$this->assertSame(Embeddings::TEXT_3_SMALL, $embeddings->getName());
31+
$this->assertSame([], $embeddings->getOptions());
32+
}
33+
34+
public function testItCreatesEmbeddingsWithCustomSettings()
35+
{
36+
$embeddings = new Embeddings(Embeddings::TEXT_3_LARGE, ['dimensions' => 256]);
37+
38+
$this->assertSame(Embeddings::TEXT_3_LARGE, $embeddings->getName());
39+
$this->assertSame(['dimensions' => 256], $embeddings->getOptions());
40+
}
41+
42+
public function testItCreatesEmbeddingsWithAdaModel()
43+
{
44+
$embeddings = new Embeddings(Embeddings::TEXT_ADA_002);
45+
46+
$this->assertSame(Embeddings::TEXT_ADA_002, $embeddings->getName());
47+
}
48+
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
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\OpenAi\Gpt;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\Attributes\TestWith;
17+
use PHPUnit\Framework\Attributes\UsesClass;
18+
use PHPUnit\Framework\TestCase;
19+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
20+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt\ModelClient;
21+
use Symfony\AI\Platform\Exception\InvalidArgumentException;
22+
use Symfony\Component\HttpClient\EventSourceHttpClient;
23+
use Symfony\Component\HttpClient\MockHttpClient;
24+
use Symfony\Component\HttpClient\Response\MockResponse;
25+
use Symfony\Contracts\HttpClient\ResponseInterface as HttpResponse;
26+
27+
/**
28+
* @author Oskar Stark <[email protected]>
29+
*/
30+
#[CoversClass(ModelClient::class)]
31+
#[UsesClass(Gpt::class)]
32+
#[Small]
33+
final class ModelClientTest extends TestCase
34+
{
35+
public function testItThrowsExceptionWhenApiKeyIsEmpty()
36+
{
37+
$this->expectException(InvalidArgumentException::class);
38+
$this->expectExceptionMessage('The API key must not be empty.');
39+
40+
new ModelClient(new MockHttpClient(), '');
41+
}
42+
43+
#[TestWith(['api-key-without-prefix'])]
44+
#[TestWith(['pk-api-key'])]
45+
#[TestWith(['SK-api-key'])]
46+
#[TestWith(['skapikey'])]
47+
#[TestWith(['sk api-key'])]
48+
#[TestWith(['sk'])]
49+
public function testItThrowsExceptionWhenApiKeyDoesNotStartWithSk(string $invalidApiKey)
50+
{
51+
$this->expectException(InvalidArgumentException::class);
52+
$this->expectExceptionMessage('The API key must start with "sk-".');
53+
54+
new ModelClient(new MockHttpClient(), $invalidApiKey);
55+
}
56+
57+
public function testItAcceptsValidApiKey()
58+
{
59+
$modelClient = new ModelClient(new MockHttpClient(), 'sk-valid-api-key');
60+
61+
$this->assertInstanceOf(ModelClient::class, $modelClient);
62+
}
63+
64+
public function testItWrapsHttpClientInEventSourceHttpClient()
65+
{
66+
$httpClient = new MockHttpClient();
67+
$modelClient = new ModelClient($httpClient, 'sk-valid-api-key');
68+
69+
$this->assertInstanceOf(ModelClient::class, $modelClient);
70+
}
71+
72+
public function testItAcceptsEventSourceHttpClientDirectly()
73+
{
74+
$httpClient = new EventSourceHttpClient(new MockHttpClient());
75+
$modelClient = new ModelClient($httpClient, 'sk-valid-api-key');
76+
77+
$this->assertInstanceOf(ModelClient::class, $modelClient);
78+
}
79+
80+
public function testItIsSupportingTheCorrectModel()
81+
{
82+
$modelClient = new ModelClient(new MockHttpClient(), 'sk-api-key');
83+
84+
$this->assertTrue($modelClient->supports(new Gpt()));
85+
}
86+
87+
public function testItIsExecutingTheCorrectRequest()
88+
{
89+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
90+
self::assertSame('POST', $method);
91+
self::assertSame('https://api.openai.com/v1/chat/completions', $url);
92+
self::assertSame('Authorization: Bearer sk-api-key', $options['normalized_headers']['authorization'][0]);
93+
self::assertSame('{"temperature":1,"model":"gpt-4o","messages":[{"role":"user","content":"test message"}]}', $options['body']);
94+
95+
return new MockResponse();
96+
};
97+
$httpClient = new MockHttpClient([$resultCallback]);
98+
$modelClient = new ModelClient($httpClient, 'sk-api-key');
99+
$modelClient->request(new Gpt(), ['model' => 'gpt-4o', 'messages' => [['role' => 'user', 'content' => 'test message']]], ['temperature' => 1]);
100+
}
101+
102+
public function testItIsExecutingTheCorrectRequestWithArrayPayload()
103+
{
104+
$resultCallback = static function (string $method, string $url, array $options): HttpResponse {
105+
self::assertSame('POST', $method);
106+
self::assertSame('https://api.openai.com/v1/chat/completions', $url);
107+
self::assertSame('Authorization: Bearer sk-api-key', $options['normalized_headers']['authorization'][0]);
108+
self::assertSame('{"temperature":0.7,"model":"gpt-4o","messages":[{"role":"user","content":"Hello"}]}', $options['body']);
109+
110+
return new MockResponse();
111+
};
112+
$httpClient = new MockHttpClient([$resultCallback]);
113+
$modelClient = new ModelClient($httpClient, 'sk-api-key');
114+
$modelClient->request(new Gpt(), ['model' => 'gpt-4o', 'messages' => [['role' => 'user', 'content' => 'Hello']]], ['temperature' => 0.7]);
115+
}
116+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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\OpenAi;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\TestCase;
17+
use Symfony\AI\Platform\Bridge\OpenAi\Gpt;
18+
19+
/**
20+
* @author Oskar Stark <[email protected]>
21+
*/
22+
#[CoversClass(Gpt::class)]
23+
#[Small]
24+
final class GptTest extends TestCase
25+
{
26+
public function testItCreatesGptWithDefaultSettings()
27+
{
28+
$gpt = new Gpt();
29+
30+
$this->assertSame(Gpt::GPT_4O, $gpt->getName());
31+
$this->assertSame(['temperature' => 1.0], $gpt->getOptions());
32+
}
33+
34+
public function testItCreatesGptWithCustomSettings()
35+
{
36+
$gpt = new Gpt(Gpt::GPT_4_TURBO, ['temperature' => 0.5, 'max_tokens' => 1000]);
37+
38+
$this->assertSame(Gpt::GPT_4_TURBO, $gpt->getName());
39+
$this->assertSame(['temperature' => 0.5, 'max_tokens' => 1000], $gpt->getOptions());
40+
}
41+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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\OpenAi;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\Attributes\Small;
16+
use PHPUnit\Framework\TestCase;
17+
use Symfony\AI\Platform\Bridge\OpenAi\PlatformFactory;
18+
use Symfony\AI\Platform\Platform;
19+
use Symfony\Component\HttpClient\EventSourceHttpClient;
20+
use Symfony\Component\HttpClient\MockHttpClient;
21+
22+
/**
23+
* @author Oskar Stark <[email protected]>
24+
*/
25+
#[CoversClass(PlatformFactory::class)]
26+
#[Small]
27+
final class PlatformFactoryTest extends TestCase
28+
{
29+
public function testItCreatesPlatformWithDefaultSettings()
30+
{
31+
$platform = PlatformFactory::create('sk-test-api-key');
32+
33+
$this->assertInstanceOf(Platform::class, $platform);
34+
}
35+
36+
public function testItCreatesPlatformWithCustomHttpClient()
37+
{
38+
$httpClient = new MockHttpClient();
39+
$platform = PlatformFactory::create('sk-test-api-key', $httpClient);
40+
41+
$this->assertInstanceOf(Platform::class, $platform);
42+
}
43+
44+
public function testItCreatesPlatformWithEventSourceHttpClient()
45+
{
46+
$httpClient = new EventSourceHttpClient(new MockHttpClient());
47+
$platform = PlatformFactory::create('sk-test-api-key', $httpClient);
48+
49+
$this->assertInstanceOf(Platform::class, $platform);
50+
}
51+
}

0 commit comments

Comments
 (0)