Skip to content

Commit 626fdaa

Browse files
Jeroenyfabpot
authored andcommitted
[Notifier] Add Slack bridge tests
1 parent 255f557 commit 626fdaa

File tree

3 files changed

+272
-0
lines changed

3 files changed

+272
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Notifier\Bridge\Slack\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\Notifier\Bridge\Slack\SlackTransportFactory;
16+
use Symfony\Component\Notifier\Exception\IncompleteDsnException;
17+
use Symfony\Component\Notifier\Exception\UnsupportedSchemeException;
18+
use Symfony\Component\Notifier\Transport\Dsn;
19+
20+
final class SlackTransportFactoryTest extends TestCase
21+
{
22+
public function testCreateWithDsn(): void
23+
{
24+
$factory = new SlackTransportFactory();
25+
26+
$host = 'testHost';
27+
$channel = 'testChannel';
28+
$transport = $factory->create(Dsn::fromString(sprintf('slack://testUser@%s/?channel=%s', $host, $channel)));
29+
30+
$this->assertSame(sprintf('slack://%s?channel=%s', $host, $channel), (string) $transport);
31+
}
32+
33+
public function testCreateWithNoTokenThrowsMalformed(): void
34+
{
35+
$factory = new SlackTransportFactory();
36+
37+
$this->expectException(IncompleteDsnException::class);
38+
$factory->create(Dsn::fromString(sprintf('slack://%s/?channel=%s', 'testHost', 'testChannel')));
39+
}
40+
41+
public function testSupportsSlackScheme(): void
42+
{
43+
$factory = new SlackTransportFactory();
44+
45+
$this->assertTrue($factory->supports(Dsn::fromString('slack://host/?channel=testChannel')));
46+
$this->assertFalse($factory->supports(Dsn::fromString('somethingElse://host/?channel=testChannel')));
47+
}
48+
49+
public function testNonSlackSchemeThrows(): void
50+
{
51+
$factory = new SlackTransportFactory();
52+
53+
$this->expectException(UnsupportedSchemeException::class);
54+
55+
$factory->create(Dsn::fromString('somethingElse://user:pwd@host/?channel=testChannel'));
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Notifier\Bridge\Slack\Tests;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\HttpClient\MockHttpClient;
16+
use Symfony\Component\Notifier\Bridge\Slack\SlackOptions;
17+
use Symfony\Component\Notifier\Bridge\Slack\SlackTransport;
18+
use Symfony\Component\Notifier\Exception\LogicException;
19+
use Symfony\Component\Notifier\Exception\TransportException;
20+
use Symfony\Component\Notifier\Message\ChatMessage;
21+
use Symfony\Component\Notifier\Message\MessageInterface;
22+
use Symfony\Component\Notifier\Message\MessageOptionsInterface;
23+
use Symfony\Component\Notifier\Notification\Notification;
24+
use Symfony\Component\Notifier\Recipient\Recipient;
25+
use Symfony\Contracts\HttpClient\HttpClientInterface;
26+
use Symfony\Contracts\HttpClient\ResponseInterface;
27+
28+
final class SlackTransportTest extends TestCase
29+
{
30+
public function testToStringContainsProperties(): void
31+
{
32+
$host = 'testHost';
33+
$channel = 'testChannel';
34+
35+
$transport = new SlackTransport('testToken', $channel, $this->createMock(HttpClientInterface::class));
36+
$transport->setHost('testHost');
37+
38+
$this->assertSame(sprintf('slack://%s?channel=%s', $host, $channel), (string) $transport);
39+
}
40+
41+
public function testSupportsChatMessage(): void
42+
{
43+
$transport = new SlackTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
44+
45+
$this->assertTrue($transport->supports(new ChatMessage('testChatMessage')));
46+
$this->assertFalse($transport->supports($this->createMock(MessageInterface::class)));
47+
}
48+
49+
public function testSendNonChatMessageThrows(): void
50+
{
51+
$this->expectException(LogicException::class);
52+
53+
$transport = new SlackTransport('testToken', 'testChannel', $this->createMock(HttpClientInterface::class));
54+
55+
$transport->send($this->createMock(MessageInterface::class));
56+
}
57+
58+
public function testSendWithEmptyArrayResponseThrows(): void
59+
{
60+
$this->expectException(TransportException::class);
61+
62+
$response = $this->createMock(ResponseInterface::class);
63+
$response->expects($this->exactly(2))
64+
->method('getStatusCode')
65+
->willReturn(500);
66+
$response->expects($this->once())
67+
->method('getContent')
68+
->willReturn('[]');
69+
70+
$client = new MockHttpClient(static function () use ($response): ResponseInterface {
71+
return $response;
72+
});
73+
74+
$transport = new SlackTransport('testToken', 'testChannel', $client);
75+
76+
$transport->send(new ChatMessage('testMessage'));
77+
}
78+
79+
public function testSendWithErrorResponseThrows(): void
80+
{
81+
$this->expectException(TransportException::class);
82+
$this->expectExceptionMessageRegExp('/testErrorCode/');
83+
84+
$response = $this->createMock(ResponseInterface::class);
85+
$response->expects($this->exactly(2))
86+
->method('getStatusCode')
87+
->willReturn(400);
88+
89+
$response->expects($this->once())
90+
->method('getContent')
91+
->willReturn(json_encode(['error' => 'testErrorCode']));
92+
93+
$client = new MockHttpClient(static function () use ($response): ResponseInterface {
94+
return $response;
95+
});
96+
97+
$transport = new SlackTransport('testToken', 'testChannel', $client);
98+
99+
$transport->send(new ChatMessage('testMessage'));
100+
}
101+
102+
public function testSendWithOptions(): void
103+
{
104+
$token = 'testToken';
105+
$channel = 'testChannel';
106+
$message = 'testMessage';
107+
108+
$response = $this->createMock(ResponseInterface::class);
109+
110+
$response->expects($this->exactly(2))
111+
->method('getStatusCode')
112+
->willReturn(200);
113+
114+
$response->expects($this->once())
115+
->method('getContent')
116+
->willReturn(json_encode(['ok' => true]));
117+
118+
$expectedBody = sprintf('token=%s&channel=%s&text=%s', $token, $channel, $message);
119+
120+
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface {
121+
$this->assertSame($expectedBody, $options['body']);
122+
123+
return $response;
124+
});
125+
126+
$transport = new SlackTransport($token, $channel, $client);
127+
128+
$transport->send(new ChatMessage('testMessage'));
129+
}
130+
131+
public function testSendWithNotification(): void
132+
{
133+
$token = 'testToken';
134+
$channel = 'testChannel';
135+
$message = 'testMessage';
136+
137+
$response = $this->createMock(ResponseInterface::class);
138+
139+
$response->expects($this->exactly(2))
140+
->method('getStatusCode')
141+
->willReturn(200);
142+
143+
$response->expects($this->once())
144+
->method('getContent')
145+
->willReturn(json_encode(['ok' => true]));
146+
147+
$notification = new Notification($message);
148+
$chatMessage = ChatMessage::fromNotification($notification, new Recipient('test-email@example.com'));
149+
$options = SlackOptions::fromNotification($notification);
150+
151+
$expectedBody = http_build_query([
152+
'blocks' => $options->toArray()['blocks'],
153+
'token' => $token,
154+
'channel' => $channel,
155+
'text' => $message,
156+
]);
157+
158+
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface {
159+
$this->assertSame($expectedBody, $options['body']);
160+
161+
return $response;
162+
});
163+
164+
$transport = new SlackTransport($token, $channel, $client);
165+
166+
$transport->send($chatMessage);
167+
}
168+
169+
public function testSendWithInvalidOptions(): void
170+
{
171+
$this->expectException(LogicException::class);
172+
173+
$client = new MockHttpClient(function (string $method, string $url, array $options = []): ResponseInterface {
174+
return $this->createMock(ResponseInterface::class);
175+
});
176+
177+
$transport = new SlackTransport('testToken', 'testChannel', $client);
178+
179+
$transport->send(new ChatMessage('testMessage', $this->createMock(MessageOptionsInterface::class)));
180+
}
181+
182+
public function testSendWith200ResponseButNotOk(): void
183+
{
184+
$token = 'testToken';
185+
$channel = 'testChannel';
186+
$message = 'testMessage';
187+
188+
$this->expectException(TransportException::class);
189+
190+
$response = $this->createMock(ResponseInterface::class);
191+
192+
$response->expects($this->exactly(2))
193+
->method('getStatusCode')
194+
->willReturn(200);
195+
196+
$response->expects($this->once())
197+
->method('getContent')
198+
->willReturn(json_encode(['ok' => false, 'error' => 'testErrorCode']));
199+
200+
$expectedBody = sprintf('token=%s&channel=%s&text=%s', $token, $channel, $message);
201+
202+
$client = new MockHttpClient(function (string $method, string $url, array $options = []) use ($response, $expectedBody): ResponseInterface {
203+
$this->assertSame($expectedBody, $options['body']);
204+
205+
return $response;
206+
});
207+
208+
$transport = new SlackTransport($token, $channel, $client);
209+
210+
$transport->send(new ChatMessage('testMessage'));
211+
}
212+
}

src/Symfony/Component/Notifier/Bridge/Slack/composer.json

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
"symfony/http-client": "^4.3|^5.0",
2121
"symfony/notifier": "~5.0.0"
2222
},
23+
"require-dev": {
24+
"symfony/event-dispatcher": "^4.3|^5.0"
25+
},
2326
"autoload": {
2427
"psr-4": { "Symfony\\Component\\Notifier\\Bridge\\Slack\\": "" },
2528
"exclude-from-classmap": [

0 commit comments

Comments
 (0)