From 626fdaa9a424fb755321ec9e521155b24986dd93 Mon Sep 17 00:00:00 2001 From: Jeroeny Date: Sat, 23 Nov 2019 15:02:30 +0100 Subject: [PATCH] [Notifier] Add Slack bridge tests --- .../Slack/Tests/SlackTransportFactoryTest.php | 57 +++++ .../Bridge/Slack/Tests/SlackTransportTest.php | 212 ++++++++++++++++++ .../Notifier/Bridge/Slack/composer.json | 3 + 3 files changed, 272 insertions(+) create mode 100644 src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php create mode 100644 src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php new file mode 100644 index 000000000000..afd77200ba8e --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportFactoryTest.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Slack\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory; +use Symfony\Component\Notifier\Exception\IncompleteDsnException; +use Symfony\Component\Notifier\Exception\UnsupportedSchemeException; +use Symfony\Component\Notifier\Transport\Dsn; + +final class SlackTransportFactoryTest extends TestCase +{ + public function testCreateWithDsn(): void + { + $factory = new SlackTransportFactory(); + + $host = 'testHost'; + $channel = 'testChannel'; + $transport = $factory->create(Dsn::fromString(sprintf('slack://testUser@%s/?channel=%s', $host, $channel))); + + $this->assertSame(sprintf('slack://%s?channel=%s', $host, $channel), (string) $transport); + } + + public function testCreateWithNoTokenThrowsMalformed(): void + { + $factory = new SlackTransportFactory(); + + $this->expectException(IncompleteDsnException::class); + $factory->create(Dsn::fromString(sprintf('slack://%s/?channel=%s', 'testHost', 'testChannel'))); + } + + public function testSupportsSlackScheme(): void + { + $factory = new SlackTransportFactory(); + + $this->assertTrue($factory->supports(Dsn::fromString('slack://host/?channel=testChannel'))); + $this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/?channel=testChannel'))); + } + + public function testNonSlackSchemeThrows(): void + { + $factory = new SlackTransportFactory(); + + $this->expectException(UnsupportedSchemeException::class); + + $factory->create(Dsn::fromString('somethingElse://user:pwd@host/?channel=testChannel')); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php new file mode 100644 index 000000000000..cbfaadd6060c --- /dev/null +++ b/src/Symfony/Component/Notifier/Bridge/Slack/Tests/SlackTransportTest.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Notifier\Bridge\Slack\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpClient\MockHttpClient; +use Symfony\Component\Notifier\Bridge\Slack\SlackOptions; +use Symfony\Component\Notifier\Bridge\Slack\SlackTransport; +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\Component\Notifier\Notification\Notification; +use Symfony\Component\Notifier\Recipient\Recipient; +use Symfony\Contracts\HttpClient\HttpClientInterface; +use Symfony\Contracts\HttpClient\ResponseInterface; + +final class SlackTransportTest extends TestCase +{ + public function testToStringContainsProperties(): void + { + $host = 'testHost'; + $channel = 'testChannel'; + + $transport = new SlackTransport('testToken', $channel, $this->createMock(HttpClientInterface::class)); + $transport->setHost('testHost'); + + $this->assertSame(sprintf('slack://%s?channel=%s', $host, $channel), (string) $transport); + } + + public function testSupportsChatMessage(): void + { + $transport = new SlackTransport('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 SlackTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class)); + + $transport->send($this->createMock(MessageInterface::class)); + } + + public function testSendWithEmptyArrayResponseThrows(): void + { + $this->expectException(TransportException::class); + + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(500); + $response->expects($this->once()) + ->method('getContent') + ->willReturn('[]'); + + $client = new MockHttpClient(static function () use ($response): ResponseInterface { + return $response; + }); + + $transport = new SlackTransport('testToken', 'testChannel', $client); + + $transport->send(new ChatMessage('testMessage')); + } + + public function testSendWithErrorResponseThrows(): void + { + $this->expectException(TransportException::class); + $this->expectExceptionMessageRegExp('/testErrorCode/'); + + $response = $this->createMock(ResponseInterface::class); + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(400); + + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['error' => 'testErrorCode'])); + + $client = new MockHttpClient(static function () use ($response): ResponseInterface { + return $response; + }); + + $transport = new SlackTransport('testToken', 'testChannel', $client); + + $transport->send(new ChatMessage('testMessage')); + } + + public function testSendWithOptions(): void + { + $token = 'testToken'; + $channel = 'testChannel'; + $message = 'testMessage'; + + $response = $this->createMock(ResponseInterface::class); + + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['ok' => true])); + + $expectedBody = sprintf('token=%s&channel=%s&text=%s', $token, $channel, $message); + + $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertSame($expectedBody, $options['body']); + + return $response; + }); + + $transport = new SlackTransport($token, $channel, $client); + + $transport->send(new ChatMessage('testMessage')); + } + + public function testSendWithNotification(): void + { + $token = 'testToken'; + $channel = 'testChannel'; + $message = 'testMessage'; + + $response = $this->createMock(ResponseInterface::class); + + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['ok' => true])); + + $notification = new Notification($message); + $chatMessage = ChatMessage::fromNotification($notification, new Recipient('test-email@example.com')); + $options = SlackOptions::fromNotification($notification); + + $expectedBody = http_build_query([ + 'blocks' => $options->toArray()['blocks'], + 'token' => $token, + 'channel' => $channel, + 'text' => $message, + ]); + + $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertSame($expectedBody, $options['body']); + + return $response; + }); + + $transport = new SlackTransport($token, $channel, $client); + + $transport->send($chatMessage); + } + + public function testSendWithInvalidOptions(): void + { + $this->expectException(LogicException::class); + + $client = new MockHttpClient(function (string $method, string $url, array $options = []): ResponseInterface { + return $this->createMock(ResponseInterface::class); + }); + + $transport = new SlackTransport('testToken', 'testChannel', $client); + + $transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class))); + } + + public function testSendWith200ResponseButNotOk(): void + { + $token = 'testToken'; + $channel = 'testChannel'; + $message = 'testMessage'; + + $this->expectException(TransportException::class); + + $response = $this->createMock(ResponseInterface::class); + + $response->expects($this->exactly(2)) + ->method('getStatusCode') + ->willReturn(200); + + $response->expects($this->once()) + ->method('getContent') + ->willReturn(json_encode(['ok' => false, 'error' => 'testErrorCode'])); + + $expectedBody = sprintf('token=%s&channel=%s&text=%s', $token, $channel, $message); + + $client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface { + $this->assertSame($expectedBody, $options['body']); + + return $response; + }); + + $transport = new SlackTransport($token, $channel, $client); + + $transport->send(new ChatMessage('testMessage')); + } +} diff --git a/src/Symfony/Component/Notifier/Bridge/Slack/composer.json b/src/Symfony/Component/Notifier/Bridge/Slack/composer.json index feb1e5f4edbb..9b9d08930a9b 100644 --- a/src/Symfony/Component/Notifier/Bridge/Slack/composer.json +++ b/src/Symfony/Component/Notifier/Bridge/Slack/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\\Slack\\": "" }, "exclude-from-classmap": [