From d406967dbfb781c57de7588a85408536bc3eeb4a Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Fri, 29 Aug 2025 13:14:51 +0200 Subject: [PATCH] [Store][Voyage] Add unit test for `ResultConverter` --- .../Bridge/Voyage/ResultConverterTest.php | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/platform/tests/Bridge/Voyage/ResultConverterTest.php diff --git a/src/platform/tests/Bridge/Voyage/ResultConverterTest.php b/src/platform/tests/Bridge/Voyage/ResultConverterTest.php new file mode 100644 index 000000000..807aba097 --- /dev/null +++ b/src/platform/tests/Bridge/Voyage/ResultConverterTest.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\AI\Platform\Tests\Bridge\Voyage; + +use PHPUnit\Framework\Attributes\CoversClass; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Small; +use PHPUnit\Framework\Attributes\UsesClass; +use PHPUnit\Framework\TestCase; +use Symfony\AI\Platform\Bridge\Voyage\ResultConverter; +use Symfony\AI\Platform\Bridge\Voyage\Voyage; +use Symfony\AI\Platform\Exception\RuntimeException; +use Symfony\AI\Platform\Result\RawHttpResult; +use Symfony\AI\Platform\Result\VectorResult; +use Symfony\AI\Platform\Vector\Vector; +use Symfony\Contracts\HttpClient\ResponseInterface; + +/** + * @author Oskar Stark + */ +#[CoversClass(ResultConverter::class)] +#[Small] +#[UsesClass(Vector::class)] +#[UsesClass(VectorResult::class)] +#[UsesClass(Voyage::class)] +class ResultConverterTest extends TestCase +{ + public function testItConvertsAResponseToAVectorResult() + { + $result = $this->createStub(ResponseInterface::class); + $result + ->method('toArray') + ->willReturn([ + 'data' => [ + [ + 'embedding' => [0.1, 0.2, 0.3], + ], + ], + ]); + + $converter = new ResultConverter(); + $vectorResult = $converter->convert(new RawHttpResult($result)); + + $this->assertInstanceOf(VectorResult::class, $vectorResult); + $this->assertSame([0.1, 0.2, 0.3], $vectorResult->getContent()[0]->getData()); + } + + public function testItConvertsMultipleEmbeddings() + { + $result = $this->createStub(ResponseInterface::class); + $result + ->method('toArray') + ->willReturn([ + 'data' => [ + [ + 'embedding' => [0.1, 0.2, 0.3], + ], + [ + 'embedding' => [0.4, 0.5, 0.6], + ], + ], + ]); + + $converter = new ResultConverter(); + $vectorResult = $converter->convert(new RawHttpResult($result)); + + $this->assertInstanceOf(VectorResult::class, $vectorResult); + // The converter returns only the first vector + $this->assertSame([0.1, 0.2, 0.3], $vectorResult->getContent()[0]->getData()); + } + + public function testItThrowsExceptionWhenResponseDoesNotContainData() + { + $result = $this->createStub(ResponseInterface::class); + $result + ->method('toArray') + ->willReturn(['invalid' => 'response']); + + $converter = new ResultConverter(); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Response does not contain embedding data.'); + + $converter->convert(new RawHttpResult($result)); + } + + #[DataProvider('voyageModelsProvider')] + public function testItSupportsVoyageModel(string $modelName) + { + $converter = new ResultConverter(); + + $this->assertTrue($converter->supports(new Voyage($modelName))); + } + + public static function voyageModelsProvider(): iterable + { + yield 'V3' => [Voyage::V3]; + yield 'V3_LITE' => [Voyage::V3_LITE]; + yield 'FINANCE_2' => [Voyage::FINANCE_2]; + yield 'MULTILINGUAL_2' => [Voyage::MULTILINGUAL_2]; + yield 'LAW_2' => [Voyage::LAW_2]; + yield 'CODE_2' => [Voyage::CODE_2]; + } +}