Skip to content

Commit 62c4b80

Browse files
committed
Tests
1 parent 69e1e73 commit 62c4b80

13 files changed

+632
-3
lines changed

src/ModelFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ public function createUpdateList(array $data): UpdateList
137137

138138
return new UpdateList(
139139
$updateObjects,
140-
$data['marker'] ?? null,
140+
$data['marker'] ? (int)$data['marker'] : null,
141141
);
142142
}
143143

src/Models/UpdateList.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,18 @@ public function __construct(
2020
public ?int $marker,
2121
) {
2222
}
23+
24+
/**
25+
* Overridden to prevent incorrect usage.
26+
* UpdateList contains polymorphic objects and must be created via ModelFactory.
27+
*
28+
* @param array<string, mixed> $data
29+
* @throws \LogicException Always.
30+
*/
31+
public static function fromArray(array $data): static
32+
{
33+
throw new \LogicException(
34+
'Cannot create UpdateList directly from an array. Use ModelFactory::createUpdateList() instead.'
35+
);
36+
}
2337
}

src/WebhookHandler.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public function onMessageCreated(callable $handler): self
6868
* @param callable(Models\Updates\BotStartedUpdate, Api): void $handler
6969
*
7070
* @return $this
71+
* @codeCoverageIgnore
7172
*/
7273
public function onBotStarted(callable $handler): self
7374
{

tests/ApiTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
use BushlanovDev\MaxMessengerBot\Models\Subscription;
3030
use BushlanovDev\MaxMessengerBot\Models\UpdateList;
3131
use BushlanovDev\MaxMessengerBot\Models\UploadEndpoint;
32+
use BushlanovDev\MaxMessengerBot\WebhookHandler;
3233
use InvalidArgumentException;
3334
use PHPUnit\Framework\Attributes\CoversClass;
3435
use PHPUnit\Framework\Attributes\Test;
@@ -56,6 +57,7 @@
5657
#[UsesClass(UploadEndpoint::class)]
5758
#[UsesClass(Chat::class)]
5859
#[UsesClass(UpdateList::class)]
60+
#[UsesClass(WebhookHandler::class)]
5961
final class ApiTest extends TestCase
6062
{
6163
private MockObject&ClientApiInterface $clientMock;
@@ -546,4 +548,24 @@ public function getUpdatesHandlesNullParameters(): void
546548

547549
$this->api->getUpdates();
548550
}
551+
552+
#[Test]
553+
public function createWebhookHandlerReturnsInstanceWithProvidedSecret(): void
554+
{
555+
$secret = 'my-test-secret-key';
556+
$webhookHandler = $this->api->createWebhookHandler($secret);
557+
558+
$this->assertInstanceOf(WebhookHandler::class, $webhookHandler);
559+
560+
$reflection = new ReflectionClass($webhookHandler);
561+
562+
$apiProperty = $reflection->getProperty('api');
563+
$this->assertSame($this->api, $apiProperty->getValue($webhookHandler));
564+
565+
$factoryProperty = $reflection->getProperty('modelFactory');
566+
$this->assertSame($this->modelFactoryMock, $factoryProperty->getValue($webhookHandler));
567+
568+
$secretProperty = $reflection->getProperty('secret');
569+
$this->assertSame($secret, $secretProperty->getValue($webhookHandler));
570+
}
549571
}

tests/Models/Attachments/Buttons/OpenAppButtonTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use PHPUnit\Framework\TestCase;
1212

1313
#[CoversClass(OpenAppButton::class)]
14-
class OpenAppButtonTest extends TestCase
14+
final class OpenAppButtonTest extends TestCase
1515
{
1616
#[Test]
1717
public function toArraySerializesCorrectly(): void
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BushlanovDev\MaxMessengerBot\Tests\Models\Attachments\Payloads;
6+
7+
use BushlanovDev\MaxMessengerBot\Enums\ButtonType;
8+
use BushlanovDev\MaxMessengerBot\Enums\Intent;
9+
use BushlanovDev\MaxMessengerBot\Models\Attachments\Buttons\CallbackButton;
10+
use BushlanovDev\MaxMessengerBot\Models\Attachments\Buttons\LinkButton;
11+
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\InlineKeyboardPayload;
12+
use PHPUnit\Framework\Attributes\CoversClass;
13+
use PHPUnit\Framework\Attributes\Test;
14+
use PHPUnit\Framework\Attributes\UsesClass;
15+
use PHPUnit\Framework\TestCase;
16+
17+
#[CoversClass(InlineKeyboardPayload::class)]
18+
#[UsesClass(CallbackButton::class)]
19+
#[UsesClass(LinkButton::class)]
20+
final class InlineKeyboardPayloadTest extends TestCase
21+
{
22+
#[Test]
23+
public function constructionAndPropertyAccess(): void
24+
{
25+
$buttons = [
26+
[new CallbackButton('Test', 'payload')],
27+
];
28+
$payload = new InlineKeyboardPayload($buttons);
29+
30+
$this->assertInstanceOf(InlineKeyboardPayload::class, $payload);
31+
$this->assertSame($buttons, $payload->buttons);
32+
}
33+
34+
#[Test]
35+
public function toArraySerializesCorrectly(): void
36+
{
37+
$buttons = [
38+
[new CallbackButton('Accept', 'accept_payload', Intent::Positive)],
39+
[
40+
new CallbackButton('Decline', 'decline_payload', Intent::Negative),
41+
new LinkButton('Help', 'https://example.com/help'),
42+
],
43+
];
44+
$payload = new InlineKeyboardPayload($buttons);
45+
46+
$resultArray = $payload->toArray();
47+
48+
$expectedArray = [
49+
'buttons' => [
50+
[
51+
[
52+
'type' => ButtonType::Callback->value,
53+
'text' => 'Accept',
54+
'payload' => 'accept_payload',
55+
'intent' => Intent::Positive->value,
56+
],
57+
],
58+
[
59+
[
60+
'type' => ButtonType::Callback->value,
61+
'text' => 'Decline',
62+
'payload' => 'decline_payload',
63+
'intent' => Intent::Negative->value,
64+
],
65+
[
66+
'type' => ButtonType::Link->value,
67+
'text' => 'Help',
68+
'url' => 'https://example.com/help',
69+
],
70+
],
71+
],
72+
];
73+
74+
$this->assertEquals($expectedArray, $resultArray);
75+
}
76+
77+
#[Test]
78+
public function toArrayHandlesEmptyButtonsArray(): void
79+
{
80+
$payload = new InlineKeyboardPayload([]);
81+
$resultArray = $payload->toArray();
82+
83+
$expectedArray = [
84+
'buttons' => [],
85+
];
86+
$this->assertEquals($expectedArray, $resultArray);
87+
}
88+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BushlanovDev\MaxMessengerBot\Tests\Models\Attachments\Payloads;
6+
7+
use BushlanovDev\MaxMessengerBot\Attributes\ArrayOf;
8+
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\PhotoAttachmentPayload;
9+
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\PhotoToken;
10+
use InvalidArgumentException;
11+
use PHPUnit\Framework\Attributes\CoversClass;
12+
use PHPUnit\Framework\Attributes\DataProvider;
13+
use PHPUnit\Framework\Attributes\Test;
14+
use PHPUnit\Framework\Attributes\UsesClass;
15+
use PHPUnit\Framework\TestCase;
16+
17+
#[CoversClass(PhotoAttachmentPayload::class)]
18+
#[UsesClass(PhotoToken::class)]
19+
#[UsesClass(ArrayOf::class)]
20+
final class PhotoAttachmentPayloadTest extends TestCase
21+
{
22+
#[Test]
23+
public function canBeCreatedWithUrlOnly(): void
24+
{
25+
$payload = new PhotoAttachmentPayload(url: 'https://example.com/photo.jpg');
26+
27+
$this->assertSame('https://example.com/photo.jpg', $payload->url);
28+
$this->assertNull($payload->token);
29+
$this->assertNull($payload->photos);
30+
31+
$expectedArray = [
32+
'url' => 'https://example.com/photo.jpg',
33+
'token' => null,
34+
'photos' => null,
35+
];
36+
$this->assertEquals($expectedArray, $payload->toArray());
37+
}
38+
39+
#[Test]
40+
public function canBeCreatedWithTokenOnly(): void
41+
{
42+
$payload = new PhotoAttachmentPayload(token: 'uploaded_token_abc');
43+
44+
$this->assertSame('uploaded_token_abc', $payload->token);
45+
$this->assertNull($payload->url);
46+
$this->assertNull($payload->photos);
47+
48+
$expectedArray = [
49+
'token' => 'uploaded_token_abc',
50+
'url' => null,
51+
'photos' => null,
52+
];
53+
$this->assertEquals($expectedArray, $payload->toArray());
54+
}
55+
56+
#[Test]
57+
public function canBeCreatedWithPhotosOnly(): void
58+
{
59+
$photos = [
60+
new PhotoToken('token_1'),
61+
new PhotoToken('token_2'),
62+
];
63+
$payload = new PhotoAttachmentPayload(photos: $photos);
64+
65+
$this->assertSame($photos, $payload->photos);
66+
$this->assertNull($payload->url);
67+
$this->assertNull($payload->token);
68+
69+
$expectedArray = [
70+
'photos' => [
71+
['token' => 'token_1'],
72+
['token' => 'token_2'],
73+
],
74+
'url' => null,
75+
'token' => null,
76+
];
77+
$this->assertEquals($expectedArray, $payload->toArray());
78+
}
79+
80+
/**
81+
* Data provider for invalid constructor arguments.
82+
*
83+
* @return array<string, array{0: string|null, 1: string|null, 2: array|null}>
84+
*/
85+
public static function invalidPayloadProvider(): array
86+
{
87+
return [
88+
'all null (no arguments)' => [null, null, null],
89+
'url and token provided' => ['https://a.com', 'token123', null],
90+
'url and photos provided' => ['https://a.com', null, [new PhotoToken('t')]],
91+
'token and photos provided' => [null, 'token123', [new PhotoToken('t')]],
92+
'all three arguments provided' => ['https://a.com', 'token123', [new PhotoToken('t')]],
93+
];
94+
}
95+
96+
#[Test]
97+
#[DataProvider('invalidPayloadProvider')]
98+
public function constructorThrowsExceptionForInvalidArguments(
99+
?string $url,
100+
?string $token,
101+
?array $photos
102+
): void {
103+
$this->expectException(InvalidArgumentException::class);
104+
$this->expectExceptionMessage('Provide exactly one of "url", "token", or "photos" for PhotoAttachmentPayload.');
105+
106+
new PhotoAttachmentPayload($url, $token, $photos);
107+
}
108+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace BushlanovDev\MaxMessengerBot\Tests\Models\Attachments\Payloads;
6+
7+
use BushlanovDev\MaxMessengerBot\Models\Attachments\Payloads\PhotoToken;
8+
use PHPUnit\Framework\Attributes\CoversClass;
9+
use PHPUnit\Framework\Attributes\Test;
10+
use PHPUnit\Framework\TestCase;
11+
12+
#[CoversClass(PhotoToken::class)]
13+
final class PhotoTokenTest extends TestCase
14+
{
15+
#[Test]
16+
public function itCorrectlyHandlesCreationSerializationAndState(): void
17+
{
18+
$tokenValue = 'some_unique_token_string_123';
19+
$rawData = ['token' => $tokenValue];
20+
21+
$photoToken = PhotoToken::fromArray($rawData);
22+
23+
$this->assertInstanceOf(PhotoToken::class, $photoToken);
24+
$this->assertSame($tokenValue, $photoToken->token);
25+
26+
$serializedData = $photoToken->toArray();
27+
$this->assertEquals($rawData, $serializedData);
28+
29+
$directInstance = new PhotoToken($tokenValue);
30+
$this->assertSame($tokenValue, $directInstance->token);
31+
}
32+
}

0 commit comments

Comments
 (0)