Skip to content

Commit

Permalink
Add Event Dispatching for Notifications (#12)
Browse files Browse the repository at this point in the history
* remove phpunit & add pestphp

* Drop support for Laravel 8

* update composer scripts & code quality tools

* refactoring

* migrate to pestphp

* Achieved 100% code coverage

* Temporarily revert changes that should be done in another PR

* remove namespace

* add Pest v1 support for Laravel 9

* formatting

* Remove parallel flag for Pest v1

https://github.com/mertasan/onesignal/actions/runs/10187251895/job/28180865729#step:6:33

The Parallel plugin has been moved to the main repo in Pest v2.

* Add missing directories to phpunit.xml

* add Events

* Apply events

* Add tests for Events
  • Loading branch information
mertasan authored Aug 1, 2024
1 parent 7631f7d commit ec53497
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 24 deletions.
34 changes: 14 additions & 20 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="vendor/autoload.php"
backupGlobals="false"
colors="true"
processIsolation="false"
stopOnError="true"
stopOnFailure="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
>
<coverage>
<include>
<directory suffix=".php">./src</directory>
</include>
</coverage>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" colors="true" processIsolation="false" stopOnError="true" stopOnFailure="true" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd">
<testsuites>
<testsuite name="Unit Tests">
<directory>tests/Unit</directory>
</testsuite>
<testsuite name="Feature Tests">
<directory>tests/Feature</directory>
</testsuite>
</testsuites>
<source>
<include>
<directory suffix=".php">./src</directory>
</include>
</source>

<testsuites>
<testsuite name="Laravel Onesignal Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>
25 changes: 25 additions & 0 deletions src/Events/OneSignalNotificationErrorsOccurred.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Macellan\OneSignal\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\SerializesModels;

class OneSignalNotificationErrorsOccurred
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public function __construct(
public mixed $notifiable,
public Notification $notification,
public array $errors,
) {
// .
}
}
24 changes: 24 additions & 0 deletions src/Events/OneSignalNotificationNotSent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Macellan\OneSignal\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\SerializesModels;

class OneSignalNotificationNotSent
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public function __construct(
public mixed $notifiable,
public Notification $notification,
) {
// .
}
}
24 changes: 24 additions & 0 deletions src/Events/OneSignalNotificationSending.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Macellan\OneSignal\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\SerializesModels;

class OneSignalNotificationSending
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public function __construct(
public mixed $notifiable,
public Notification $notification,
) {
// .
}
}
25 changes: 25 additions & 0 deletions src/Events/OneSignalNotificationSent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Macellan\OneSignal\Events;

use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Notifications\Notification;
use Illuminate\Queue\SerializesModels;

class OneSignalNotificationSent
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

public function __construct(
public mixed $notifiable,
public Notification $notification,
public array $response,
) {
// .
}
}
18 changes: 14 additions & 4 deletions src/OneSignalChannel.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Http;
use Macellan\OneSignal\Events\OneSignalNotificationErrorsOccurred;
use Macellan\OneSignal\Events\OneSignalNotificationNotSent;
use Macellan\OneSignal\Events\OneSignalNotificationSending;
use Macellan\OneSignal\Events\OneSignalNotificationSent;
use Macellan\OneSignal\Exceptions\CouldNotSendNotification;

class OneSignalChannel
Expand All @@ -27,7 +31,7 @@ public function __construct(string $appId)
*
* @throws CouldNotSendNotification|\Illuminate\Http\Client\RequestException|\Illuminate\Http\Client\ConnectionException
*/
public function send(mixed $notifiable, Notification $notification): ?object
public function send(mixed $notifiable, Notification $notification): void
{
/**
* @noinspection PhpPossiblePolymorphicInvocationInspection
Expand All @@ -40,9 +44,13 @@ public function send(mixed $notifiable, Notification $notification): ?object
}

if (! $userIds = $notifiable->routeNotificationFor('OneSignal', $notification)) {
return null;
OneSignalNotificationNotSent::dispatch($notifiable, $notification);

return;
}

OneSignalNotificationSending::dispatch($notifiable, $notification);

$result = Http::timeout($this->timeout)
->asJson()->acceptJson()
->post(self::ENDPOINT, [
Expand All @@ -58,16 +66,18 @@ public function send(mixed $notifiable, Notification $notification): ?object

]);

OneSignalNotificationSent::dispatch($notifiable, $notification, $result->json());

if ($requestException = $result->toException()) {
throw $requestException;
}

$errors = $result->json('errors');

if (! empty($errors)) {
OneSignalNotificationErrorsOccurred::dispatch($notifiable, $notification, $errors);

throw CouldNotSendNotification::withErrors($result->body());
}

return $result;
}
}
97 changes: 97 additions & 0 deletions tests/Feature/ChannelEventsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Http;
use Macellan\OneSignal\Events\OneSignalNotificationErrorsOccurred;
use Macellan\OneSignal\Events\OneSignalNotificationNotSent;
use Macellan\OneSignal\Events\OneSignalNotificationSending;
use Macellan\OneSignal\Events\OneSignalNotificationSent;
use Macellan\OneSignal\Exceptions\CouldNotSendNotification;
use Macellan\OneSignal\OneSignalChannel;
use Macellan\OneSignal\Tests\Fixtures\Notifiable;
use Macellan\OneSignal\Tests\Fixtures\Notifications\TestNotification;
use Macellan\OneSignal\Tests\Fixtures\Notifications\TestNotificationByText;
use Macellan\OneSignal\Tests\Fixtures\WrongNotifiable;

test('notification not sent', function () {
Event::fake();

Http::fake([
'api/v1/notifications' => Http::response(),
]);

(new WrongNotifiable)->notify(new TestNotificationByText);

Http::assertNothingSent();

Event::assertDispatched(OneSignalNotificationNotSent::class);
});

test('notification sent', function () {
Event::fake();

Http::fake([
'api/v1/notifications' => Http::response([
'id' => '931082f5-e442-42b1-a951-19e7e45dee39',
'recipients' => 1,
'external_id' => null,
]),
]);

(new Notifiable)->notify(new TestNotification);

Http::assertSent(function (Request $request) {
return $request->url() === OneSignalChannel::ENDPOINT &&
$request['app_id'] === $this->appId &&
$request['include_player_ids'] === ['player_id'] &&
$request['headings'] === ['en' => 'Subject'] &&
$request['contents'] === ['en' => 'Body'] &&
$request['data'] === null;
});

Event::assertNotDispatched(OneSignalNotificationNotSent::class);

Event::assertDispatched(OneSignalNotificationSending::class, static function ($event) {
return $event->notification instanceof TestNotification;
});

Event::assertDispatched(OneSignalNotificationSent::class, static function ($event) {
return $event->response['id'] === '931082f5-e442-42b1-a951-19e7e45dee39';
});

Event::assertNotDispatched(OneSignalNotificationErrorsOccurred::class);
});

test('notification errors occurred', function () {
Event::fake();

Http::fake([
'api/v1/notifications' => Http::response([
'id' => '',
'recipients' => 0,
'errors' => [
'All included players are not subscribed',
],
]),
]);

try {
(new Notifiable)->notify(new TestNotification);
} catch (CouldNotSendNotification $e) {
expect($e->getMessage())
->toContain('{"id":"","recipients":0,"errors":["All included players are not subscribed"]}');
}

Event::assertNotDispatched(OneSignalNotificationNotSent::class);

Event::assertDispatched(OneSignalNotificationSending::class, static function ($event) {
return $event->notification instanceof TestNotification;
});

Event::assertDispatched(OneSignalNotificationSent::class);

Event::assertDispatched(OneSignalNotificationErrorsOccurred::class);
});

0 comments on commit ec53497

Please sign in to comment.