diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php new file mode 100644 index 0000000000000..c74d38f2f6882 --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportFactoryTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Telegram\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransportFactory; +use Symfony\Component\Notifier\Exception\IncompleteDsnException; +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\Dsn; + +final class TelegramTransportFactoryTest extends TestCase +{ + public function testCreateWithDsn(): void + { + $factory = new TelegramTransportFactory(); + + $host = 'testHost'; + $channel = 'testChannel'; + + $transport = $factory->create(Dsn::fromString(sprintf('telegram://%s@%s/?channel=%s', 'testUser:testPassword', $host, $channel))); + + $this->assertSame(sprintf('telegram://%s?channel=%s', $host, $channel), (string) $transport); + } + + public function testCreateWithNoPasswordThrowsMalformed(): void + { + $factory = new TelegramTransportFactory(); + + $this->expectException(IncompleteDsnException::class); + $factory->create(Dsn::fromString(sprintf('telegram://%s@%s/?channel=%s', 'simpleToken', 'testHost', 'testChannel'))); + } + + public function testCreateWithNoTokenThrowsMalformed(): void + { + $factory = new TelegramTransportFactory(); + + $this->expectException(IncompleteDsnException::class); + $factory->create(Dsn::fromString(sprintf('telegram://%s/?channel=%s', 'testHost', 'testChannel'))); + } + + public function testSupportsTelegramScheme(): void + { + $factory = new TelegramTransportFactory(); + + $this->assertTrue($factory->supports(Dsn::fromString('telegram://host/?channel=testChannel'))); + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/?channel=testChannel'))); + } + + public function testNonTelegramSchemeThrows(): void + { + $factory = new TelegramTransportFactory(); + + $this->expectException(UnsupportedSchemeException::class); + $factory->create(Dsn::fromString('somethingElse://user:pwd@host/?channel=testChannel')); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php new file mode 100644 index 0000000000000..352b390ffd00b --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/Tests/TelegramTransportTest.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Telegram\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\Notifier\Bridge\Telegram\TelegramTransport; +use Symfony\Component\Notifier\Exception\LogicException; +use Symfony\Component\Notifier\Exception\TransportException; +use Symfony\Component\Notifier\Message\ChatMessage; +use Symfony\Component\Notifier\Message\MessageInterface; +use Symfony\Component\Notifier\Message\MessageOptionsInterface; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; + +final class TelegramTransportTest extends TestCase +{ + public function testToStringContainsProperties(): void + { + $channel = 'testChannel'; + + $transport = new TelegramTransport('testToken', $channel, $this->createMock(HttpClientInterface::class)); + $transport->setHost('testHost'); + + $this->assertSame(sprintf('telegram://%s?channel=%s', 'testHost', $channel), (string) $transport); + } + + public function testSupportsChatMessage(): void + { + $transport = new TelegramTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class)); + + $this->assertTrue($transport->supports(new ChatMessage('testChatMessage'))); + $this->assertFalse($transport->supports($this->createMock(MessageInterface::class))); + } + + public function testSendNonChatMessageThrows(): void + { + $this->expectException(LogicException::class); + $transport = new TelegramTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class)); + + $transport->send($this->createMock(MessageInterface::class)); + } + + public function testSendWithErrorResponseThrows(): void + { + $this->expectException(TransportException::class); + $this->expectExceptionMessageRegExp('/testDescription.+testErrorCode/'); + + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(400); + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['description' => 'testDescription', 'error_code' => 'testErrorCode'])); + + $client = new MockHttpClient(static function () use ($response): ResponseInterface { + return $response; + }); + + $transport = new TelegramTransport('testToken', 'testChannel', $client); + + $transport->send(new ChatMessage('testMessage')); + } + + public function testSendWithOptions(): void + { + $channel = 'testChannel'; + + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + $response->expects($this->once()) + ->method('getContent') + ->willReturn(''); + + $expectedBody = [ + 'chat_id' => $channel, + 'text' => 'testMessage', + 'parse_mode' => 'Markdown', + ]; + + $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertEquals($expectedBody, json_decode($options['body'], true)); + + return $response; + }); + + $transport = new TelegramTransport('testToken', $channel, $client); + + $transport->send(new ChatMessage('testMessage')); + } + + public function testSendWithChannelOverride(): void + { + $channelOverride = 'channelOverride'; + + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + $response->expects($this->once()) + ->method('getContent') + ->willReturn(''); + + $expectedBody = [ + 'chat_id' => $channelOverride, + 'text' => 'testMessage', + 'parse_mode' => 'Markdown', + ]; + + $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertEquals($expectedBody, json_decode($options['body'], true)); + + return $response; + }); + + $transport = new TelegramTransport('testToken', 'defaultChannel', $client); + + $messageOptions = $this->createMock(MessageOptionsInterface::class); + $messageOptions + ->expects($this->once()) + ->method('getRecipientId') + ->willReturn($channelOverride); + + $transport->send(new ChatMessage('testMessage', $messageOptions)); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Telegram/composer.json b/src/Symfony/Component/Notifier/Bridge/Telegram/composer.json index a562f74dce549..003215dd49e9a 100644 --- a/src/Symfony/Component/Notifier/Bridge/Telegram/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Telegram/composer.json @@ -20,6 +20,9 @@ "symfony/http-client": "^4.3|^5.0", "symfony/notifier": "~5.0.0" }, + "require-dev": { + "symfony/event-dispatcher": "^4.3|^5.0" + }, "autoload": { "psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Telegram\\": "" }, "exclude-from-classmap": [