mirror of
https://github.com/BushlanovDev/max-bot-api-client-php.git
synced 2026-10-08 21:08:52 +00:00
Added PhotoAttachment
This commit is contained in:
@@ -11,10 +11,14 @@ use BushlanovDev\MaxMessengerBot\Enums\AttachmentType;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\ButtonType;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\MessageFormat;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\UpdateType;
|
||||
use BushlanovDev\MaxMessengerBot\Enums\UploadType;
|
||||
use BushlanovDev\MaxMessengerBot\ModelFactory;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Attachments\Buttons\CallbackButton;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\InlineKeyboardPayload;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\PhotoAttachmentPayload;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\PhotoToken;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\InlineKeyboardAttachmentRequest;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Attachments\Requests\PhotoAttachmentRequest;
|
||||
use BushlanovDev\MaxMessengerBot\Models\BotInfo;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Message;
|
||||
use BushlanovDev\MaxMessengerBot\Models\MessageBody;
|
||||
@@ -22,6 +26,8 @@ use BushlanovDev\MaxMessengerBot\Models\Recipient;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Result;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Sender;
|
||||
use BushlanovDev\MaxMessengerBot\Models\Subscription;
|
||||
use BushlanovDev\MaxMessengerBot\Models\UploadEndpoint;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\Attributes\UsesClass;
|
||||
@@ -42,6 +48,10 @@ use ReflectionClass;
|
||||
#[UsesClass(CallbackButton::class)]
|
||||
#[UsesClass(InlineKeyboardPayload::class)]
|
||||
#[UsesClass(InlineKeyboardAttachmentRequest::class)]
|
||||
#[UsesClass(PhotoToken::class)]
|
||||
#[UsesClass(PhotoAttachmentRequest::class)]
|
||||
#[UsesClass(PhotoAttachmentPayload::class)]
|
||||
#[UsesClass(UploadEndpoint::class)]
|
||||
final class ApiTest extends TestCase
|
||||
{
|
||||
private MockObject&ClientApiInterface $clientMock;
|
||||
@@ -368,4 +378,76 @@ final class ApiTest extends TestCase
|
||||
|
||||
$this->assertSame($expectedMessageObject, $result);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function uploadAttachmentSuccessfullyUploadsImageAndReturnsAttachment(): void
|
||||
{
|
||||
$filePath = tempnam(sys_get_temp_dir(), 'test_upload_');
|
||||
file_put_contents($filePath, 'fake-image-content');
|
||||
|
||||
$uploadType = UploadType::Image;
|
||||
$uploadUrl = 'https://upload.server/gohere';
|
||||
$uploadToken = 'FINAL_TOKEN_123';
|
||||
|
||||
$getUploadUrlResponse = ['url' => $uploadUrl];
|
||||
$uploadResponse = ['token' => $uploadToken];
|
||||
$expectedEndpoint = new UploadEndpoint($uploadUrl);
|
||||
$expectedAttachment = PhotoAttachmentRequest::fromToken($uploadToken);
|
||||
|
||||
$this->clientMock
|
||||
->expects($this->once())
|
||||
->method('request')
|
||||
->with('POST', '/uploads', ['type' => $uploadType->value])
|
||||
->willReturn($getUploadUrlResponse);
|
||||
|
||||
$this->modelFactoryMock
|
||||
->expects($this->once())
|
||||
->method('createUploadEndpoint')
|
||||
->with($getUploadUrlResponse)
|
||||
->willReturn($expectedEndpoint);
|
||||
|
||||
$this->clientMock
|
||||
->expects($this->once())
|
||||
->method('upload')
|
||||
->with($uploadUrl, $this->isResource(), basename($filePath))
|
||||
->willReturn($uploadResponse);
|
||||
|
||||
$result = $this->api->uploadAttachment($uploadType, $filePath);
|
||||
|
||||
$this->assertEquals($expectedAttachment, $result);
|
||||
|
||||
unlink($filePath);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function uploadAttachmentForMultiplePhotosReturnsCorrectAttachment(): void
|
||||
{
|
||||
$filePath = tempnam(sys_get_temp_dir(), 'test_');
|
||||
file_put_contents($filePath, 'content');
|
||||
|
||||
$getUploadUrlResponse = ['url' => 'http://upload.server'];
|
||||
$expectedEndpoint = new UploadEndpoint('http://upload.server');
|
||||
|
||||
$uploadResponse = ['token' => 'token'];
|
||||
|
||||
$expectedAttachment = PhotoAttachmentRequest::fromToken('token');
|
||||
|
||||
$this->clientMock->method('request')->willReturn($getUploadUrlResponse);
|
||||
$this->modelFactoryMock->method('createUploadEndpoint')->willReturn($expectedEndpoint);
|
||||
$this->clientMock->method('upload')->willReturn($uploadResponse);
|
||||
|
||||
$result = $this->api->uploadAttachment(UploadType::Image, $filePath);
|
||||
|
||||
$this->assertEquals($expectedAttachment, $result);
|
||||
|
||||
unlink($filePath);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function uploadAttachmentThrowsExceptionForNonExistentFile(): void
|
||||
{
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessageMatches('/File not found or not readable/');
|
||||
$this->api->uploadAttachment(UploadType::Image, '/path/to/non/existent/file.jpg');
|
||||
}
|
||||
}
|
||||
|
||||
+48
-14
@@ -13,6 +13,7 @@ use BushlanovDev\MaxMessengerBot\Exceptions\NotFoundException;
|
||||
use BushlanovDev\MaxMessengerBot\Exceptions\RateLimitExceededException;
|
||||
use BushlanovDev\MaxMessengerBot\Exceptions\SerializationException;
|
||||
use BushlanovDev\MaxMessengerBot\Exceptions\UnauthorizedException;
|
||||
use GuzzleHttp\Psr7\HttpFactory;
|
||||
use InvalidArgumentException;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
@@ -37,7 +38,7 @@ final class ClientTest extends TestCase
|
||||
|
||||
private MockObject&ClientInterface $httpClientMock;
|
||||
private MockObject&RequestFactoryInterface $requestFactoryMock;
|
||||
private MockObject&StreamFactoryInterface $streamFactoryMock;
|
||||
private StreamFactoryInterface $streamFactory;
|
||||
private MockObject&RequestInterface $requestMock;
|
||||
private MockObject&ResponseInterface $responseMock;
|
||||
private MockObject&StreamInterface $streamMock;
|
||||
@@ -56,7 +57,7 @@ final class ClientTest extends TestCase
|
||||
// Create mocks for all PSR interfaces
|
||||
$this->httpClientMock = $this->createMock(ClientInterface::class);
|
||||
$this->requestFactoryMock = $this->createMock(RequestFactoryInterface::class);
|
||||
$this->streamFactoryMock = $this->createMock(StreamFactoryInterface::class);
|
||||
$this->streamFactory = new HttpFactory();
|
||||
$this->requestMock = $this->createMock(RequestInterface::class);
|
||||
$this->responseMock = $this->createMock(ResponseInterface::class);
|
||||
$this->streamMock = $this->createMock(StreamInterface::class);
|
||||
@@ -65,15 +66,13 @@ final class ClientTest extends TestCase
|
||||
$this->requestFactoryMock->method('createRequest')->willReturn($this->requestMock);
|
||||
$this->responseMock->method('getBody')->willReturn($this->streamMock);
|
||||
$this->httpClientMock->method('sendRequest')->willReturn($this->responseMock);
|
||||
$this->requestMock->method('withBody')->willReturn($this->requestMock);
|
||||
$this->requestMock->method('withHeader')->willReturn($this->requestMock);
|
||||
|
||||
// Instantiate the System Under Test (SUT)
|
||||
$this->client = new Client(
|
||||
self::FAKE_TOKEN,
|
||||
$this->httpClientMock,
|
||||
$this->requestFactoryMock,
|
||||
$this->streamFactoryMock,
|
||||
$this->streamFactory,
|
||||
self::API_BASE_URL,
|
||||
self::API_VERSION,
|
||||
);
|
||||
@@ -85,7 +84,7 @@ final class ClientTest extends TestCase
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('Access token cannot be empty.');
|
||||
|
||||
new Client('', $this->httpClientMock, $this->requestFactoryMock, $this->streamFactoryMock, '', '');
|
||||
new Client('', $this->httpClientMock, $this->requestFactoryMock, $this->streamFactory, '', '');
|
||||
}
|
||||
|
||||
#[Test]
|
||||
@@ -134,7 +133,6 @@ final class ClientTest extends TestCase
|
||||
],
|
||||
];
|
||||
$responsePayload = ['success' => true];
|
||||
|
||||
$expectedUrl = self::API_BASE_URL . $uri . '?' . http_build_query([
|
||||
'access_token' => self::FAKE_TOKEN,
|
||||
'v' => self::API_VERSION
|
||||
@@ -146,16 +144,13 @@ final class ClientTest extends TestCase
|
||||
->with('POST', $expectedUrl)
|
||||
->willReturn($this->requestMock);
|
||||
|
||||
$this->streamFactoryMock
|
||||
->expects($this->once())
|
||||
->method('createStream')
|
||||
->with(json_encode($requestBody))
|
||||
->willReturn($this->streamMock);
|
||||
|
||||
$this->requestMock
|
||||
->expects($this->once())
|
||||
->method('withBody')
|
||||
->with($this->streamMock)
|
||||
->with($this->callback(function (StreamInterface $stream) use ($requestBody) {
|
||||
$this->assertSame(json_encode($requestBody), $stream->getContents());
|
||||
return true;
|
||||
}))
|
||||
->willReturn($this->requestMock);
|
||||
|
||||
$this->requestMock
|
||||
@@ -273,4 +268,43 @@ final class ClientTest extends TestCase
|
||||
throw $e; // Re-throw for PHPUnit to catch the expected exception type
|
||||
}
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function uploadMethodSendsCorrectMultipartRequest(): void
|
||||
{
|
||||
$uploadUrl = 'https://upload.server/path';
|
||||
$fileContents = 'fake-image-binary-data';
|
||||
$fileName = 'test.jpg';
|
||||
$responsePayload = ['token' => 'upload_successful_token'];
|
||||
|
||||
$this->requestMock
|
||||
->expects($this->once())
|
||||
->method('withBody')
|
||||
->with($this->callback(function (StreamInterface $stream) use ($fileContents, $fileName) {
|
||||
$stream->rewind();
|
||||
$body = $stream->getContents();
|
||||
$this->assertStringContainsString('Content-Disposition: form-data; name="data"; filename="' . $fileName . '"', $body);
|
||||
$this->assertStringContainsString($fileContents, $body);
|
||||
return true;
|
||||
}))
|
||||
->willReturn($this->requestMock);
|
||||
|
||||
$this->requestMock
|
||||
->expects($this->once())
|
||||
->method('withHeader')
|
||||
->with($this->stringStartsWith('Content-Type'), $this->stringStartsWith('multipart/form-data'))
|
||||
->willReturn($this->requestMock);
|
||||
|
||||
$this->requestFactoryMock
|
||||
->expects($this->once())
|
||||
->method('createRequest')
|
||||
->with('POST', $uploadUrl)
|
||||
->willReturn($this->requestMock);
|
||||
|
||||
$this->responseMock->method('getStatusCode')->willReturn(200);
|
||||
$this->streamMock->method('__toString')->willReturn(json_encode($responsePayload));
|
||||
|
||||
$result = $this->client->upload($uploadUrl, $fileContents, $fileName);
|
||||
$this->assertSame($responsePayload, $result);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user