Skip to content

Commit 071a56e

Browse files
committed
Add feature tests, controller, and make all tests pass
1 parent 4abd36a commit 071a56e

File tree

9 files changed

+237
-7
lines changed

9 files changed

+237
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
/.phive/
33
/tools/
44

5+
.idea

composer.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66
"require": {
77
"php": ">=7.3",
88
"ext-json": "*",
9-
"aws/aws-php-sns-message-validator": "^1.6",
10-
"orchestra/testbench": "^6.0"
9+
"aws/aws-php-sns-message-validator": "^1.6"
10+
1111
},
1212
"require-dev" : {
1313
"phpunit/phpunit": "^9.5",
1414
"roave/security-advisories": "dev-latest",
15-
"guzzlehttp/guzzle": "^7.2"
15+
"guzzlehttp/guzzle": "^7.2",
16+
"orchestra/testbench": "^6.0"
1617
},
1718
"autoload-dev": {
1819
"psr-4": {

config/sns-handler.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
return [
4+
'sns-class-map' => []
5+
];

routes/api.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
use Illuminate\Support\Facades\Route;
3+
use MiamiOH\SnsHandler\Controllers\SnsMessageController;
4+
5+
Route::post('/sns/message', [SnsMessageController::class, 'handle']);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
namespace MiamiOH\SnsHandler\Controllers;
4+
5+
use Illuminate\Http\Request;
6+
use Illuminate\Routing\Controller;
7+
use MiamiOH\SnsHandler\SnsBroker;
8+
use MiamiOH\SnsHandler\SnsConfirmSubscriptionException;
9+
use MiamiOH\SnsHandler\SnsException;
10+
use MiamiOH\SnsHandler\SnsHttpRequest;
11+
use MiamiOH\SnsHandler\SnsUnknownTopicArnException;
12+
13+
14+
class SnsMessageController extends Controller
15+
{
16+
/**
17+
* @var SnsBroker
18+
*/
19+
private $snsBroker;
20+
21+
public function __construct(SnsBroker $snsBroker)
22+
{
23+
$this->snsBroker = $snsBroker;
24+
}
25+
26+
public function handle(SnsHttpRequest $request)
27+
{
28+
try {
29+
$this->snsBroker->handleRequest($request);
30+
} catch (SnsUnknownTopicArnException $e) {
31+
return response(null, 404);
32+
} catch (SnsConfirmSubscriptionException $e) {
33+
return response(null, 502);
34+
} catch (SnsException $e) {
35+
return response(null, 500);
36+
}
37+
38+
return response()->json();
39+
}
40+
}

src/ServiceProvider.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
4+
namespace MiamiOH\SnsHandler;
5+
6+
7+
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
8+
use MiamiOH\SnsHandler\Controllers\SnsMessageController;
9+
10+
class ServiceProvider extends BaseServiceProvider
11+
{
12+
private $configPath = __DIR__ . '/../config/sns-handler.php';
13+
14+
public function boot()
15+
{
16+
$this->loadRoutesFrom(__DIR__ . '/../routes/api.php');
17+
$this->publishes([
18+
$this->configPath => config_path('sns-handler.php'),
19+
]);
20+
}
21+
22+
/**
23+
* Register the application services.
24+
*
25+
* @return void
26+
*/
27+
public function register()
28+
{
29+
$this->app->make(SnsMessageController::class);
30+
$this->mergeConfigFrom($this->configPath, 'sns-handler');
31+
$this->app->bind(SnsTopicMapper::class, function () {
32+
return new SnsTopicMapper(config('sns-handler.sns-class-map', []));
33+
});
34+
}
35+
}

src/SnsHttpRequest.php

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,35 @@
11
<?php
22

3-
43
namespace MiamiOH\SnsHandler;
54

6-
interface SnsHttpRequest
5+
use Illuminate\Foundation\Http\FormRequest;
6+
7+
class SnsHttpRequest extends FormRequest
78
{
8-
public function jsonContent(): string;
9+
/**
10+
* Determine if the user is authorized to make this request.
11+
*
12+
* @return bool
13+
*/
14+
public function authorize()
15+
{
16+
return true;
17+
}
18+
19+
/**
20+
* Get the validation rules that apply to the request.
21+
*
22+
* @return array
23+
*/
24+
public function rules()
25+
{
26+
return [
27+
//
28+
];
29+
}
30+
31+
public function jsonContent(): string
32+
{
33+
return $this->content;
34+
}
935
}

tests/Feature/SnsHandlerTest.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<?php
2+
3+
4+
namespace Tests\MiamiOH\SnsHandler\Feature;
5+
6+
use Aws\Sns\MessageValidator;
7+
use Illuminate\Http\Client\Request;
8+
use Illuminate\Support\Facades\Http;
9+
use MiamiOH\SnsHandler\NullMessageValidator;
10+
use MiamiOH\SnsHandler\ServiceProvider;
11+
use MiamiOH\SnsHandler\SnsMessage;
12+
use Tests\MiamiOH\SnsHandler\MakesSnsTests;
13+
use Tests\MiamiOH\SnsHandler\Unit\SnsMessageHandlerStub;
14+
15+
16+
class SnsHandlerTest extends \Tests\MiamiOH\SnsHandler\TestCase
17+
{
18+
use MakesSnsTests;
19+
20+
public function setUp(): void
21+
{
22+
parent::setUp();
23+
$this->app->bind(MessageValidator::class, NullMessageValidator::class);
24+
}
25+
26+
protected function getEnvironmentSetUp($app)
27+
{
28+
$app['config']->set('sns-handler.sns-class-map', [
29+
'arn:aws:sns:us-west-2:123456789012:MyTopic' => SnsMessageHandlerStub::class,
30+
]);
31+
}
32+
33+
protected function getPackageProviders($app)
34+
{
35+
return [ServiceProvider::class];
36+
}
37+
38+
public function testReturnsNotFoundForUnknownTopicArn(): void
39+
{
40+
41+
42+
$data = $this->makeSnsMessageData([
43+
'Type' => SnsMessage::NOTIFICATION_TYPE,
44+
'TopicArn' => 'arn:aws:sns:us-west-2:123456789012:Unknown',
45+
]);
46+
$response = $this->postJson('/sns/message', $data);
47+
48+
$this->assertEquals(404, $response->status());
49+
}
50+
51+
public function testConfirmsSubscriptionForKnownTopicArn(): void
52+
{
53+
Http::fake();
54+
55+
$data = $this->makeSnsMessageData([
56+
'Type' => SnsMessage::SUBSCRIBE_TYPE,
57+
'Message' => json_encode(['id' => 123, 'color' => 'red'], true),
58+
'SubscribeURL' => 'https://aws.amazon.com/sns/register/abc123'
59+
]);
60+
61+
$this->postJson('/sns/message', $data);
62+
63+
Http::assertSent(function (Request $request) {
64+
return $request->url() === 'https://aws.amazon.com/sns/register/abc123';
65+
});
66+
}
67+
68+
public function testRespondsWithOkAfterConfirmsSubscription(): void
69+
{
70+
Http::fake();
71+
72+
$data = $this->makeSnsMessageData([
73+
'Type' => SnsMessage::SUBSCRIBE_TYPE,
74+
'Message' => json_encode(['id' => 123, 'color' => 'red'], true),
75+
'SubscribeURL' => 'https://aws.amazon.com/sns/register/abc123'
76+
]);
77+
78+
$response = $this->postJson('/sns/message', $data);
79+
print_r($response->getContent());
80+
81+
$this->assertEquals(200, $response->status());
82+
}
83+
84+
public function testReturnsBadGatewayResponseIfConfirmationFails(): void
85+
{
86+
Http::fake([
87+
'*' => Http::response(null, 404),
88+
]);
89+
90+
$data = $this->makeSnsMessageData([
91+
'Type' => SnsMessage::SUBSCRIBE_TYPE,
92+
'Message' => json_encode(['id' => 123, 'color' => 'red'], true),
93+
'SubscribeURL' => 'https://aws.amazon.com/sns/register/abc123'
94+
]);
95+
96+
$response = $this->postJson('/sns/message', $data);
97+
98+
$this->assertEquals(502, $response->status());
99+
}
100+
101+
public function testSendsMessageToRegisteredHandler(): void
102+
{
103+
$data = $this->makeSnsMessageData([
104+
'Type' => SnsMessage::NOTIFICATION_TYPE,
105+
'TopicArn' => 'arn:aws:sns:us-west-2:123456789012:MyTopic',
106+
'Message' => 'Test message',
107+
]);
108+
109+
SnsMessageHandlerStub::handleCallback(function (SnsMessage $message) {
110+
$this->assertEquals('Test message', $message->message());
111+
});
112+
113+
$response = $this->postJson('/sns/message', $data);
114+
115+
$this->assertEquals(200, $response->status());
116+
}
117+
}

tests/Unit/SnsBrokerTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public function testThrowsExceptionIfConfirmSubscriptionFails(): void
102102
'Type' => SnsMessage::SUBSCRIBE_TYPE,
103103
'SubscribeURL' => 'https://aws.amazon.com/subscribe/123',
104104
]));
105-
105+
106106
Http::fake([
107107
'https://aws.amazon.com/subscribe/123' => Http::response([], 404, [])
108108
]);

0 commit comments

Comments
 (0)