Skip to content

Commit

Permalink
Fix broken apns background message data detection
Browse files Browse the repository at this point in the history
  • Loading branch information
Marc Espiard authored and jeromegamez committed Jan 27, 2023
1 parent cb66574 commit f7e6074
Show file tree
Hide file tree
Showing 4 changed files with 316 additions and 5 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## [Unreleased]

### Fixed

* Cloud Messaging: The APNS `content-available` payload field was not set correctly when a message contained
message data at the root level, but not at the APNS config level.
([#762](https://github.com/kreait/firebase-php/pull/762))

## [7.0.1] - 2023-01-24

### Fixed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ public function __invoke(Message $message): Message
$messageData = $this->getMessageData($payload);
$apnsData = $apnsConfig->data();

if ($apnsData === []) {
// No data, no 'content-available' field
return $message;
}
$hasData = $messageData->toArray() !== [] || $apnsData !== [];

if ($messageData->toArray() === []) {
if (!$hasData) {
// No data, no 'content-available' field
return $message;
}
Expand Down
118 changes: 118 additions & 0 deletions tests/Unit/Messaging/Processor/SetApnsContentAvailableIfNeededTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php

declare(strict_types=1);

namespace Kreait\Firebase\Tests\Unit\Messaging\Processor;

use Beste\Json;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Message;
use Kreait\Firebase\Messaging\Processor\SetApnsContentAvailableIfNeeded;
use PHPUnit\Framework\TestCase;

/**
* @internal
*/
final class SetApnsContentAvailableIfNeededTest extends TestCase
{
private SetApnsContentAvailableIfNeeded $processor;

protected function setUp(): void
{
$this->processor = new SetApnsContentAvailableIfNeeded();
}

/**
* @dataProvider provideMessagesWithExpectedContentAvailable
*
* @param array<mixed> $messageData
*
* @see https://github.com/kreait/firebase-php/pull/762
*/
public function testItSetsTheExpectedPushType(bool $expected, array $messageData): void
{
$message = CloudMessage::fromArray($messageData);

$processed = Json::decode(Json::encode(($this->processor)($message)), true);

if ($expected === true) {
$this->assertTrue(isset($processed['apns']['payload']['aps']['content-available']));
$this->assertSame(1, $processed['apns']['payload']['aps']['content-available']);
} else {
$this->assertFalse(isset($processed['apns']['payload']['aps']['content-available']));
}
}

/**
* @return iterable<string, array{0: bool, 1: array<mixed>}>
*/
public function provideMessagesWithExpectedContentAvailable(): iterable
{
yield 'message data at root level -> true' => [
true,
[
'data' => [
'key' => 'value',
],
],
];

yield 'message data at apns level -> true' => [
true,
[
'apns' => [
'payload' => [
'data' => [
'key' => 'value',
],
],
],
],
];

yield 'both message and apns data -> true' => [
true,
[
'data' => [
'key' => 'value',
],
'apns' => [
'payload' => [
'data' => [
'key' => 'value',
],
],
],
],
];

yield 'no data -> false' => [
false,
[
'data' => [],
'apns' => [
'payload' => [
],
],
],
];
}

/**
* @param non-empty-string $type
*/
private function assertMessageHasPushType(Message $message, string $type): void
{
$processed = Json::decode(Json::encode(($this->processor)($message)), true);

$this->assertTrue(isset($processed['apns']['headers']['apns-push-type']));
$this->assertSame($type, $processed['apns']['headers']['apns-push-type']);
}

private function assertMessageHasNoPushType(Message $message): void
{
$processed = Json::decode(Json::encode(($this->processor)($message)), true);

$this->assertFalse(isset($processed['apns']['headers']['apns-push-type']));
}
}
190 changes: 190 additions & 0 deletions tests/Unit/Messaging/Processor/SetApnsPushTypeIfNeededTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?php

declare(strict_types=1);

namespace Kreait\Firebase\Tests\Unit\Messaging\Processor;

use Beste\Json;
use Kreait\Firebase\Messaging\CloudMessage;
use Kreait\Firebase\Messaging\Message;
use Kreait\Firebase\Messaging\Processor\SetApnsPushTypeIfNeeded;
use PHPUnit\Framework\TestCase;

/**
* @internal
*/
final class SetApnsPushTypeIfNeededTest extends TestCase
{
private SetApnsPushTypeIfNeeded $processor;

protected function setUp(): void
{
$this->processor = new SetApnsPushTypeIfNeeded();
}

/**
* @dataProvider provideMessagesWithExpectedPushType
*
* @param non-empty-string|null $expected
* @param array<mixed> $messageData
*/
public function testItSetsTheExpectedPushType(?string $expected, array $messageData): void
{
$message = CloudMessage::fromArray($messageData);

if ($expected === null) {
$this->assertMessageHasNoPushType($message);
} else {
$this->assertMessageHasPushType($message, $expected);
}
}

/**
* @return iterable<string, array{0: non-empty-string|null, 1: array<mixed>}>
*/
public function provideMessagesWithExpectedPushType(): iterable
{
yield 'message data at root level -> background' => [
'background',
[
'data' => [
'key' => 'value',
],
],
];

yield 'message data at apns level -> background' => [
'background',
[
'apns' => [
'payload' => [
'data' => [
'key' => 'value',
],
],
],
],
];

yield 'both message and apns data -> background' => [
'background',
[
'data' => [
'key' => 'value',
],
'apns' => [
'payload' => [
'data' => [
'key' => 'value',
],
],
],
],
];

yield 'notification at root level -> alert' => [
'alert',
[
'notification' => [
'title' => 'Alert',
],
],
];

yield 'notification at apns level -> alert' => [
'alert',
[
'apns' => [
'payload' => [
'aps' => [
'alert' => [
'title' => 'Alert',
],
],
],
],
],
];

yield 'notification both at root apns level -> alert' => [
'alert',
[
'notification' => [
'title' => 'Alert',
],
'apns' => [
'payload' => [
'aps' => [
'alert' => [
'title' => 'Alert',
],
],
],
],
],
];

yield 'data at root, notification at apns level -> alert' => [
'alert',
[
'data' => [
'key' => 'value',
],
'apns' => [
'payload' => [
'aps' => [
'alert' => [
'title' => 'Alert',
],
],
],
],
],
];

yield 'notification at root, data at apns level -> alert' => [
'alert',
[
'notification' => [
'title' => 'Alert',
],
'apns' => [
'payload' => [
'data' => [
'key' => 'value',
],
],
],
],
];

yield 'no data -> none' => [
null,
[
'data' => [],
'apns' => [
'payload' => [
],
],
],
];
}

/**
* @param non-empty-string $type
*/
private function assertMessageHasPushType(Message $message, string $type): void
{
$processed = Json::decode(Json::encode(($this->processor)($message)), true);

$this->assertTrue(isset($processed['apns']['headers']['apns-push-type']));
$this->assertSame($type, $processed['apns']['headers']['apns-push-type']);
}

private function assertMessageHasNoPushType(Message $message): void
{
$processed = Json::decode(Json::encode(($this->processor)($message)), true);

$this->assertFalse(isset($processed['apns']['headers']['apns-push-type']));
}
}

0 comments on commit f7e6074

Please sign in to comment.