212 lines
5.7 KiB
PHP
Executable File
212 lines
5.7 KiB
PHP
Executable File
<?php
|
|
|
|
namespace OpenAI\Testing;
|
|
|
|
use OpenAI\Contracts\ClientContract;
|
|
use OpenAI\Contracts\Resources\VectorStoresContract;
|
|
use OpenAI\Contracts\ResponseContract;
|
|
use OpenAI\Contracts\ResponseStreamContract;
|
|
use OpenAI\Responses\StreamResponse;
|
|
use OpenAI\Testing\Requests\TestRequest;
|
|
use OpenAI\Testing\Resources\AssistantsTestResource;
|
|
use OpenAI\Testing\Resources\AudioTestResource;
|
|
use OpenAI\Testing\Resources\BatchesTestResource;
|
|
use OpenAI\Testing\Resources\ChatTestResource;
|
|
use OpenAI\Testing\Resources\CompletionsTestResource;
|
|
use OpenAI\Testing\Resources\EditsTestResource;
|
|
use OpenAI\Testing\Resources\EmbeddingsTestResource;
|
|
use OpenAI\Testing\Resources\FilesTestResource;
|
|
use OpenAI\Testing\Resources\FineTunesTestResource;
|
|
use OpenAI\Testing\Resources\FineTuningTestResource;
|
|
use OpenAI\Testing\Resources\ImagesTestResource;
|
|
use OpenAI\Testing\Resources\ModelsTestResource;
|
|
use OpenAI\Testing\Resources\ModerationsTestResource;
|
|
use OpenAI\Testing\Resources\ThreadsTestResource;
|
|
use OpenAI\Testing\Resources\VectorStoresTestResource;
|
|
use PHPUnit\Framework\Assert as PHPUnit;
|
|
use Throwable;
|
|
|
|
class ClientFake implements ClientContract
|
|
{
|
|
/**
|
|
* @var array<array-key, TestRequest>
|
|
*/
|
|
private array $requests = [];
|
|
|
|
/**
|
|
* @param array<array-key, ResponseContract|StreamResponse|string> $responses
|
|
*/
|
|
public function __construct(protected array $responses = [])
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @param array<array-key, Response> $responses
|
|
*/
|
|
public function addResponses(array $responses): void
|
|
{
|
|
$this->responses = [...$this->responses, ...$responses];
|
|
}
|
|
|
|
public function assertSent(string $resource, callable|int|null $callback = null): void
|
|
{
|
|
if (is_int($callback)) {
|
|
$this->assertSentTimes($resource, $callback);
|
|
|
|
return;
|
|
}
|
|
|
|
PHPUnit::assertTrue(
|
|
$this->sent($resource, $callback) !== [],
|
|
"The expected [{$resource}] request was not sent."
|
|
);
|
|
}
|
|
|
|
private function assertSentTimes(string $resource, int $times = 1): void
|
|
{
|
|
$count = count($this->sent($resource));
|
|
|
|
PHPUnit::assertSame(
|
|
$times, $count,
|
|
"The expected [{$resource}] resource was sent {$count} times instead of {$times} times."
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return mixed[]
|
|
*/
|
|
private function sent(string $resource, ?callable $callback = null): array
|
|
{
|
|
if (! $this->hasSent($resource)) {
|
|
return [];
|
|
}
|
|
|
|
$callback = $callback ?: fn (): bool => true;
|
|
|
|
return array_filter($this->resourcesOf($resource), fn (TestRequest $resource) => $callback($resource->method(), ...$resource->args()));
|
|
}
|
|
|
|
private function hasSent(string $resource): bool
|
|
{
|
|
return $this->resourcesOf($resource) !== [];
|
|
}
|
|
|
|
public function assertNotSent(string $resource, ?callable $callback = null): void
|
|
{
|
|
PHPUnit::assertCount(
|
|
0, $this->sent($resource, $callback),
|
|
"The unexpected [{$resource}] request was sent."
|
|
);
|
|
}
|
|
|
|
public function assertNothingSent(): void
|
|
{
|
|
$resourceNames = implode(
|
|
separator: ', ',
|
|
array: array_map(fn (TestRequest $request): string => $request->resource(), $this->requests)
|
|
);
|
|
|
|
PHPUnit::assertEmpty($this->requests, 'The following requests were sent unexpectedly: '.$resourceNames);
|
|
}
|
|
|
|
/**
|
|
* @return array<array-key, TestRequest>
|
|
*/
|
|
private function resourcesOf(string $type): array
|
|
{
|
|
return array_filter($this->requests, fn (TestRequest $request): bool => $request->resource() === $type);
|
|
}
|
|
|
|
public function record(TestRequest $request): ResponseContract|ResponseStreamContract|string
|
|
{
|
|
$this->requests[] = $request;
|
|
|
|
$response = array_shift($this->responses);
|
|
|
|
if (is_null($response)) {
|
|
throw new \Exception('No fake responses left.');
|
|
}
|
|
|
|
if ($response instanceof Throwable) {
|
|
throw $response;
|
|
}
|
|
|
|
return $response;
|
|
}
|
|
|
|
public function completions(): CompletionsTestResource
|
|
{
|
|
return new CompletionsTestResource($this);
|
|
}
|
|
|
|
public function chat(): ChatTestResource
|
|
{
|
|
return new ChatTestResource($this);
|
|
}
|
|
|
|
public function embeddings(): EmbeddingsTestResource
|
|
{
|
|
return new EmbeddingsTestResource($this);
|
|
}
|
|
|
|
public function audio(): AudioTestResource
|
|
{
|
|
return new AudioTestResource($this);
|
|
}
|
|
|
|
public function edits(): EditsTestResource
|
|
{
|
|
return new EditsTestResource($this);
|
|
}
|
|
|
|
public function files(): FilesTestResource
|
|
{
|
|
return new FilesTestResource($this);
|
|
}
|
|
|
|
public function models(): ModelsTestResource
|
|
{
|
|
return new ModelsTestResource($this);
|
|
}
|
|
|
|
public function fineTunes(): FineTunesTestResource
|
|
{
|
|
return new FineTunesTestResource($this);
|
|
}
|
|
|
|
public function fineTuning(): FineTuningTestResource
|
|
{
|
|
return new FineTuningTestResource($this);
|
|
}
|
|
|
|
public function moderations(): ModerationsTestResource
|
|
{
|
|
return new ModerationsTestResource($this);
|
|
}
|
|
|
|
public function images(): ImagesTestResource
|
|
{
|
|
return new ImagesTestResource($this);
|
|
}
|
|
|
|
public function assistants(): AssistantsTestResource
|
|
{
|
|
return new AssistantsTestResource($this);
|
|
}
|
|
|
|
public function threads(): ThreadsTestResource
|
|
{
|
|
return new ThreadsTestResource($this);
|
|
}
|
|
|
|
public function batches(): BatchesTestResource
|
|
{
|
|
return new BatchesTestResource($this);
|
|
}
|
|
|
|
public function vectorStores(): VectorStoresContract
|
|
{
|
|
return new VectorStoresTestResource($this);
|
|
}
|
|
}
|