Skip to content

Commit 6af70a8

Browse files
committed
Add tests, refactor and improve testability
1 parent e906a04 commit 6af70a8

15 files changed

+543
-90
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"twilio/sdk": "^4.11",
1717
"illuminate/notifications": "5.1.*|5.2.*|5.3.*",
1818
"illuminate/support": "5.1.*|5.2.*|5.3.*",
19-
"illuminate/events": "5.1.*|5.2.*|5.3.*"
19+
"illuminate/events": "5.1.*|5.2.*|5.3.*",
20+
"illuminate/queue": "5.1.*|5.2.*|5.3.*"
2021
},
2122
"require-dev": {
2223
"mockery/mockery": "^0.9.5",

src/Exceptions/CouldNotSendNotification.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ public static function invalidMessageObject($message)
1616
{
1717
$className = get_class($message) ?: 'Unknown';
1818

19-
return new static("Notification was not sent. Message object class `{$className}` is invalid. It should be either `".SmsMessage::class.'` or `'.CallMessage::class.'`');
19+
return new static(
20+
"Notification was not sent. Message object class `{$className}` is invalid. It should
21+
be either `".SmsMessage::class.'` or `'.CallMessage::class.'`');
2022
}
2123

2224
/**
@@ -26,4 +28,15 @@ public static function missingFrom()
2628
{
2729
return new static('Notification was not sent. Missing `from` number.');
2830
}
31+
32+
/**
33+
* @return static
34+
*/
35+
public static function invalidReceiver()
36+
{
37+
return new static(
38+
'The notifiable did not have a receiving phone number. Add a routeNotificationForTwilio
39+
method or a phone_number attribute to your notifiable.'
40+
);
41+
}
2942
}

src/Twilio.php

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
namespace NotificationChannels\Twilio;
4+
5+
use NotificationChannels\Twilio\Exceptions\CouldNotSendNotification;
6+
use Services_Twilio as TwilioService;
7+
8+
class Twilio
9+
{
10+
/**
11+
* @var TwilioService
12+
*/
13+
protected $twilioService;
14+
15+
/**
16+
* Default 'from' from config.
17+
* @var string
18+
*/
19+
protected $from;
20+
21+
/**
22+
* Twilio constructor.
23+
*
24+
* @param TwilioService $twilioService
25+
* @param string $from
26+
*/
27+
public function __construct(TwilioService $twilioService, $from)
28+
{
29+
$this->twilioService = $twilioService;
30+
$this->from = $from;
31+
}
32+
33+
/**
34+
* Send a TwilioMessage to the a phone number.
35+
*
36+
* @param TwilioMessage $message
37+
* @param $to
38+
* @return mixed
39+
* @throws CouldNotSendNotification
40+
*/
41+
public function sendMessage(TwilioMessage $message, $to)
42+
{
43+
if ($message instanceof TwilioSmsMessage) {
44+
return $this->sendSmsMessage($message, $to);
45+
}
46+
47+
if ($message instanceof TwilioCallMessage) {
48+
return $this->makeCall($message, $to);
49+
}
50+
51+
throw CouldNotSendNotification::invalidMessageObject($message);
52+
}
53+
54+
protected function sendSmsMessage($message, $to)
55+
{
56+
return $this->twilioService->account->messages->sendMessage(
57+
$this->getFrom($message),
58+
$to,
59+
trim($message->content)
60+
);
61+
}
62+
63+
protected function makeCall($message, $to)
64+
{
65+
return $this->twilioService->account->calls->create(
66+
$this->getFrom($message),
67+
$to,
68+
trim($message->content)
69+
);
70+
}
71+
72+
protected function getFrom($message)
73+
{
74+
if (! $from = $message->from ?: $this->from) {
75+
throw CouldNotSendNotification::missingFrom();
76+
}
77+
78+
return $from;
79+
}
80+
}

src/TwilioCallMessage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace NotificationChannels\Twilio;
44

5-
class TwilioCallMessage extends TwilioAbstractMessage
5+
class TwilioCallMessage extends TwilioMessage
66
{
77
/**
88
* Set the message url.

src/TwilioChannel.php

Lines changed: 18 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,29 @@
44

55
use Exception;
66
use Illuminate\Notifications\Notification;
7-
use Illuminate\Events\Dispatcher;
7+
use Illuminate\Contracts\Events\Dispatcher;
88
use NotificationChannels\Twilio\Exceptions\CouldNotSendNotification;
99
use Illuminate\Notifications\Events\NotificationFailed;
10-
use Services_Twilio;
1110

1211
class TwilioChannel
1312
{
1413
/**
15-
* @var \Services_Twilio
14+
* @var Twilio
1615
*/
1716
protected $twilio;
1817

1918
/**
20-
* @var \Illuminate\Events\Dispatcher
19+
* @var Dispatcher
2120
*/
22-
private $events;
21+
protected $events;
2322

2423
/**
2524
* TwilioChannel constructor.
2625
*
27-
* @param Services_Twilio $twilio
28-
* @param Dispatcher $events
26+
* @param Twilio $twilio
27+
* @param Dispatcher $events
2928
*/
30-
public function __construct(Services_Twilio $twilio, Dispatcher $events)
29+
public function __construct(Twilio $twilio, Dispatcher $events)
3130
{
3231
$this->twilio = $twilio;
3332
$this->events = $events;
@@ -36,68 +35,42 @@ public function __construct(Services_Twilio $twilio, Dispatcher $events)
3635
/**
3736
* Send the given notification.
3837
*
39-
* @param mixed $notifiable
40-
* @param \Illuminate\Notifications\Notification $notification
38+
* @param mixed $notifiable
39+
* @param \Illuminate\Notifications\Notification $notification
4140
* @return mixed
4241
* @throws CouldNotSendNotification
4342
*/
4443
public function send($notifiable, Notification $notification)
4544
{
46-
if (! $to = $notifiable->routeNotificationFor('twilio')) {
47-
if (! $to = $notifiable->phone_number) {
48-
return;
49-
}
50-
}
51-
5245
try {
46+
$to = $this->getTo($notifiable);
5347
$message = $notification->toTwilio($notifiable);
5448

5549
if (is_string($message)) {
5650
$message = new TwilioSmsMessage($message);
5751
}
5852

59-
if (! $message instanceof TwilioAbstractMessage) {
53+
if (! $message instanceof TwilioMessage) {
6054
throw CouldNotSendNotification::invalidMessageObject($message);
6155
}
6256

63-
if (! $from = $message->from ?: config('services.twilio.from')) {
64-
throw CouldNotSendNotification::missingFrom();
65-
}
66-
67-
return $this->sendMessage($message, $from, $to);
57+
return $this->twilio->sendMessage($message, $to);
6858
} catch (Exception $exception) {
6959
$this->events->fire(
7060
new NotificationFailed($notifiable, $notification, 'twilio', ['message' => $exception->getMessage()])
7161
);
7262
}
7363
}
7464

75-
/**
76-
* @param $message
77-
* @param $from
78-
* @param $to
79-
* @return mixed
80-
*
81-
* @throws \NotificationChannels\Twilio\Exceptions\CouldNotSendNotification
82-
*/
83-
protected function sendMessage($message, $from, $to)
65+
protected function getTo($notifiable)
8466
{
85-
if ($message instanceof TwilioSmsMessage) {
86-
return $this->twilio->account->messages->sendMessage(
87-
$from,
88-
$to,
89-
trim($message->content)
90-
);
67+
if ($notifiable->routeNotificationFor('twilio')) {
68+
return $notifiable->routeNotificationFor('twilio');
9169
}
92-
93-
if ($message instanceof TwilioCallMessage) {
94-
return $this->twilio->account->calls->create(
95-
$from,
96-
$to,
97-
trim($message->content)
98-
);
70+
if (isset($notifiable->phone_number)) {
71+
return $notifiable->phone_number;
9972
}
10073

101-
throw CouldNotSendNotification::invalidMessageObject($message);
74+
throw CouldNotSendNotification::invalidReceiver();
10275
}
10376
}

src/TwilioAbstractMessage.php renamed to src/TwilioMessage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace NotificationChannels\Twilio;
44

5-
abstract class TwilioAbstractMessage
5+
abstract class TwilioMessage
66
{
77
/**
88
* The message content.

src/TwilioProvider.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace NotificationChannels\Twilio;
44

55
use Illuminate\Support\ServiceProvider;
6+
use Services_Twilio as TwilioService;
67

78
class TwilioProvider extends ServiceProvider
89
{
@@ -12,13 +13,16 @@ class TwilioProvider extends ServiceProvider
1213
public function boot()
1314
{
1415
$this->app->when(TwilioChannel::class)
15-
->needs(\Services_Twilio::class)
16+
->needs(Twilio::class)
1617
->give(function () {
17-
$config = config('services.twilio');
18+
$config = $this->app['config']['services.twilio'];
1819

19-
return new \Services_Twilio(
20-
$config['account_sid'],
21-
$config['auth_token']
20+
return new Twilio(
21+
$this->app->make(TwilioService::class, [
22+
$config['account_sid'],
23+
$config['auth_token'],
24+
]),
25+
$config['from']
2226
);
2327
});
2428
}

src/TwilioSmsMessage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
namespace NotificationChannels\Twilio;
44

5-
class TwilioSmsMessage extends TwilioAbstractMessage
5+
class TwilioSmsMessage extends TwilioMessage
66
{
77
}

tests/IntegrationTest.php

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace NotificationChannels\Twilio\Test;
4+
5+
use Illuminate\Contracts\Events\Dispatcher;
6+
use Illuminate\Notifications\Notification;
7+
use Mockery;
8+
use NotificationChannels\Twilio\TwilioCallMessage;
9+
use NotificationChannels\Twilio\TwilioChannel;
10+
use NotificationChannels\Twilio\TwilioSmsMessage;
11+
use PHPUnit_Framework_TestCase;
12+
use NotificationChannels\Twilio\Twilio;
13+
use Services_Twilio as TwilioService;
14+
use Services_Twilio_Rest_Calls;
15+
use Services_Twilio_Rest_Messages;
16+
17+
class IntegrationTest extends PHPUnit_Framework_TestCase
18+
{
19+
/** @var TwilioService */
20+
protected $twilioService;
21+
22+
/** @var Notification */
23+
protected $notification;
24+
25+
/** @var Dispatcher */
26+
protected $events;
27+
28+
public function setUp()
29+
{
30+
parent::setUp();
31+
32+
$this->twilioService = Mockery::mock(TwilioService::class);
33+
$this->twilioService->account = new \stdClass();
34+
$this->twilioService->account->messages = Mockery::mock(Services_Twilio_Rest_Messages::class);
35+
$this->twilioService->account->calls = Mockery::mock(Services_Twilio_Rest_Calls::class);
36+
37+
$this->events = Mockery::mock(Dispatcher::class);
38+
$this->notification = Mockery::mock(Notification::class);
39+
}
40+
41+
/** @test */
42+
public function it_can_send_a_sms_message()
43+
{
44+
$message = TwilioSmsMessage::create('Message text');
45+
$this->notification->shouldReceive('toTwilio')->andReturn($message);
46+
47+
$twilio = new Twilio($this->twilioService, '+31612345678');
48+
49+
$channel = new TwilioChannel($twilio, $this->events);
50+
51+
$this->smsMessageWillBeSentToTwilioWith('+31612345678', '+22222222222', 'Message text');
52+
53+
$channel->send(new NotifiableWithAttribute(), $this->notification);
54+
}
55+
56+
/** @test */
57+
public function it_can_make_a_call()
58+
{
59+
$message = TwilioCallMessage::create('http://example.com');
60+
$this->notification->shouldReceive('toTwilio')->andReturn($message);
61+
62+
$twilio = new Twilio($this->twilioService, '+31612345678');
63+
64+
$channel = new TwilioChannel($twilio, $this->events);
65+
66+
$this->callWillBeSentToTwilioWith('+31612345678', '+22222222222', 'http://example.com');
67+
68+
$channel->send(new NotifiableWithAttribute(), $this->notification);
69+
}
70+
71+
protected function smsMessageWillBeSentToTwilioWith($from, $to, $message)
72+
{
73+
$this->twilioService->account->messages->shouldReceive('sendMessage')
74+
->atLeast()->once()
75+
->with($from, $to, $message)
76+
->andReturn(true);
77+
}
78+
79+
protected function callWillBeSentToTwilioWith($from, $to, $url)
80+
{
81+
$this->twilioService->account->calls->shouldReceive('create')
82+
->atLeast()->once()
83+
->with($from, $to, $url)
84+
->andReturn(true);
85+
}
86+
}

0 commit comments

Comments
 (0)